diff --git a/app/assets/javascripts/work_items/components/work_item_todos.vue b/app/assets/javascripts/work_items/components/shared/todos_toggle.vue
similarity index 71%
rename from app/assets/javascripts/work_items/components/work_item_todos.vue
rename to app/assets/javascripts/work_items/components/shared/todos_toggle.vue
index 471dc33cbe29a35148c7b938e714a8038a008bb0..0ce2fc77a0f6e153ead531d6e033765cce289623 100644
--- a/app/assets/javascripts/work_items/components/work_item_todos.vue
+++ b/app/assets/javascripts/work_items/components/shared/todos_toggle.vue
@@ -1,20 +1,17 @@
 <script>
 import { GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
-import { produce } from 'immer';
 
 import { s__ } from '~/locale';
 import { updateGlobalTodoCount } from '~/sidebar/utils';
-import workItemByIidQuery from '../graphql/work_item_by_iid.query.graphql';
-import createWorkItemTodosMutation from '../graphql/create_work_item_todos.mutation.graphql';
-import markDoneWorkItemTodosMutation from '../graphql/mark_done_work_item_todos.mutation.graphql';
+import createWorkItemTodosMutation from '../../graphql/create_work_item_todos.mutation.graphql';
+import markDoneWorkItemTodosMutation from '../../graphql/mark_done_work_item_todos.mutation.graphql';
 
 import {
   TODO_ADD_ICON,
   TODO_DONE_ICON,
   TODO_PENDING_STATE,
   TODO_DONE_STATE,
-  WIDGET_TYPE_CURRENT_USER_TODOS,
-} from '../constants';
+} from '../../constants';
 
 export default {
   i18n: {
@@ -29,15 +26,7 @@ export default {
     GlButton,
   },
   props: {
-    workItemId: {
-      type: String,
-      required: true,
-    },
-    workItemIid: {
-      type: String,
-      required: true,
-    },
-    workItemFullpath: {
+    itemId: {
       type: String,
       required: true,
     },
@@ -46,6 +35,11 @@ export default {
       required: false,
       default: () => [],
     },
+    todosButtonType: {
+      type: String,
+      required: false,
+      default: 'tertiary',
+    },
   },
   data() {
     return {
@@ -73,7 +67,7 @@ export default {
       this.buttonLabel = '';
       let mutation = createWorkItemTodosMutation;
       let inputVariables = {
-        targetId: this.workItemId,
+        targetId: this.itemId,
       };
       if (this.pendingTodo) {
         mutation = markDoneWorkItemTodosMutation;
@@ -114,11 +108,7 @@ export default {
                 id: todo.id,
               });
             }
-
-            this.updateWorkItemCurrentTodosWidgetCache({
-              cache,
-              todos,
-            });
+            this.$emit('todosUpdated', { cache, todos });
           },
         })
         .then(
@@ -146,26 +136,6 @@ export default {
           this.isLoading = false;
         });
     },
-    updateWorkItemCurrentTodosWidgetCache({ cache, todos }) {
-      const query = {
-        query: workItemByIidQuery,
-        variables: { fullPath: this.workItemFullpath, iid: this.workItemIid },
-      };
-
-      const sourceData = cache.readQuery(query);
-
-      const newData = produce(sourceData, (draftState) => {
-        const { widgets } = draftState.workspace.workItem;
-
-        const widgetCurrentUserTodos = widgets.find(
-          (widget) => widget.type === WIDGET_TYPE_CURRENT_USER_TODOS,
-        );
-
-        widgetCurrentUserTodos.currentUserTodos.nodes = todos;
-      });
-
-      cache.writeQuery({ ...query, data: newData });
-    },
   },
 };
 </script>
