Skip to content

Conversation

@alexfrombox
Copy link

@alexfrombox alexfrombox commented Nov 18, 2025

Summary

Implements new Blueprint-based versions of AddTaskButton and AddTaskMenu components with corresponding test coverage.

Changes

  • ✨ Added AddTaskButtonV2.tsx - Functional component using Blueprint Web's DropdownMenu
  • ✨ Added AddTaskMenuV2.tsx - Menu component with General and Approval task options
  • ✨ Added AddTaskMenuV2.scss - Styling for menu items with icons
  • ✅ Added comprehensive RTL tests for both components

Key Improvements

  • Migrated from legacy UI components to Blueprint Web design system
  • Maintains backward compatibility (V1 components unchanged)
  • Follows project CSS naming conventions (bcs- prefix)

Screenshots

Screenshot 2025-11-18 at 17 48 00

Summary by CodeRabbit

  • New Features

    • Added a dropdown for creating tasks with General and Approval options.
    • Added a task creation modal with submission error handling and focus management.
    • Supports opening the task form via navigation/history integration.
  • Style

    • Added updated styling for the new task menu (layout, icons, typography).
  • Tests

    • Added tests covering menu interactions, modal open/close flows, and navigation scenarios.

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 18, 2025

Walkthrough

Adds AddTaskButtonV2 and AddTaskMenuV2 React components with SCSS styling and tests. The button component manages task-type selection, modal open/close, submission error state, and supports router-based or internal sidebar navigation.

Changes

Cohort / File(s) Summary
Components
src/elements/content-sidebar/AddTaskButtonV2.tsx, src/elements/content-sidebar/AddTaskMenuV2.tsx
New AddTaskButtonV2 component manages task form modal state, selected TaskType (defaults to approval), submission error handling, and navigation via history.replace or an internalSidebarNavigationHandler. New AddTaskMenuV2 renders a localized dropdown with General and Approval task items and exposes a trigger ref callback.
Styling
src/elements/content-sidebar/AddTaskMenuV2.scss
New SCSS module defining layout, sizing, icon slot, and typography for the Add Task V2 menu using shared design tokens.
Tests
src/elements/content-sidebar/__tests__/AddTaskButtonV2.test.tsx, src/elements/content-sidebar/__tests__/AddTaskMenuV2.test.tsx
New tests for modal open/close flows, router vs internal navigation behavior, menu rendering, disabled state, item click handling, and trigger ref assignment; components mocked where appropriate.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Menu as AddTaskMenuV2
    participant Button as AddTaskButtonV2
    participant Nav as Navigation
    participant Modal as TaskModal

    User->>Menu: Click trigger
    Menu->>Menu: Open menu
    User->>Menu: Select task item (General/Approval)
    Menu->>Button: onMenuItemClick(taskType)
    Button->>Button: set taskType, isTaskFormOpen = true
    alt Router enabled
        Button->>Nav: history.replace({ open: true })
    else Router disabled
        Button->>Nav: internalSidebarNavigationHandler({ open: true, ...state })
    end
    Button->>Modal: Render TaskModal with taskFormProps
    User->>Modal: Submit or Close
    alt Submit error
        Modal->>Button: handleSubmitError(error)
    else Close/Success
        Modal->>Button: handleModalClose()
        Button->>Button: clear error, refocus trigger
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–25 minutes

  • Review attention: conditional navigation logic in AddTaskButtonV2 (history.replace vs internalSidebarNavigationHandler), focus/ref handling, and error-state propagation to TaskModal.
  • Verify AddTaskMenuV2 accessibility of the trigger ref and intl message usage.
  • Validate tests correctly mock navigation and assert state transitions.

Possibly related PRs

Suggested labels

ready-to-merge

Suggested reviewers

  • jpan-box
  • tjuanitas
  • jankowiakdawid

Poem

🐰 A tiny button hops to play,
Menu pops up, then leads the way,
Modal opens, forms take flight,
Errors caught and focus bright,
Hooray — tasks bloom in gentle light 🌿

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title references 'BP AddTaskButtonV2' which directly corresponds to the main component being introduced in this PR, aligning with the primary change of implementing Blueprint-based versions of task button components.
Description check ✅ Passed The PR description comprehensively covers the changes including new components added, styling files, test coverage, and key improvements, with a screenshot demonstrating the UI change.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 39b019c and d654476.

📒 Files selected for processing (1)
  • src/elements/content-sidebar/AddTaskMenuV2.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/elements/content-sidebar/AddTaskMenuV2.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: lint_test_build
  • GitHub Check: Summary

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@alexfrombox alexfrombox changed the title Fature/new add task button component Feature/new add task button component Nov 18, 2025
@alexfrombox alexfrombox changed the title Feature/new add task button component feat(ui-uplift): BP AddTaskButtonV2 Nov 18, 2025
@alexfrombox alexfrombox marked this pull request as ready for review November 18, 2025 16:49
@alexfrombox alexfrombox requested review from a team as code owners November 18, 2025 16:49
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
src/elements/content-sidebar/__tests__/AddTaskMenuV2.test.tsx (1)

