Skip to content

feat: Update Sana Canvas Popup, Modal and Dialog#4018

Open
josh-bagwell wants to merge 7 commits into
Workday:prerelease/majorfrom
josh-bagwell:feat/update-sana-canvas-popup-dialog-modal-26-06
Open

feat: Update Sana Canvas Popup, Modal and Dialog#4018
josh-bagwell wants to merge 7 commits into
Workday:prerelease/majorfrom
josh-bagwell:feat/update-sana-canvas-popup-dialog-modal-26-06

Conversation

@josh-bagwell

@josh-bagwell josh-bagwell commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes: #3988

Release Category

Components

Release Note

Updates Popup, Modal and Dialog to new Sana Canvas styling.

BREAKING CHANGES

Visual.


Where Should the Reviewer Start?

/modules/react/dialog
/modules/react/modal
/modules/react/popup

Summary by CodeRabbit

  • New Features

    • Added Dialog.ButtonGroup, Modal.ButtonGroup, and Popup.ButtonGroup for consistent grouped action-button layouts (with configurable alignment for popups).
  • Style

    • Updated dialog, modal, and popup examples to use button groups instead of flex-based spacing.
    • Standardized grouped action-button ordering so “Cancel” appears first.
    • Refined popup card padding for improved spacing.
  • Tests

    • Updated Cypress modal/popup focus and tab-order assertions to match the new button-group layout.

@josh-bagwell josh-bagwell self-assigned this Jun 24, 2026
@josh-bagwell josh-bagwell requested a review from a team as a code owner June 24, 2026 17:48
@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: cfb9b53c-a119-4080-b387-d9c8a4f04fbd

📥 Commits

Reviewing files that changed from the base of the PR and between 14cc36a and e15c384.

📒 Files selected for processing (1)
  • modules/react/popup/lib/PopupCard.tsx
✅ Files skipped from review due to trivial changes (1)
  • modules/react/popup/lib/PopupCard.tsx

📝 Walkthrough

Walkthrough

The PR adds Popup.ButtonGroup and exposes it through Popup, Modal, and Dialog. Popup, modal, and dialog stories now use the new wrapper instead of Flex, with updated button ordering. Popup and modal focus specs were adjusted to match the new tab order.

Changes

ButtonGroup subcomponent and story migration