@@ -175,7 +145,7 @@ export default {
     v-gl-tooltip.hover
     :disabled="isLoading"
     :title="buttonLabel"
-    category="secondary"
+    :category="todosButtonType"
     class="btn-icon"
     :aria-label="buttonLabel"
     @click="onToggle"
diff --git a/app/assets/javascripts/work_items/components/work_item_detail.vue b/app/assets/javascripts/work_items/components/work_item_detail.vue
index 939e3d6defb5a8cbc54e1a5c844dcafeaccccc88..0cb008de6f9a38c936ea28ecbf8382e9f2dac175 100644
--- a/app/assets/javascripts/work_items/components/work_item_detail.vue
+++ b/app/assets/javascripts/work_items/components/work_item_detail.vue
@@ -37,6 +37,7 @@ import workItemByIidQuery from '../graphql/work_item_by_iid.query.graphql';
 import getAllowedWorkItemChildTypes from '../graphql/work_item_allowed_children.query.graphql';
 import workspacePermissionsQuery from '../graphql/workspace_permissions.query.graphql';
 import { findHierarchyWidgetDefinition } from '../utils';
+import { updateWorkItemCurrentTodosWidget } from '../graphql/cache_utils';
 
 import getWorkItemDesignListQuery from './design_management/graphql/design_collection.query.graphql';
 import uploadDesignMutation from './design_management/graphql/upload_design.mutation.graphql';
@@ -51,7 +52,7 @@ import {
 
 import WorkItemTree from './work_item_links/work_item_tree.vue';
 import WorkItemActions from './work_item_actions.vue';
-import WorkItemTodos from './work_item_todos.vue';
+import TodosToggle from './shared/todos_toggle.vue';
 import WorkItemNotificationsWidget from './work_item_notifications_widget.vue';
 import WorkItemAttributesWrapper from './work_item_attributes_wrapper.vue';
 import WorkItemCreatedUpdated from './work_item_created_updated.vue';
@@ -86,7 +87,7 @@ export default {
     GlButton,
     GlEmptyState,
     WorkItemActions,
-    WorkItemTodos,
+    TodosToggle,
     WorkItemNotificationsWidget,
     WorkItemCreatedUpdated,
     WorkItemDescription,
@@ -628,6 +629,14 @@ export default {
       this.resetFilesToBeSaved();
       this.designUploadError = UPLOAD_DESIGN_ERROR_MESSAGE;
     },
+    updateWorkItemCurrentTodosWidgetCache({ cache, todos }) {
+      updateWorkItemCurrentTodosWidget({
+        cache,
+        todos,
+        fullPath: this.workItemFullPath,
+        iid: this.workItemIid,
+      });
+    },
   },
   WORK_ITEM_TYPE_VALUE_OBJECTIVE,
   WORKSPACE_PROJECT,
@@ -658,6 +667,7 @@ export default {
       @toggleEditMode="enableEditMode"
       @workItemStateUpdated="$emit('workItemStateUpdated')"
       @toggleReportAbuseModal="toggleReportAbuseModal"
+      @todosUpdated="updateWorkItemCurrentTodosWidgetCache"
     />
     <section class="work-item-view">
       <section v-if="updateError" class="flash-container flash-container-page sticky">
@@ -708,12 +718,12 @@ export default {
               >
                 {{ __('Edit') }}
               </gl-button>
-              <work-item-todos
+              <todos-toggle
                 v-if="showWorkItemCurrentUserTodos"
-                :work-item-id="workItem.id"
-                :work-item-iid="workItemIid"
-                :work-item-fullpath="workItemFullPath"
+                :item-id="workItem.id"
                 :current-user-todos="currentUserTodos"
+                :todos-button-type="'secondary'"
+                @todosUpdated="updateWorkItemCurrentTodosWidgetCache"
                 @error="updateError = $event"
               />
               <work-item-notifications-widget
diff --git a/app/assets/javascripts/work_items/components/work_item_sticky_header.vue b/app/assets/javascripts/work_items/components/work_item_sticky_header.vue
index 5dc2122caffdb4c59a9aa14b435cfd1afd037b83..11d645c1f493bb9b7c2400b09afdfcdc9c8affca 100644
--- a/app/assets/javascripts/work_items/components/work_item_sticky_header.vue
+++ b/app/assets/javascripts/work_items/components/work_item_sticky_header.vue
@@ -6,7 +6,7 @@ import ConfidentialityBadge from '~/vue_shared/components/confidentiality_badge.
 import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
 import { isNotesWidget } from '../utils';
 import WorkItemActions from './work_item_actions.vue';
-import WorkItemTodos from './work_item_todos.vue';
+import TodosToggle from './shared/todos_toggle.vue';
 import WorkItemStateBadge from './work_item_state_badge.vue';
 import WorkItemNotificationsWidget from './work_item_notifications_widget.vue';
 
@@ -16,7 +16,7 @@ export default {
     GlIntersectionObserver,
     GlLoadingIcon,
     WorkItemActions,
-    WorkItemTodos,
+    TodosToggle,
     ConfidentialityBadge,
     WorkItemStateBadge,
     WorkItemNotificationsWidget,
@@ -141,13 +141,13 @@ export default {
           >
             {{ __('Edit') }}
           </gl-button>
-          <work-item-todos
+          <todos-toggle
             v-if="showWorkItemCurrentUserTodos"
-            :work-item-id="workItem.id"
-            :work-item-iid="workItem.iid"
-            :work-item-fullpath="projectFullPath"
+            :item-id="workItem.id"
             :current-user-todos="currentUserTodos"
-            @error="$emit('error')"
+            :todos-button-type="'secondary'"
+            @todosUpdated="$emit('todosUpdated', $event)"
+            @error="updateError = $event"
           />
           <work-item-notifications-widget
             v-if="newTodoAndNotificationsEnabled"
diff --git a/app/assets/javascripts/work_items/graphql/cache_utils.js b/app/assets/javascripts/work_items/graphql/cache_utils.js
index e6a73c677af8efd1289893cf79ba1f4ce81df9b1..5ccc5cc3480560d07591a40c66c498fa92d1a9b8 100644
--- a/app/assets/javascripts/work_items/graphql/cache_utils.js
+++ b/app/assets/javascripts/work_items/graphql/cache_utils.js
@@ -33,6 +33,7 @@ import {
   WIDGET_TYPE_DESCRIPTION,
   WIDGET_TYPE_CRM_CONTACTS,
   NEW_WORK_ITEM_IID,
+  WIDGET_TYPE_CURRENT_USER_TODOS,
 } from '../constants';
 import workItemByIidQuery from './work_item_by_iid.query.graphql';
 import getWorkItemTreeQuery from './work_item_tree.query.graphql';
@@ -266,6 +267,30 @@ export const updateParent = ({ cache, fullPath, iid, workItem }) => {
   });
 };
 
+export const updateWorkItemCurrentTodosWidget = ({ cache, fullPath, iid, todos }) => {
+  const query = {
+    query: workItemByIidQuery,
+    variables: { fullPath, iid },
+  };
+
+  const sourceData = cache.readQuery(query);
+
+  if (!sourceData) {
+    return;
+  }
+
+  const newData = produce(sourceData, (draftState) => {
+    const { widgets } = draftState.workspace.workItem;
+    const widgetCurrentUserTodos = widgets.find(
+      (widget) => widget.type === WIDGET_TYPE_CURRENT_USER_TODOS,
+    );
+
+    widgetCurrentUserTodos.currentUserTodos.nodes = todos;
+  });
+
+  cache.writeQuery({ ...query, data: newData });
+};
+
 export const setNewWorkItemCache = async (
   fullPath,
   widgetDefinitions,
diff --git a/spec/frontend/work_items/components/work_item_todos_spec.js b/spec/frontend/work_items/components/shared/todos_toggle_spec.js
similarity index 79%
rename from spec/frontend/work_items/components/work_item_todos_spec.js
rename to spec/frontend/work_items/components/shared/todos_toggle_spec.js
index 90de213a5d176c68507ba87006fd30858502855e..4ec0ec6ae4d2da65b5dfbd836f1d2df7c1839c65 100644
--- a/spec/frontend/work_items/components/work_item_todos_spec.js
+++ b/spec/frontend/work_items/components/shared/todos_toggle_spec.js
@@ -6,7 +6,7 @@ import createMockApollo from 'helpers/mock_apollo_helper';
 import waitForPromises from 'helpers/wait_for_promises';
 import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
 
-import WorkItemTodos from '~/work_items/components/work_item_todos.vue';
+import TodosToggle from '~/work_items/components/shared/todos_toggle.vue';
 import {
   TODO_DONE_ICON,
   TODO_ADD_ICON,
@@ -16,9 +16,8 @@ import {
 import { updateGlobalTodoCount } from '~/sidebar/utils';
 import createWorkItemTodosMutation from '~/work_items/graphql/create_work_item_todos.mutation.graphql';
 import markDoneWorkItemTodosMutation from '~/work_items/graphql/mark_done_work_item_todos.mutation.graphql';
-import workItemByIidQuery from '~/work_items/graphql/work_item_by_iid.query.graphql';
 
-import { workItemResponseFactory, getTodosMutationResponse } from '../mock_data';
+import { workItemResponseFactory, getTodosMutationResponse } from '../../mock_data';
 
 jest.mock('~/sidebar/utils');
 
@@ -33,8 +32,6 @@ describe('WorkItemTodo component', () => {
   const errorMessage = 'Failed to add item';
   const workItemQueryResponse = workItemResponseFactory({ canUpdate: true });
   const mockWorkItemId = workItemQueryResponse.data.workItem.id;
-  const mockWorkItemIid = workItemQueryResponse.data.workItem.iid;
-  const mockWorkItemFullpath = workItemQueryResponse.data.workItem.namespace.fullPath;
 
   const createTodoSuccessHandler = jest
     .fn()
@@ -60,29 +57,16 @@ describe('WorkItemTodo component', () => {
     mutation = createWorkItemTodosMutation,
     currentUserTodosHandler = createTodoSuccessHandler,
     currentUserTodos = [],
+    todosButtonType = 'tertiary',
   } = {}) => {
     const mockApolloProvider = createMockApollo([[mutation, currentUserTodosHandler]]);
 
-    mockApolloProvider.clients.defaultClient.cache.writeQuery({
-      query: workItemByIidQuery,
-      variables: { fullPath: mockWorkItemFullpath, iid: mockWorkItemIid },
-      data: {
-        ...workItemQueryResponse.data,
-        workspace: {
-          __typename: 'Project',
-          id: 'gid://gitlab/Project/1',
-          workItem: workItemQueryResponse.data.workItem,
-        },
-      },
-    });
-
-    wrapper = shallowMountExtended(WorkItemTodos, {
+    wrapper = shallowMountExtended(TodosToggle, {
       apolloProvider: mockApolloProvider,
       propsData: {
-        workItemId: mockWorkItemId,
-        workItemIid: mockWorkItemIid,
-        workItemFullpath: mockWorkItemFullpath,
+        itemId: mockWorkItemId,
         currentUserTodos,
+        todosButtonType,
       },
     });
   };
@@ -93,6 +77,7 @@ describe('WorkItemTodo component', () => {
     expect(findTodoWidget().exists()).toBe(true);
     expect(findTodoIcon().props('name')).toEqual(TODO_ADD_ICON);
     expect(findTodoIcon().classes('!gl-fill-blue-500')).toBe(false);
+    expect(findTodoWidget().props('category')).toBe('tertiary');
   });
 
   it('renders mark as done button when there is pending item', () => {
@@ -105,12 +90,12 @@ describe('WorkItemTodo component', () => {
   });
 
   it.each`
-    assertionName  | mutation                         | currentUserTodosHandler       | currentUserTodos          | inputVariables
-    ${'create'}    | ${createWorkItemTodosMutation}   | ${createTodoSuccessHandler}   | ${[]}                     | ${inputVariablesCreateTodos}
-    ${'mark done'} | ${markDoneWorkItemTodosMutation} | ${markDoneTodoSuccessHandler} | ${[mockCurrentUserTodos]} | ${inputVariablesMarkDoneTodos}
+    assertionName  | mutation                         | currentUserTodosHandler       | currentUserTodos          | inputVariables                 | todos
+    ${'create'}    | ${createWorkItemTodosMutation}   | ${createTodoSuccessHandler}   | ${[]}                     | ${inputVariablesCreateTodos}   | ${[{ id: expect.anything() }]}
+    ${'mark done'} | ${markDoneWorkItemTodosMutation} | ${markDoneTodoSuccessHandler} | ${[mockCurrentUserTodos]} | ${inputVariablesMarkDoneTodos} | ${[]}
   `(
     'calls $assertionName todos mutation when to do button is toggled',
-    async ({ mutation, currentUserTodosHandler, currentUserTodos, inputVariables }) => {
+    async ({ mutation, currentUserTodosHandler, currentUserTodos, inputVariables, todos }) => {
       createComponent({
         mutation,
         currentUserTodosHandler,
@@ -124,10 +109,22 @@ describe('WorkItemTodo component', () => {
       expect(currentUserTodosHandler).toHaveBeenCalledWith({
         input: inputVariables,
       });
+      expect(wrapper.emitted('todosUpdated')[0][0]).toMatchObject({
+        cache: expect.anything(),
+        todos,
+      });
       expect(updateGlobalTodoCount).toHaveBeenCalled();
     },
   );
 
+  it('renders secondary button when `todosButtonType` is secondary', () => {
+    createComponent({
+      todosButtonType: 'secondary',
+    });
+
+    expect(findTodoWidget().props('category')).toBe('secondary');
+  });
+
   it('emits error when the update mutation fails', async () => {
     createComponent({
       currentUserTodosHandler: failureHandler,
diff --git a/spec/frontend/work_items/components/work_item_detail_spec.js b/spec/frontend/work_items/components/work_item_detail_spec.js
index d1c11ed05c845cb9a086a1abe1ca7f84f6f338f7..d368664cb53dd9921a8969a0e091bdcb8b65a4ce 100644
--- a/spec/frontend/work_items/components/work_item_detail_spec.js
+++ b/spec/frontend/work_items/components/work_item_detail_spec.js
@@ -21,7 +21,7 @@ import WorkItemDetailModal from '~/work_items/components/work_item_detail_modal.
 import WorkItemStickyHeader from '~/work_items/components/work_item_sticky_header.vue';
 import WorkItemTitle from '~/work_items/components/work_item_title.vue';
 import WorkItemAbuseModal from '~/work_items/components/work_item_abuse_modal.vue';
-import WorkItemTodos from '~/work_items/components/work_item_todos.vue';
+import TodosToggle from '~/work_items/components/shared/todos_toggle.vue';
 import DesignWidget from '~/work_items/components/design_management/design_management_widget.vue';
 import DesignUploadButton from '~/work_items/components//design_management/upload_button.vue';
 import uploadDesignMutation from '~/work_items/components/design_management/graphql/upload_design.mutation.graphql';
@@ -113,7 +113,7 @@ describe('WorkItemDetail component', () => {
   const findNotesWidget = () => wrapper.findComponent(WorkItemNotes);
   const findModal = () => wrapper.findComponent(WorkItemDetailModal);
   const findWorkItemAbuseModal = () => wrapper.findComponent(WorkItemAbuseModal);
-  const findWorkItemTodos = () => wrapper.findComponent(WorkItemTodos);
+  const findTodosToggle = () => wrapper.findComponent(TodosToggle);
   const findStickyHeader = () => wrapper.findComponent(WorkItemStickyHeader);
   const findWorkItemTwoColumnViewContainer = () => wrapper.findByTestId('work-item-overview');
   const findRightSidebar = () => wrapper.findByTestId('work-item-overview-right-sidebar');
@@ -245,7 +245,7 @@ describe('WorkItemDetail component', () => {
     });
 
     it('renders todos widget if logged in', () => {
-      expect(findWorkItemTodos().exists()).toBe(true);
+      expect(findTodosToggle().exists()).toBe(true);
     });
 
     it('calls the work item updated subscription', () => {
@@ -816,7 +816,7 @@ describe('WorkItemDetail component', () => {
     });
 
     it('does not renders if not logged in', () => {
-      expect(findWorkItemTodos().exists()).toBe(false);
+      expect(findTodosToggle().exists()).toBe(false);
     });
   });
 
diff --git a/spec/frontend/work_items/components/work_item_sticky_header_spec.js b/spec/frontend/work_items/components/work_item_sticky_header_spec.js
index 07a2204d1f665263b682dfc1c0a83415d0bfd8c9..19af66ac1f78e47bcfcbaba64aa491cc6db1687d 100644
--- a/spec/frontend/work_items/components/work_item_sticky_header_spec.js
+++ b/spec/frontend/work_items/components/work_item_sticky_header_spec.js
@@ -7,7 +7,7 @@ import LockedBadge from '~/issuable/components/locked_badge.vue';
 import WorkItemStickyHeader from '~/work_items/components/work_item_sticky_header.vue';
 import ConfidentialityBadge from '~/vue_shared/components/confidentiality_badge.vue';
 import WorkItemActions from '~/work_items/components/work_item_actions.vue';
-import WorkItemTodos from '~/work_items/components/work_item_todos.vue';
+import TodosToggle from '~/work_items/components/shared/todos_toggle.vue';
 import WorkItemStateBadge from '~/work_items/components/work_item_state_badge.vue';
 import WorkItemNotificationsWidget from '~/work_items/components/work_item_notifications_widget.vue';
 
@@ -46,7 +46,7 @@ describe('WorkItemStickyHeader', () => {
   const findConfidentialityBadge = () => wrapper.findComponent(ConfidentialityBadge);
   const findLockedBadge = () => wrapper.findComponent(LockedBadge);
   const findWorkItemActions = () => wrapper.findComponent(WorkItemActions);
-  const findWorkItemTodos = () => wrapper.findComponent(WorkItemTodos);
+  const findTodosToggle = () => wrapper.findComponent(TodosToggle);
   const findIntersectionObserver = () => wrapper.findComponent(GlIntersectionObserver);
   const findWorkItemStateBadge = () => wrapper.findComponent(WorkItemStateBadge);
   const findEditButton = () => wrapper.findByTestId('work-item-edit-button-sticky');
@@ -67,7 +67,7 @@ describe('WorkItemStickyHeader', () => {
     createComponent();
 
     expect(findWorkItemTitle().exists()).toBe(true);
-    expect(findWorkItemTodos().exists()).toBe(true);
+    expect(findTodosToggle().exists()).toBe(true);
     expect(findWorkItemActions().exists()).toBe(true);
   });