82-88: Consider verifying the ref argument type.

The test confirms the callback is invoked but doesn't verify it receives an HTMLButtonElement. For more robust coverage, consider asserting the argument type.

 test('should call setAddTaskButtonRef with button element', () => {
     const setAddTaskButtonRef = jest.fn();

     renderComponent({ setAddTaskButtonRef });

     expect(setAddTaskButtonRef).toHaveBeenCalled();
+    expect(setAddTaskButtonRef).toHaveBeenCalledWith(expect.any(HTMLButtonElement));
 });
src/elements/content-sidebar/AddTaskMenuV2.scss (1)

28-36: Consider using design tokens for typography.

If the project has design tokens for font-weight, font-size, and line-height values, consider using them for consistency across the codebase.

src/elements/content-sidebar/AddTaskMenuV2.tsx (1)

80-80: Prefer useIntl hook over injectIntl HOC in TypeScript files.

Based on the codebase pattern, TypeScript files should use the modern useIntl hook instead of the injectIntl HOC for consistency with other new TypeScript components.

Based on learnings

Apply this refactor:

-import { injectIntl, IntlShape } from 'react-intl';
+import { useIntl } from 'react-intl';

 import { DropdownMenu, TriggerButton } from '@box/blueprint-web';
 import ApprovalTask from '@box/blueprint-web-assets/icons/Fill/ApprovalTask';
 import Tasks from '@box/blueprint-web-assets/icons/MediumFilled/Tasks';
 import messages from './messages';
 import { TASK_TYPE_APPROVAL, TASK_TYPE_GENERAL } from '../../constants';
 import type { TaskType } from '../../common/types/tasks';

 import './AddTaskMenuV2.scss';

 type Props = {
     isDisabled: boolean;
     onMenuItemClick: (taskType: TaskType) => void;
     setAddTaskButtonRef?: (element: HTMLButtonElement | null) => void;
-    intl: IntlShape;
 };

