Popup command collection with a trigger label, canonical open state, collection navigation, and one select event.
Install @wyrd-company/react or the Flutter package and use it directly —
your DESIGN.md does the styling.
catalog/contracts/menu.ymlsource of truth · verbatim
$schema: https://thewyrdingway.dev/schemas/component-contract.schema.ymlcontractVersion: 0.1.0identity:name: Menutag: wyrd-menupackage: wyrd.component.menutitle: Menusummary: Popup command collection with a trigger label, canonical open state, collection navigation, and one select event.relationships:related-to: - collection-navigation - behavior-menuclassification:category: navigationcomposition: collectioninteractive: truetarget-strategy:react: requiredflutter: requiredsurface:properties: - name: labeltype:kind: stringrequired: falsedefault: Menuserializable: truesummary: Trigger label and accessible-name source for the menu button. - name: itemstype:kind: arrayitem:kind: objectfields:id:kind: stringlabel:kind: stringdisabled:kind: booleanrequired: falsedefault: - id: editlabel: Edit - id: duplicatelabel: Duplicate - id: deletelabel: Deleteserializable: truesummary: Ordered menu item data; disabled items render but are skipped by collection navigation and activation. - name: is-opentype:kind: booleanrequired: falsedefault: falsecontrolled: truereflects: trueserializable: truesummary: Controlled popup visibility. - name: default-opentype:kind: booleanrequired: falsedefault: falseserializable: truesummary: Initial uncontrolled popup visibility. - name: is-disabledtype:kind: booleanrequired: falsedefault: falsereflects: trueserializable: truesummary: Prevents opening and item activation. - name: trigger-modetype:kind: enumvalues: - button - context-menurequired: falsedefault: buttonreflects: trueserializable: truesummary: Opens from the button or from a context-menu gesture on the trigger surface.slots: []events: - name: open-changepayload:is-open:kind: booleanreason:kind: enumvalues: - trigger - context-menu - escape - select - dismissbubbles: truecomposed: truecancelable: falsesummary: Canonical popup visibility event. - name: selectpayload:id:kind: stringlabel:kind: stringbubbles: truecomposed: truecancelable: truesummary: Canonical item activation event emitted once per accepted selection.states: - name: closedsource: behavior-runtimesummary: Popup content is not visible. - name: opensource: behavior-runtimesummary: Popup content is visible and collection navigation is active. - name: focus-visiblesource: platformsummary: Trigger or active item has keyboard-visible focus. - name: disabledsource: propertysummary: Disabled state derived from is-disabled.parts: - name: rootsummary: Menu root and positioning owner. - name: triggersummary: Interactive trigger control. - name: popupsummary: Popup surface. - name: itemsummary: Repeated menu item container.tokens:trigger:background: color.surfaceforeground: color.on-surfaceborder-color: color.outlinepadding-x: spacing.mdpadding-y: spacing.smpanel:background: color.surface-containerforeground: color.on-surfaceborder-color: color.outlineitem:active-background: color.primary-hoveractive-foreground: color.on-primarypadding-x: spacing.mdpadding-y: spacing.smradius: rounded.mdborder-width: 1pxgap: spacing.xspadding-x: spacing.xspadding-y: spacing.xsmessages: []obligations:accessibility:role: menuname: Label property provides the accessible name for the menu button.keyboard: - Enter, Space, ArrowDown, and ArrowUp open the menu from the trigger. - ArrowDown and ArrowUp move the active item while the popup is open. - Home and End move to the collection boundaries. - Typeahead moves to the next matching item. - Escape closes the menu and restores focus to the trigger. - Tab dismisses the menu and allows normal focus traversal. - In context-menu trigger mode, Shift+F10 and the ContextMenu key open the menu at the focused trigger surface.semantics: - Trigger exposes menu popup and expanded state. - Popup exposes menu semantics and active descendant state where supported. - Disabled menu prevents popup opening and item activation. - Disabled items remain visible but are skipped by keyboard navigation and do not activate. - Context-menu trigger mode keeps the trigger surface keyboard focusable and exposes menu popup state.behavior:model: collectionruntimeBlueprint: behavior/menuinteractions: - Opening at first or last item follows the committed menu behavior trace. - Collection navigation owns active item movement, disabled-item skipping, wrapping, and typeahead. - Selecting an item emits select and closes the popup. - Context-menu trigger mode opens at the pointer coordinates on contextmenu and at the trigger surface for keyboard invocation. - Web targets position the popup with the package flip/shift utility and a zero-size virtual anchor at the invocation coordinates. - Flutter opens context-menu trigger mode on long press and anchors the menu at the press position.hostEffects: - Move focus to the popup on open. - Restore focus to the trigger on close. - Dispatch item activation event. - Preserve the context-menu invocation point while the popup is open and recompute collision-aware positioning on viewport changes.conditions: - rtl - reduced-motion - cvd-deuteranopia - density-compactsdui:status: serializableserializableProperties: - label - items - is-open - default-open - is-disabled - trigger-modeserializableSlots: []eventBindings: - open-change - selectnotes: Menu item data and open state serialize; target runtimes own focus, positioning, and keyboard host effects.examples: - name: closedstate: closedproperties:label: Actionsitems: - id: editlabel: Edit - id: duplicatelabel: Duplicate - id: deletelabel: Deleteis-open: falseslots: {} - name: openstate: openproperties:label: Actionsitems: - id: editlabel: Edit - id: duplicatelabel: Duplicate - id: deletelabel: Deletedefault-open: trueslots: {} - name: disabledstate: disabledproperties:label: Actionsitems: - id: editlabel: Edit - id: duplicatelabel: Duplicate - id: deletelabel: Deleteis-disabled: trueslots: {} - name: context-menustate: closedproperties:label: File actionstrigger-mode: context-menuitems: - id: renamelabel: Rename - id: duplicatelabel: Duplicate - id: deletelabel: Deleteslots: {}
01
Examples
Generated from the contract's examples block.
Previews are the published @wyrd-company/react component, themed by the
brand's role tokens — flip the site's light/dark toggle and they follow.
Trigger label and accessible-name source for the menu button.
items
array
[object Object],[object Object],[object Object]
Ordered menu item data; disabled items render but are skipped by collection navigation and activation.
is-open
boolean
false
Controlled popup visibility.
default-open
boolean
false
Initial uncontrolled popup visibility.
is-disabled
boolean
false
Prevents opening and item activation.
trigger-mode
button | context-menu
button
Opens from the button or from a context-menu gesture on the trigger surface.
03
Slots & events
Event
Payload
Summary
open-change
is-open, reason
Canonical popup visibility event.
select
id, label
Canonical item activation event emitted once per accepted selection.
04
Tokens
The contract's token bindings. Open the shared contextual sidebar from any example;
primary swatches reflect the color you pick there. Error swatches show the active
preset's values; editing any knob switches to custom and resets error to TWW · Ink.
Binding
Token
trigger.background
color.surface
trigger.foreground
color.on-surface
trigger.border-color
color.outline
trigger.padding-x
spacing.md
trigger.padding-y
spacing.sm
panel.background
color.surface-container
panel.foreground
color.on-surface
panel.border-color
color.outline
item.active-background
color.primary-hover
item.active-foreground
color.on-primary
item.padding-x
spacing.md
item.padding-y
spacing.sm
radius
rounded.md
border-width
1px
gap
spacing.xs
padding-x
spacing.xs
padding-y
spacing.xs
05
States
State
Source
Summary
closed
behavior-runtime
Popup content is not visible.
open
behavior-runtime
Popup content is visible and collection navigation is active.
focus-visible
platform
Trigger or active item has keyboard-visible focus.
disabled
property
Disabled state derived from is-disabled.
06
Accessibility
From the contract's accessibility obligations. Role menu; Label property provides the accessible name for the menu button.
Enter, Space, ArrowDown, and ArrowUp open the menu from the trigger.
ArrowDown and ArrowUp move the active item while the popup is open.
Home and End move to the collection boundaries.
Typeahead moves to the next matching item.
Escape closes the menu and restores focus to the trigger.
Tab dismisses the menu and allows normal focus traversal.
In context-menu trigger mode, Shift+F10 and the ContextMenu key open the menu at the focused trigger surface.
Trigger exposes menu popup and expanded state.
Popup exposes menu semantics and active descendant state where supported.
Disabled menu prevents popup opening and item activation.
Disabled items remain visible but are skipped by keyboard navigation and do not activate.
Context-menu trigger mode keeps the trigger surface keyboard focusable and exposes menu popup state.