diff --git a/i18n/en-US.properties b/i18n/en-US.properties
index f6a0cfac0e..3681645d7a 100644
--- a/i18n/en-US.properties
+++ b/i18n/en-US.properties
@@ -872,6 +872,16 @@ be.sort = Sort
be.statusSkill = Status
# Generic success label.
be.success = Success
+# aria-label for the task modal close button
+be.taskModalV2.close = Close
+# Title of the modal for creating an approval task
+be.taskModalV2.createApprovalTask = Create Approval Task
+# Title of the modal for creating a general task
+be.taskModalV2.createGeneralTask = Create General Task
+# Title of the modal for editing an existing approval task
+be.taskModalV2.editApprovalTask = Modify Approval Task
+# Title of the modal for editing an existing general task
+be.taskModalV2.editGeneralTask = Modify General Task
# Shown instead of todays date.
be.today = today
# Label for keywords/topics skill section in the preview sidebar
diff --git a/src/elements/content-sidebar/activity-feed-v2/task-modal-v2/TaskModalV2.scss b/src/elements/content-sidebar/activity-feed-v2/task-modal-v2/TaskModalV2.scss
new file mode 100644
index 0000000000..4ab1ca010f
--- /dev/null
+++ b/src/elements/content-sidebar/activity-feed-v2/task-modal-v2/TaskModalV2.scss
@@ -0,0 +1,5 @@
+.bcs-NewTaskModal {
+ display: flex;
+ flex-direction: column;
+ gap: var(--bp-space-040);
+}
diff --git a/src/elements/content-sidebar/activity-feed-v2/task-modal-v2/TaskModalV2.tsx b/src/elements/content-sidebar/activity-feed-v2/task-modal-v2/TaskModalV2.tsx
new file mode 100644
index 0000000000..b34b249eb4
--- /dev/null
+++ b/src/elements/content-sidebar/activity-feed-v2/task-modal-v2/TaskModalV2.tsx
@@ -0,0 +1,58 @@
+import * as React from 'react';
+import { useIntl } from 'react-intl';
+import type { MessageDescriptor } from 'react-intl';
+
+import { Modal } from '@box/blueprint-web';
+
+import { TASK_EDIT_MODE_CREATE, TASK_TYPE_APPROVAL, TASK_TYPE_GENERAL } from '../../../../constants';
+
+import type { TaskEditMode, TaskType } from '../../../../common/types/tasks';
+
+import messages from './messages';
+
+import './TaskModalV2.scss';
+
+export type TaskModalV2Props = {
+ editMode?: TaskEditMode;
+ isOpen: boolean;
+ onClose: () => void;
+ taskType: TaskType;
+};
+
+const getTitleMessage = (taskType: TaskType, editMode: TaskEditMode): MessageDescriptor => {
+ const isCreate = editMode === TASK_EDIT_MODE_CREATE;
+ if (taskType === TASK_TYPE_GENERAL) {
+ return isCreate ? messages.createGeneralTaskTitle : messages.editGeneralTaskTitle;
+ }
+ return isCreate ? messages.createApprovalTaskTitle : messages.editApprovalTaskTitle;
+};
+
+const TaskModalV2 = ({
+ editMode = TASK_EDIT_MODE_CREATE,
+ isOpen,
+ onClose,
+ taskType = TASK_TYPE_APPROVAL,
+}: TaskModalV2Props) => {
+ const { formatMessage } = useIntl();
+ const titleMessage = getTitleMessage(taskType, editMode);
+
+ const handleOpenChange = (open: boolean) => {
+ if (!open) {
+ onClose();
+ }
+ };
+
+ return (
+
+
+ {formatMessage(titleMessage)}
+
+ Form goes here
+
+
+
+
+ );
+};
+
+export default TaskModalV2;
diff --git a/src/elements/content-sidebar/activity-feed-v2/task-modal-v2/__tests__/TaskModalV2.test.tsx b/src/elements/content-sidebar/activity-feed-v2/task-modal-v2/__tests__/TaskModalV2.test.tsx
new file mode 100644
index 0000000000..89a9dea0b2
--- /dev/null
+++ b/src/elements/content-sidebar/activity-feed-v2/task-modal-v2/__tests__/TaskModalV2.test.tsx
@@ -0,0 +1,54 @@
+import * as React from 'react';
+
+import { render, screen, userEvent } from '../../../../../test-utils/testing-library';
+import {
+ TASK_EDIT_MODE_CREATE,
+ TASK_EDIT_MODE_EDIT,
+ TASK_TYPE_APPROVAL,
+ TASK_TYPE_GENERAL,
+} from '../../../../../constants';
+import TaskModalV2 from '../TaskModalV2';
+
+import type { TaskModalV2Props } from '../TaskModalV2';
+
+describe('elements/content-sidebar/task-modal-v2/TaskModalV2', () => {
+ const renderModal = (props: Partial = {}) =>
+ render();
+
+ test('renders nothing when isOpen is false', () => {
+ renderModal({ isOpen: false });
+ expect(screen.queryByTestId('task-modal-v2')).not.toBeInTheDocument();
+ });
+
+ test('renders the modal with a placeholder form region when isOpen is true', () => {
+ renderModal();
+ expect(screen.getByTestId('task-modal-v2')).toBeVisible();
+ expect(screen.getByText('Form goes here')).toBeVisible();
+ });
+
+ test.each([
+ [TASK_TYPE_APPROVAL, TASK_EDIT_MODE_CREATE, 'Create Approval Task'],
+ [TASK_TYPE_APPROVAL, TASK_EDIT_MODE_EDIT, 'Modify Approval Task'],
+ [TASK_TYPE_GENERAL, TASK_EDIT_MODE_CREATE, 'Create General Task'],
+ [TASK_TYPE_GENERAL, TASK_EDIT_MODE_EDIT, 'Modify General Task'],
+ ])('renders the correct title for taskType=%s editMode=%s', (taskType, editMode, expectedTitle) => {
+ renderModal({ taskType, editMode });
+ expect(screen.getByRole('heading', { name: expectedTitle })).toBeVisible();
+ });
+
+ test('calls onClose when the close button is clicked', async () => {
+ const user = userEvent();
+ const onClose = jest.fn();
+ renderModal({ onClose });
+ await user.click(screen.getByRole('button', { name: 'Close' }));
+ expect(onClose).toHaveBeenCalledTimes(1);
+ });
+
+ test('calls onClose when Escape is pressed', async () => {
+ const user = userEvent();
+ const onClose = jest.fn();
+ renderModal({ onClose });
+ await user.keyboard('{Escape}');
+ expect(onClose).toHaveBeenCalledTimes(1);
+ });
+});
diff --git a/src/elements/content-sidebar/activity-feed-v2/task-modal-v2/index.ts b/src/elements/content-sidebar/activity-feed-v2/task-modal-v2/index.ts
new file mode 100644
index 0000000000..ea9831cbff
--- /dev/null
+++ b/src/elements/content-sidebar/activity-feed-v2/task-modal-v2/index.ts
@@ -0,0 +1,2 @@
+export { default } from './TaskModalV2';
+export type { TaskModalV2Props } from './TaskModalV2';
diff --git a/src/elements/content-sidebar/activity-feed-v2/task-modal-v2/messages.ts b/src/elements/content-sidebar/activity-feed-v2/task-modal-v2/messages.ts
new file mode 100644
index 0000000000..486cb9446d
--- /dev/null
+++ b/src/elements/content-sidebar/activity-feed-v2/task-modal-v2/messages.ts
@@ -0,0 +1,31 @@
+import { defineMessages } from 'react-intl';
+
+const messages = defineMessages({
+ closeLabel: {
+ id: 'be.taskModalV2.close',
+ defaultMessage: 'Close',
+ description: 'aria-label for the task modal close button',
+ },
+ createApprovalTaskTitle: {
+ id: 'be.taskModalV2.createApprovalTask',
+ defaultMessage: 'Create Approval Task',
+ description: 'Title of the modal for creating an approval task',
+ },
+ createGeneralTaskTitle: {
+ id: 'be.taskModalV2.createGeneralTask',
+ defaultMessage: 'Create General Task',
+ description: 'Title of the modal for creating a general task',
+ },
+ editApprovalTaskTitle: {
+ id: 'be.taskModalV2.editApprovalTask',
+ defaultMessage: 'Modify Approval Task',
+ description: 'Title of the modal for editing an existing approval task',
+ },
+ editGeneralTaskTitle: {
+ id: 'be.taskModalV2.editGeneralTask',
+ defaultMessage: 'Modify General Task',
+ description: 'Title of the modal for editing an existing general task',
+ },
+});
+
+export default messages;