Layer / File(s) Summary
PopupButtonGroup component
modules/react/popup/lib/PopupButtonGroup.tsx
Defines PopupButtonGroupProps, popupButtonGroupStencil, and PopupButtonGroup with usePopupModel, position handling, responsive column layout, and grow behavior.
Popup, Modal, and Dialog ButtonGroup wiring
modules/react/popup/lib/Popup.tsx, modules/react/modal/lib/Modal.tsx, modules/react/dialog/lib/Dialog.tsx, modules/react/popup/lib/PopupCard.tsx
Imports and registers PopupButtonGroup in Popup, exposes Modal.ButtonGroup and Dialog.ButtonGroup, and changes PopupCard padding values.
Popup and modal story updates
modules/react/popup/stories/examples/*.tsx, modules/react/modal/stories/examples/*.tsx, cypress/component/Popup.spec.tsx, cypress/component/Modal.spec.tsx
Replaces Flex wrappers with Popup.ButtonGroup and Modal.ButtonGroup across popup and modal stories, removes unused layout and styling imports, and updates popup and modal focus specs to match the new tab order.
Dialog examples and ordering updates
modules/react/dialog/stories/examples/*.tsx, modules/react/dialog/stories/FallbackTesting.stories.tsx
Replaces Flex wrappers with Dialog.ButtonGroup in dialog stories and updates the button order so Cancel renders before Submit or the primary action.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

review in progress

Suggested reviewers

  • RayRedGoose
  • alanbsmith

Poem

🐇 A button group hopped into view,
Cancel first, then the action crew.
Popup, modal, dialog line up neat,
With tab order changes on little bunny feet ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning ButtonGroup and story/test updates are present, but the required Dialog/Modal token updates and codemod or migration guide are not evidenced. Add the remaining Dialog/Modal token updates and provide a codemod or migration guide for the button-ordering breaking change.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main change: updating Dialog, Modal, and related Popup styling.
Out of Scope Changes check ✅ Passed No clear unrelated changes stand out; the Popup additions appear to support the shared ButtonGroup and styling used by Dialog and Modal.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@josh-bagwell josh-bagwell changed the title Feat/update sana canvas popup dialog modal 26 06 feat: Update Popup, Modal and Dialog Sana Canvas Jun 24, 2026
@josh-bagwell josh-bagwell changed the title feat: Update Popup, Modal and Dialog Sana Canvas feat: Update Sana Canvas Popup, Modal and Dialog Jun 24, 2026
@cypress

cypress Bot commented Jun 24, 2026

Copy link
Copy Markdown

Workday/canvas-kit    Run #11119

Run Properties:  status check passed Passed #11119  •  git commit 5690920e7d ℹ️: Merge e15c384a4f7ca9fe0ca6117fd69ac19fee4310c0 into 68776ccf39d441a37b4692f52fd6...
Project Workday/canvas-kit
Branch Review feat/update-sana-canvas-popup-dialog-modal-26-06
Run status status check passed Passed #11119
Run duration 02m 24s
Commit git commit 5690920e7d ℹ️: Merge e15c384a4f7ca9fe0ca6117fd69ac19fee4310c0 into 68776ccf39d441a37b4692f52fd6...
Committer Josh
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 0
Tests that did not run due to a developer annotating a test with .skip  Pending 17
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 809
View all changes introduced in this branch ↗︎
UI Coverage  19.63%
  Untested elements 1525  
  Tested elements 370  
Accessibility  99.41%
  Failed rules  5 critical   5 serious   0 moderate   2 minor
  Failed elements 68  

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
modules/react/popup/lib/PopupButtonGroup.tsx (1)

41-47: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

grow selector matches all descendant buttons.

& button is a descendant combinator, so when a ButtonGroup contains nested interactive content (e.g. the nested Popup/Modal patterns in ModalWithPopup/WithTooltips), enabling grow would also force-width any deeper button elements. Consider scoping to direct children (& > button) if only the group's own buttons should grow.

♻️ Optional scoping
     grow: {
       true: {
-        '& button': {
+        '& > button': {
           width: '100%',
         },
       },
     },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/react/popup/lib/PopupButtonGroup.tsx` around lines 41 - 47, The
`grow` style in `PopupButtonGroup` is too broad because `& button` targets all
descendant buttons, including nested buttons inside popup/modal content. Update
the `grow.true` rule in `PopupButtonGroup.tsx` to scope the width styling to the
group’s direct button children only, using the relevant selector in the `grow`
block so nested interactive content is unaffected.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@modules/react/modal/lib/Modal.tsx`:
- Around line 95-99: The JSDoc for `Modal.ButtonGroup` contains a broken symbol
reference: it points to `modalButtonGroupStencil`, which does not exist, and the
linked `ButtonGroup` reference should also be aligned with the actual
implementation. Update the documentation in `Modal.ButtonGroup` to reference the
existing `popupButtonGroupStencil` used by `Popup.ButtonGroup`, and fix the
corresponding broken `{`@link` ButtonGroup}` reference in `Popup.tsx` so the docs
resolve correctly.

In `@modules/react/modal/stories/examples/ModalWithPopup.tsx`:
- Around line 34-37: The Cancel action inside ModalWithPopup is currently using
Popup.CloseButton, so it only targets the nested popup instead of dismissing the
surrounding modal. Update the button in the ModalWithPopup story to use the
modal’s close/dismiss control (or wire it through the modal’s close handler) and
keep the popup-specific controls only for Popup.ButtonGroup, Popup.CloseButton,
and Popup.Target where they actually manage the popup state.

In `@modules/react/modal/stories/examples/ModalWithPopupRTL.tsx`:
- Around line 35-38: The first visible “Cancel” action in the RTL modal is still
wired to Popup.CloseButton, so it only targets the popup instead of dismissing
the modal. Update the ModalWithPopupRTL story to bind that outer Cancel control
to the modal’s close action (using the modal component’s close/dismiss wiring)
while keeping the popup-specific controls inside Popup.ButtonGroup unchanged.
Use the existing Popup and modal button setup in ModalWithPopupRTL to locate the
affected JSX and switch the Cancel button to the modal-level handler.

In `@modules/react/popup/lib/Popup.tsx`:
- Around line 115-119: The JSDoc for Popup.ButtonGroup incorrectly links to a
non-existent ButtonGroup symbol and should describe PopupButtonGroup as its own
standalone component instead. Update the doc text on PopupButtonGroup in
Popup.tsx to remove the broken {`@link` ButtonGroup} reference while keeping the
valid {`@link` popupButtonGroupStencil} link, and apply the same wording fix to
the duplicated documentation in Dialog.tsx and Modal.tsx.

---

Nitpick comments:
In `@modules/react/popup/lib/PopupButtonGroup.tsx`:
- Around line 41-47: The `grow` style in `PopupButtonGroup` is too broad because
`& button` targets all descendant buttons, including nested buttons inside
popup/modal content. Update the `grow.true` rule in `PopupButtonGroup.tsx` to
scope the width styling to the group’s direct button children only, using the
relevant selector in the `grow` block so nested interactive content is
unaffected.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b46e66e1-4b71-425e-9951-674d7ee0b1d1

📥 Commits

Reviewing files that changed from the base of the PR and between d6ad8e0 and 12a9733.

📒 Files selected for processing (31)
  • modules/react/dialog/lib/Dialog.tsx
  • modules/react/dialog/stories/FallbackTesting.stories.tsx
  • modules/react/dialog/stories/examples/Basic.tsx
  • modules/react/dialog/stories/examples/DialogWithFallbackPlacements.tsx
  • modules/react/dialog/stories/examples/Focus.tsx
  • modules/react/modal/lib/Modal.tsx
  • modules/react/modal/stories/examples/Basic.tsx
  • modules/react/modal/stories/examples/BodyOverflow.tsx
  • modules/react/modal/stories/examples/CustomFocus.tsx
  • modules/react/modal/stories/examples/FormModal.tsx
  • modules/react/modal/stories/examples/FullOverflow.tsx
  • modules/react/modal/stories/examples/IframeTest.tsx
  • modules/react/modal/stories/examples/ModalWithPopup.tsx
  • modules/react/modal/stories/examples/ModalWithPopupRTL.tsx
  • modules/react/modal/stories/examples/NoTargetRTL.tsx
  • modules/react/modal/stories/examples/ReturnFocus.tsx
  • modules/react/modal/stories/examples/StackedModals.tsx
  • modules/react/modal/stories/examples/WithTooltips.tsx
  • modules/react/modal/stories/examples/WithoutCloseIcon.tsx
  • modules/react/popup/lib/Popup.tsx
  • modules/react/popup/lib/PopupButtonGroup.tsx
  • modules/react/popup/lib/PopupCard.tsx
  • modules/react/popup/stories/examples/Basic.tsx
  • modules/react/popup/stories/examples/FocusRedirect.tsx
  • modules/react/popup/stories/examples/FocusTrap.tsx
  • modules/react/popup/stories/examples/InitialFocus.tsx
  • modules/react/popup/stories/examples/InlinePopup.tsx
  • modules/react/popup/stories/examples/MultiplePopups.tsx
  • modules/react/popup/stories/examples/NestedPopups.tsx
  • modules/react/popup/stories/examples/PopupWithFallbackPlacements.tsx
  • modules/react/popup/stories/examples/RTL.tsx

Comment thread modules/react/modal/lib/Modal.tsx
Comment thread modules/react/modal/stories/examples/ModalWithPopup.tsx
Comment thread modules/react/modal/stories/examples/ModalWithPopupRTL.tsx
Comment thread modules/react/popup/lib/Popup.tsx
@josh-bagwell josh-bagwell added ready for review Code is ready for review needs-a11y Extra attention from accessibility is needed labels Jun 25, 2026

@williamjstanton williamjstanton left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Possible omissions on the upgrade guide? Can we double check on these?

Low: The v16 upgrade guide does not mention the new Popup/Dialog/Modal.ButtonGroup public API or the Popup.Card padding change.

Otherwise, looking good on accessibility side so far.

},
});

export const PopupButtonGroup = createSubcomponent('div')({

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Medium: Popup.ButtonGroup is documented in JSDoc as a button “group,” but it renders a layout-only div with no group semantics. That may be fine for dialog action rows, but it conflicts with existing Button docs that recommend semantic grouping via ul or fieldset/legend for related buttons. Recommend documenting *.ButtonGroup as visual/layout-only, and showing when to add role="group" plus an accessible name.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I can update this. Thanks WIlliam!

@josh-bagwell josh-bagwell Jun 27, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

When would be a good time to add a role="group" to the group?

Thoughts on the accessible name being "Actions" (i.e. aria-label="Actions").

boxShadow: system.depth[3],
minHeight: 0,
padding: system.legacy.padding.xl,
padding: system.legacy.padding.xxl,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I’d still recommend adding or running a 320px viewport visual/accessibility check because Popup.Card padding increased to xxl, reducing usable content width.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Let me take a look.

@@ -198,7 +198,7 @@ describe('Popup', () => {
// useFocusRedirect hides on Tab only from the last focusable in the popup (Close, Delete, Cancel)
context('when the "Cancel" button has focus and the tab key is pressed', () => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Low: The focus redirect Cypress description/comment is now stale: it says the Cancel button has focus and lists order as Close, Delete, Cancel, but the test focuses Delete after the PR’s reordered DOM. That weakens the accessibility spec around focus order.

@RayRedGoose

Copy link
Copy Markdown
Contributor

Do we have padding changed? It looks different in visual tests. We also need to setup sana theme in tests.
Also do we have info how button group should behave on small width modals? just align to right can look odd
Screenshot 2026-06-26 at 4 01 08 PM

@josh-bagwell

Copy link
Copy Markdown
Contributor Author

Do we have padding changed? It looks different in visual tests. We also need to setup sana theme in tests. Also do we have info how button group should behave on small width modals? just align to right can look odd Screenshot 2026-06-26 at 4 01 08 PM

We don't have specific info on smaller sizes but, I have it set to stacking:
Screenshot 2026-06-26 at 5 58 43 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-a11y Extra attention from accessibility is needed ready for review Code is ready for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants