Design doc: internal/design/ui/menus.md
Branch: feat/menu-ui-component (PR #1078)
Three PRs along the dependency chain:
PR 1 (Core + DOM) → PR 2 (UI flat) → PR 3 (Submenus)
Status: DONE — feat/menu-core-dom (PR #1503)
New:
packages/core/src/core/ui/menu/menu-core.tspackages/core/src/core/ui/menu/menu-data-attrs.tspackages/core/src/core/ui/menu/menu-item-data-attrs.tspackages/core/src/core/ui/menu/menu-css-vars.tspackages/core/src/core/ui/menu/tests/menu-core.test.tspackages/core/src/dom/ui/menu/create-menu.tspackages/core/src/dom/ui/menu/tests/create-menu.test.tspackages/core/src/dom/ui/menu/tests/create-menu-helpers.ts
Modified:
packages/core/src/core/index.ts— add menu exportspackages/core/src/dom/index.ts— add menu exportspackages/core/src/core/ui/transition.ts— extractTransitionDataAttrspackages/core/src/core/ui/popover/popover-data-attrs.ts— spreadTransitionDataAttrspackages/core/src/core/ui/tooltip/tooltip-data-attrs.ts— spreadTransitionDataAttrspackages/core/src/core/ui/alert-dialog/alert-dialog-data-attrs.ts— spreadTransitionDataAttrs
MenuCorefollowsPopoverCorepattern:setProps+setInput(TransitionState)+getState()isSubmenuprop onMenuCore— suppressespopover="manual"ingetContentAttrsand disables positioning props for nested menusMenuItemDataAttrsis not constrained byStateAttrMapsince items have their own state, notMenuStatedata-directionbelongs in DOM layer alongsideNavigationState, not in core constantscreateMenu()composescreatePopover()internally; items stored as ordered array (registration order matches DOM order for standard React list rendering)destroy()cancels the open RAF and typeahead timer before delegating topopover.destroy()- Open RAF guards against
status === 'ending'to prevent highlight firing during a rapid open/close
Status: PENDING — branch off feat/menu-core-dom
Status: PENDING
context.tsx,index.parts.ts,index.tsmenu-root.tsx,menu-trigger.tsx,menu-content.tsxmenu-item.tsx,menu-label.tsx,menu-separator.tsx,menu-group.tsxmenu-radio-group.tsx,menu-radio-item.tsx,menu-checkbox-item.tsx,menu-item-indicator.tsx
menu-element.ts,menu-item-element.ts,menu-label-element.ts,menu-separator-element.tsmenu-group-element.ts,menu-radio-group-element.ts,menu-radio-item-element.tsmenu-checkbox-item-element.ts,menu-item-indicator-element.ts
Modified:
packages/react/src/ui/index.ts— add Menu exportpackages/html/src/define/ui/menu.ts— registration barrelpackages/html/src/ui/index.ts— add menu exports
- Fully functional flat single-level menu with items, radio groups, checkboxes, labels, separators
- No nested Root / Back / submenu navigation — that comes in PR 4
Status: PENDING
New DOM:
packages/core/src/dom/ui/menu/create-sub-menu-transition.ts
New React:
packages/react/src/ui/menu/menu-back.tsx
New HTML:
packages/html/src/ui/menu/menu-back-element.ts
Modified:
packages/core/src/dom/ui/menu/create-menu.ts— addpush/poptoMenuApi,NavigationState, wire transitionpackages/react/src/ui/menu/menu-root.tsx— nested Root detects parent context → submenu modepackages/react/src/ui/menu/menu-content.tsx—data-submenu,data-direction, slide transition wiringpackages/html/src/ui/menu/menu-element.ts— nested<media-menu>+commandforsupportpackages/html/src/ui/menu/menu-item-element.ts—commandforattribute handlingpackages/core/src/dom/index.ts— add transition exportpackages/react/src/ui/index.ts— add Back to Menu exportspackages/html/src/define/ui/menu.ts— register<media-menu-back>
Status: PENDING — branch off feat/menu-react-html
NavigationState: stack of{ menuId, triggerId }, direction, exitingMenuId, transitioningcreateSubMenuTransition(): double-RAF lifecycle,--media-menu-width/heightmeasurement,getAnimations()settle- Nested
Menu.Rootdetection via parentMenuContext→isSubmenu: trueprop, Trigger registers as parent item Menu.Back/<media-menu-back>: pops stack, focus restoration to trigger- Auto-back on
RadioItemselection in submenu - RTL: direction-agnostic JS, CSS handles
translateXflip via[dir="rtl"]