Context Menu Stories and Implementation - #4913
Conversation
|
Visit https://backpack.github.io/storybook-prs/4913 to see this build running in a browser. |
|
Visit https://backpack.github.io/storybook-prs/4913 to see this build running in a browser. |
|
Visit https://backpack.github.io/storybook-prs/4913 to see this build running in a browser. |
There was a problem hiding this comment.
Pull request overview
Note
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Adds a new BpkContextMenu compound component wrapping Ark UI’s Menu, plus small additive changes to BpkSaveButton to support composition as an asChild menu trigger.
Changes:
- Introduces
bpk-component-context-menuwith a namespaced API (Root,Trigger,Content,Item,ItemGroup,Separator,TriggerItem) and SCSS styling. - Adds Storybook stories and unit + a11y tests for the new context menu.
- Updates
BpkSaveButtonto useforwardRef, addsonClickandhoverEffectprops, adjusts prop spread order, and tweaks focus styling when used as a menu trigger.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/backpack-web/src/bpk-component-context-menu/src/common-types.ts | Adds shared public types and item variant constants for the context menu. |
| packages/backpack-web/src/bpk-component-context-menu/src/accessibility-test.tsx | Adds axe-based accessibility coverage for open/closed states. |
| packages/backpack-web/src/bpk-component-context-menu/src/BpkContextMenuTrigger.tsx | Implements the trigger wrapper with optional asChild composition. |
| packages/backpack-web/src/bpk-component-context-menu/src/BpkContextMenuSubTriggerItem.tsx | Adds submenu trigger item wrapper (Menu.TriggerItem). |
| packages/backpack-web/src/bpk-component-context-menu/src/BpkContextMenuSeparator.tsx | Adds separator wrapper (Menu.Separator). |
| packages/backpack-web/src/bpk-component-context-menu/src/BpkContextMenuRoot.tsx | Adds root wrapper (Menu.Root) and wires selection/open callbacks. |
| packages/backpack-web/src/bpk-component-context-menu/src/BpkContextMenuItemGroup.tsx | Adds item group wrapper for layout/dividers. |
| packages/backpack-web/src/bpk-component-context-menu/src/BpkContextMenuItem.tsx | Adds menu item wrapper with variant, endIcon, and disabled support. |
| packages/backpack-web/src/bpk-component-context-menu/src/BpkContextMenuContent.tsx | Adds portalled content/positioner wrappers. |
| packages/backpack-web/src/bpk-component-context-menu/src/BpkContextMenu.tsx | Defines the namespaced API surface for the component. |
| packages/backpack-web/src/bpk-component-context-menu/src/BpkContextMenu.stories.tsx | Provides Storybook examples and Percy-friendly visual stories. |
| packages/backpack-web/src/bpk-component-context-menu/src/BpkContextMenu.module.scss | Adds styles for trigger, content surface, items, and animations. |
| packages/backpack-web/src/bpk-component-context-menu/src/BpkContextMenu-test.tsx | Adds unit tests for rendering, selection, variants, and slots. |
| packages/backpack-web/src/bpk-component-context-menu/index.ts | Exposes the component, constants, and selected public types. |
| packages/backpack-web/src/bpk-component-context-menu/README.md | Documents installation/usage/parts and accessibility notes. |
| packages/backpack-web/src/bpk-component-card-button/src/BpkSaveButton.tsx | Adds forwardRef, onClick, hoverEffect, and changes prop spreading. |
| packages/backpack-web/src/bpk-component-card-button/src/BpkSaveButton.module.scss | Adjusts focus styling for menu-trigger usage and adds “no-hover” modifiers. |
| .eslintrc | Allow-lists Ark Menu.* components for className prop usage. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Visit https://backpack.github.io/storybook-prs/4913 to see this build running in a browser. |
|
Visit https://backpack.github.io/storybook-prs/4913 to see this build running in a browser. |
|
Visit https://backpack.github.io/storybook-prs/4913 to see this build running in a browser. |
|
Can we include documents in the descriptions that will be useful for external review, as to why certain decisions were made and the figma design as well 🙏 |
…' into CAPY-2348/context-menu-component
|
Visit https://backpack.github.io/storybook-prs/4913 to see this build running in a browser. |
| flex-direction: column; | ||
| border-radius: tokens.$bpk-border-radius-lg; | ||
| outline: none; | ||
| background-color: var(--bpk-canvas, #{tokens.$bpk-canvas-day}); |
There was a problem hiding this comment.
--bpk-canvas does not exist, it should be --bpk-canvas-default
| background-color: var(--bpk-canvas, #{tokens.$bpk-canvas-day}); | |
| background-color: var(--bpk-canvas-default, #{tokens.$bpk-canvas-day}); |
| border: 0; | ||
| block-size: 0; | ||
| border-block-start: tokens.$bpk-border-size-sm solid | ||
| var(--bpk-line, #{tokens.$bpk-line-day}); |
There was a problem hiding this comment.
--bpk-line does not exist, can you double check?
I think it's --bpk-other-line-default, but not 100% sure


Summary
Adds a new
BpkContextMenucompound component wrapping Ark UI'sMenuprimitive, with accessible keyboard navigation, focus management, ARIA semantics, and floating positioning out of the box.For Backpack reviewers
https://backpack.github.io/storybook-prs/4913/?path=/docs/bpk-component-context-menu--documentation
New component:
BpkContextMenuNamespaced compound API:
.Root.Trigger<button>by default;asChildmerges props onto a custom element.SaveTrigger.Contentoverflow: hiddenancestors.ItemendIcon,destructivevariant, andonClick.ItemGroup.Separator.TriggerItemArchitecture decisions
BpkContextMenu.SaveTriggerowns the heart-button visual entirely within the context menu package — consumers get the correct visual without depending onBpkSaveButtonas an ArkasChildtrigger, avoiding coupling between the two componentsuseMenuTriggerFocusGuard— a shared hook used by bothTriggerandSaveTrigger. It tracks pointer vs keyboard interactions to suppress the:focus-visiblering after pointer-initiated close while preserving it for keyboard navigationunmountOnExitonMenu.Rootensures the menu is removed from the DOM after the close animation, preventing the invisible element from blocking pointer eventsBpkSaveButton— no functional changesThe initial draft of this PR composed
BpkSaveButtonas an ArkasChildtrigger, which required addingforwardRef,onClick,hoverEffect, and focus-ring overrides toBpkSaveButton. That approach was abandoned in favour ofBpkContextMenu.SaveTrigger.BpkSaveButtonis unchanged from its pre-PR state.ESLint:
Menu.TriggerandMenu.TriggerItemadded to theforbid-component-propsallowlist.Storybook + unit + accessibility tests included.
Consumer usage
README.md