-const AddTaskMenuV2: React.FC<Props> = ({ isDisabled, onMenuItemClick, setAddTaskButtonRef, intl }) => {
+const AddTaskMenuV2: React.FC<Props> = ({ isDisabled, onMenuItemClick, setAddTaskButtonRef }) => {
+    const intl = useIntl();
     const [isOpen, setIsOpen] = React.useState(false);

     // ... rest of component

-export default injectIntl(AddTaskMenuV2);
+export default AddTaskMenuV2;
src/elements/content-sidebar/AddTaskButtonV2.tsx (1)

107-108: Prefer useIntl hook over injectIntl HOC in TypeScript files.

Based on the codebase pattern, TypeScript files should use the modern useIntl hook instead of the injectIntl HOC for consistency with other new TypeScript components.

Based on learnings

Apply this refactor:

-import { injectIntl, IntlShape } from 'react-intl';
+import { useIntl } from 'react-intl';
 import { withRouterIfEnabled } from '../common/routing';

 import AddTaskMenuV2 from './AddTaskMenuV2';
 import TaskModal from './TaskModal';
 import { TASK_TYPE_APPROVAL } from '../../constants';
 import type { TaskFormProps } from './activity-feed/task-form/TaskForm';
 import type { TaskType } from '../../common/types/tasks';
 import type { ElementsXhrError } from '../../common/types/api';
 import type { InternalSidebarNavigation, InternalSidebarNavigationHandler } from '../common/types/SidebarNavigation';

 export type AddTaskButtonV2Props = {
     history?: History;
     internalSidebarNavigation?: InternalSidebarNavigation;
     internalSidebarNavigationHandler?: InternalSidebarNavigationHandler;
     isDisabled?: boolean;
     onTaskModalClose: () => void;
     routerDisabled?: boolean;
     taskFormProps: TaskFormProps;
-    intl: IntlShape;
 };

 const AddTaskButtonV2: React.FC<AddTaskButtonV2Props> = ({
     history,
     internalSidebarNavigation,
     internalSidebarNavigationHandler,
     isDisabled = false,
     onTaskModalClose,
     routerDisabled,
     taskFormProps,
 }) => {
+    const intl = useIntl();
     const buttonRef = React.useRef<HTMLButtonElement>(null);
     
     // ... rest of component

 export { AddTaskButtonV2 as AddTaskButtonV2Component };
-export default withRouterIfEnabled(injectIntl(AddTaskButtonV2));
+export default withRouterIfEnabled(AddTaskButtonV2);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 35080aa and 39b019c.

📒 Files selected for processing (5)
  • src/elements/content-sidebar/AddTaskButtonV2.tsx (1 hunks)
  • src/elements/content-sidebar/AddTaskMenuV2.scss (1 hunks)
  • src/elements/content-sidebar/AddTaskMenuV2.tsx (1 hunks)
  • src/elements/content-sidebar/__tests__/AddTaskButtonV2.test.tsx (1 hunks)
  • src/elements/content-sidebar/__tests__/AddTaskMenuV2.test.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-07-11T14:43:02.677Z
Learnt from: jpan-box
Repo: box/box-ui-elements PR: 4166
File: src/elements/content-sidebar/SidebarNav.js:126-126
Timestamp: 2025-07-11T14:43:02.677Z
Learning: In the box-ui-elements repository, there's a file-type-based pattern for internationalization: TypeScript files (.tsx) predominantly use the modern useIntl hook (41 vs 15 files), while JavaScript files (.js) predominantly use the legacy injectIntl HOC (64 vs 5 files). New TypeScript components should use useIntl, while existing JavaScript components typically continue using injectIntl for consistency.

Applied to files:

  • src/elements/content-sidebar/AddTaskMenuV2.tsx
  • src/elements/content-sidebar/AddTaskButtonV2.tsx
📚 Learning: 2025-08-15T14:42:01.840Z
Learnt from: jpan-box
Repo: box/box-ui-elements PR: 4227
File: src/elements/common/sub-header/SubHeader.tsx:19-19
Timestamp: 2025-08-15T14:42:01.840Z
Learning: In SubHeader.tsx, the bulkItemActionMenuProps prop is intentionally required (not optional) because there will always be a default "Download" action available, ensuring the prop is never undefined in actual usage.

Applied to files:

  • src/elements/content-sidebar/AddTaskMenuV2.tsx
  • src/elements/content-sidebar/AddTaskButtonV2.tsx
🧬 Code graph analysis (2)
src/elements/content-sidebar/__tests__/AddTaskButtonV2.test.tsx (1)
src/elements/content-sidebar/AddTaskButtonV2.tsx (1)
  • AddTaskButtonV2 (107-107)
src/elements/content-sidebar/AddTaskButtonV2.tsx (2)
src/elements/common/types/SidebarNavigation.ts (2)
  • InternalSidebarNavigation (49-51)
  • InternalSidebarNavigationHandler (55-55)
src/elements/common/routing/withRouterIfEnabled.js (1)
  • withRouterIfEnabled (6-23)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: lint_test_build
  • GitHub Check: Summary
🔇 Additional comments (13)
src/elements/content-sidebar/__tests__/AddTaskMenuV2.test.tsx (3)

1-30: LGTM! Clean test setup.

The test infrastructure is well-organized with appropriate mocking and test utilities. The TooltipProvider wrapper correctly accommodates Blueprint Web component requirements.


31-44: LGTM! Good accessibility test coverage.

These tests properly verify the component's basic rendering and disabled state using accessible role queries.


46-80: LGTM! Comprehensive interaction tests.

Both menu item click tests properly validate the user interaction flow and verify that the correct task type is passed to the callback.

src/elements/content-sidebar/AddTaskMenuV2.scss (2)

1-8: LGTM! Clean SCSS structure.

The imports and container styling follow proper patterns with appropriate use of constants and design tokens.


10-26: LGTM! Proper layout implementation.

The flexbox layout with gap and the icon styling with fixed dimensions ensure consistent presentation.

src/elements/content-sidebar/__tests__/AddTaskButtonV2.test.tsx (2)

1-104: LGTM! Comprehensive test coverage.

The test suite thoroughly validates:

  • History state management for keeping sidebar open
  • Modal open/close lifecycle
  • Callback invocations
  • State transitions

The inline comments at lines 32-35 helpfully document the design rationale for the history state management.


106-152: LGTM! Router-disabled scenario coverage.

These tests properly validate the alternative navigation path when routing is disabled, including state preservation.

src/elements/content-sidebar/AddTaskMenuV2.tsx (2)

1-19: LGTM! Clean imports and type definitions.

The props interface is well-defined with appropriate required and optional fields.


20-41: LGTM! Proper state and callback management.

The component correctly manages dropdown state and memoizes the menu item click handler with appropriate dependencies.

src/elements/content-sidebar/AddTaskButtonV2.tsx (4)

1-24: LGTM! Well-structured imports and type definitions.

The component props are comprehensively typed with appropriate optional fields for flexible integration.


25-62: LGTM! Proper state management and router handling.

The component correctly handles both router-enabled and router-disabled navigation scenarios. The inline comments at lines 39-42 helpfully document the design rationale for the history state management.


63-86: LGTM! Proper cleanup and focus management.

The modal close handler appropriately cleans up state and restores focus to the trigger button. The setTimeout pattern ensures focus occurs after React's state updates complete.


87-105: LGTM! Clean component composition.

The component properly renders the menu and modal with appropriate props, maintaining clear separation of concerns.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants