@commercetools/nimbus-mcp 0.1.0 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -14
- package/data/docs/route-manifest.json +10998 -0
- package/data/docs/routes/components-accessibility-visually-hidden.json +388 -0
- package/data/docs/routes/components-accessibility.json +34 -0
- package/data/docs/routes/components-buttons-button.json +715 -0
- package/data/docs/routes/components-buttons-icon-button.json +852 -0
- package/data/docs/routes/components-buttons-icon-toggle-button.json +594 -0
- package/data/docs/routes/components-buttons-split-button.json +670 -0
- package/data/docs/routes/components-buttons-toggle-button-group.json +722 -0
- package/data/docs/routes/components-buttons-toggle-button.json +689 -0
- package/data/docs/routes/components-buttons.json +36 -0
- package/data/docs/routes/components-data-display-badge.json +555 -0
- package/data/docs/routes/components-data-display-card.json +338 -0
- package/data/docs/routes/components-data-display-data-table.json +855 -0
- package/data/docs/routes/components-data-display-draggable-list.json +596 -0
- package/data/docs/routes/components-data-display-table.json +472 -0
- package/data/docs/routes/components-data-display-tag-group.json +535 -0
- package/data/docs/routes/components-data-display.json +34 -0
- package/data/docs/routes/components-feedback-alert.json +696 -0
- package/data/docs/routes/components-feedback-dialog.json +682 -0
- package/data/docs/routes/components-feedback-drawer.json +600 -0
- package/data/docs/routes/components-feedback-loading-spinner.json +415 -0
- package/data/docs/routes/components-feedback-progress-bar.json +661 -0
- package/data/docs/routes/components-feedback-toast.json +1040 -0
- package/data/docs/routes/components-feedback-tooltip.json +510 -0
- package/data/docs/routes/components-feedback.json +34 -0
- package/data/docs/routes/components-forms-field-errors.json +557 -0
- package/data/docs/routes/components-forms-form-field.json +848 -0
- package/data/docs/routes/components-forms-group.json +427 -0
- package/data/docs/routes/components-forms-localized-field.json +770 -0
- package/data/docs/routes/components-forms.json +37 -0
- package/data/docs/routes/components-inputs-calendar.json +611 -0
- package/data/docs/routes/components-inputs-checkbox.json +774 -0
- package/data/docs/routes/components-inputs-combo-box.json +761 -0
- package/data/docs/routes/components-inputs-date-input.json +628 -0
- package/data/docs/routes/components-inputs-date-picker.json +709 -0
- package/data/docs/routes/components-inputs-date-range-picker.json +599 -0
- package/data/docs/routes/components-inputs-money-input.json +721 -0
- package/data/docs/routes/components-inputs-multiline-text-input.json +611 -0
- package/data/docs/routes/components-inputs-number-input.json +647 -0
- package/data/docs/routes/components-inputs-password-input.json +576 -0
- package/data/docs/routes/components-inputs-radio-input.json +583 -0
- package/data/docs/routes/components-inputs-range-calendar.json +607 -0
- package/data/docs/routes/components-inputs-rich-text-input.json +599 -0
- package/data/docs/routes/components-inputs-scoped-search-input.json +570 -0
- package/data/docs/routes/components-inputs-search-input.json +588 -0
- package/data/docs/routes/components-inputs-select-input.json +960 -0
- package/data/docs/routes/components-inputs-switch.json +720 -0
- package/data/docs/routes/components-inputs-text-input.json +566 -0
- package/data/docs/routes/components-inputs-time-input.json +775 -0
- package/data/docs/routes/components-inputs.json +34 -0
- package/data/docs/routes/components-layout-box.json +501 -0
- package/data/docs/routes/components-layout-defaultpage.json +748 -0
- package/data/docs/routes/components-layout-flex.json +587 -0
- package/data/docs/routes/components-layout-grid.json +393 -0
- package/data/docs/routes/components-layout-modalpage.json +716 -0
- package/data/docs/routes/components-layout-pagecontent.json +673 -0
- package/data/docs/routes/components-layout-scrollarea.json +428 -0
- package/data/docs/routes/components-layout-separator.json +461 -0
- package/data/docs/routes/components-layout-simple-grid.json +519 -0
- package/data/docs/routes/components-layout-spacer.json +573 -0
- package/data/docs/routes/components-layout-stack.json +481 -0
- package/data/docs/routes/components-layout.json +34 -0
- package/data/docs/routes/components-media-avatar.json +427 -0
- package/data/docs/routes/components-media-icon.json +663 -0
- package/data/docs/routes/components-media-image.json +511 -0
- package/data/docs/routes/components-media-inline-svg.json +586 -0
- package/data/docs/routes/components-media.json +34 -0
- package/data/docs/routes/components-navigation-accordion.json +643 -0
- package/data/docs/routes/components-navigation-collapsible-motion.json +628 -0
- package/data/docs/routes/components-navigation-link.json +554 -0
- package/data/docs/routes/components-navigation-menu.json +546 -0
- package/data/docs/routes/components-navigation-pagination.json +502 -0
- package/data/docs/routes/components-navigation-steps.json +629 -0
- package/data/docs/routes/components-navigation-tabnav.json +546 -0
- package/data/docs/routes/components-navigation-tabs.json +635 -0
- package/data/docs/routes/components-navigation-toolbar.json +549 -0
- package/data/docs/routes/components-navigation.json +34 -0
- package/data/docs/routes/components-typography-code.json +39 -0
- package/data/docs/routes/components-typography-heading.json +402 -0
- package/data/docs/routes/components-typography-kbd.json +399 -0
- package/data/docs/routes/components-typography-list.json +593 -0
- package/data/docs/routes/components-typography-text.json +444 -0
- package/data/docs/routes/components-typography.json +34 -0
- package/data/docs/routes/components-utilities-nimbus-i18n-provider.json +295 -0
- package/data/docs/routes/components-utilities-nimbus-provider.json +663 -0
- package/data/docs/routes/components-utilities.json +34 -0
- package/data/docs/routes/components.json +33 -0
- package/data/docs/routes/home-contribute-adrs-adr0001-consumer-component-apis.json +314 -0
- package/data/docs/routes/home-contribute-adrs-adr0002-compound-component-extraction.json +160 -0
- package/data/docs/routes/home-contribute-adrs-adr0003-component-lifecycle-states.json +460 -0
- package/data/docs/routes/home-contribute-adrs.json +205 -0
- package/data/docs/routes/home-contribute-development-setup.json +213 -0
- package/data/docs/routes/home-contribute-stats.json +36 -0
- package/data/docs/routes/home-contribute.json +36 -0
- package/data/docs/routes/home-design-tokens-aspect-ratios.json +36 -0
- package/data/docs/routes/home-design-tokens-borders.json +35 -0
- package/data/docs/routes/home-design-tokens-colors.json +157 -0
- package/data/docs/routes/home-design-tokens-other-animations.json +119 -0
- package/data/docs/routes/home-design-tokens-other-blurs.json +36 -0
- package/data/docs/routes/home-design-tokens-other-breakpoints.json +61 -0
- package/data/docs/routes/home-design-tokens-other-cursors.json +36 -0
- package/data/docs/routes/home-design-tokens-other-z-indices.json +39 -0
- package/data/docs/routes/home-design-tokens-other.json +35 -0
- package/data/docs/routes/home-design-tokens-radii.json +59 -0
- package/data/docs/routes/home-design-tokens-shadows.json +57 -0
- package/data/docs/routes/home-design-tokens-sizes.json +137 -0
- package/data/docs/routes/home-design-tokens-spacing.json +36 -0
- package/data/docs/routes/home-design-tokens-typography.json +184 -0
- package/data/docs/routes/home-design-tokens.json +34 -0
- package/data/docs/routes/home-getting-started-core-concepts.json +301 -0
- package/data/docs/routes/home-getting-started-installation.json +621 -0
- package/data/docs/routes/home-getting-started-mcp-server-overview.json +139 -0
- package/data/docs/routes/home-getting-started-mcp-server-setup.json +316 -0
- package/data/docs/routes/home-getting-started-release-process.json +294 -0
- package/data/docs/routes/home-getting-started-testing-setup.json +296 -0
- package/data/docs/routes/home-playground-markdown.json +638 -0
- package/data/docs/routes/home-playground-toc.json +169 -0
- package/data/docs/routes/home-playground.json +34 -0
- package/data/docs/routes/home-style-props-background.json +236 -0
- package/data/docs/routes/home-style-props-border.json +310 -0
- package/data/docs/routes/home-style-props-display.json +120 -0
- package/data/docs/routes/home-style-props-effects.json +116 -0
- package/data/docs/routes/home-style-props-filters.json +396 -0
- package/data/docs/routes/home-style-props-flex-and-grid.json +496 -0
- package/data/docs/routes/home-style-props-interactivity.json +356 -0
- package/data/docs/routes/home-style-props-layout.json +422 -0
- package/data/docs/routes/home-style-props-list.json +116 -0
- package/data/docs/routes/home-style-props-sizing.json +244 -0
- package/data/docs/routes/home-style-props-spacing.json +228 -0
- package/data/docs/routes/home-style-props-svg.json +96 -0
- package/data/docs/routes/home-style-props-tables.json +116 -0
- package/data/docs/routes/home-style-props-transforms.json +216 -0
- package/data/docs/routes/home-style-props-transitions.json +216 -0
- package/data/docs/routes/home-style-props-typography.json +536 -0
- package/data/docs/routes/home-style-props.json +33 -0
- package/data/docs/routes/home.json +32 -0
- package/data/docs/routes/hooks-usecopytoclipboard.json +76 -0
- package/data/docs/routes/hooks-usehotkeys.json +117 -0
- package/data/docs/routes/hooks.json +33 -0
- package/data/docs/routes/icons.json +32 -0
- package/data/docs/routes/patterns-fields-date-range-picker-field.json +393 -0
- package/data/docs/routes/patterns-fields-money-input-field.json +415 -0
- package/data/docs/routes/patterns-fields-multiline-text-input-field.json +404 -0
- package/data/docs/routes/patterns-fields-number-input-field.json +470 -0
- package/data/docs/routes/patterns-fields-password-input-field.json +319 -0
- package/data/docs/routes/patterns-fields-search-input-field.json +382 -0
- package/data/docs/routes/patterns-fields-text-input-field.json +404 -0
- package/data/docs/routes/patterns-fields.json +78 -0
- package/data/docs/routes/patterns.json +34 -0
- package/data/docs/search-index.json +1 -0
- package/data/docs/types/Accordion.json +12 -0
- package/data/docs/types/AccordionContent.json +286 -0
- package/data/docs/types/AccordionHeader.json +891 -0
- package/data/docs/types/AccordionHeaderRightContent.json +27 -0
- package/data/docs/types/AccordionItem.json +242 -0
- package/data/docs/types/AccordionRoot.json +162 -0
- package/data/docs/types/Alert.json +12 -0
- package/data/docs/types/AlertActions.json +11 -0
- package/data/docs/types/AlertDescription.json +118 -0
- package/data/docs/types/AlertDismissButton.json +937 -0
- package/data/docs/types/AlertRoot.json +42 -0
- package/data/docs/types/AlertTitle.json +118 -0
- package/data/docs/types/Avatar.json +125 -0
- package/data/docs/types/Badge.json +64 -0
- package/data/docs/types/Body.json +67 -0
- package/data/docs/types/Box.json +85 -0
- package/data/docs/types/Button.json +1015 -0
- package/data/docs/types/Calendar.json +565 -0
- package/data/docs/types/Caption.json +67 -0
- package/data/docs/types/Card.json +12 -0
- package/data/docs/types/CardContent.json +27 -0
- package/data/docs/types/CardHeader.json +27 -0
- package/data/docs/types/CardRoot.json +106 -0
- package/data/docs/types/Cell.json +227 -0
- package/data/docs/types/Checkbox.json +897 -0
- package/data/docs/types/Code.json +112 -0
- package/data/docs/types/CollapsibleMotionContent.json +35 -0
- package/data/docs/types/CollapsibleMotionRoot.json +99 -0
- package/data/docs/types/CollapsibleMotionTrigger.json +71 -0
- package/data/docs/types/Column.json +101 -0
- package/data/docs/types/ColumnGroup.json +101 -0
- package/data/docs/types/ColumnHeader.json +193 -0
- package/data/docs/types/ComboBoxListBox.json +751 -0
- package/data/docs/types/ComboBoxOption.json +672 -0
- package/data/docs/types/ComboBoxPopover.json +786 -0
- package/data/docs/types/ComboBoxRoot.json +747 -0
- package/data/docs/types/ComboBoxSection.json +277 -0
- package/data/docs/types/ComboBoxTrigger.json +70 -0
- package/data/docs/types/Content.json +33 -0
- package/data/docs/types/DataTable.json +596 -0
- package/data/docs/types/DataTableBody.json +223 -0
- package/data/docs/types/DataTableFooter.json +27 -0
- package/data/docs/types/DataTableHeader.json +269 -0
- package/data/docs/types/DataTableManager.json +11 -0
- package/data/docs/types/DataTableRoot.json +590 -0
- package/data/docs/types/DataTableTable.json +271 -0
- package/data/docs/types/DateInput.json +792 -0
- package/data/docs/types/DatePicker.json +700 -0
- package/data/docs/types/DateRangePicker.json +936 -0
- package/data/docs/types/DateRangePickerField.json +1047 -0
- package/data/docs/types/DefaultPage.json +12 -0
- package/data/docs/types/DefaultPageActions.json +27 -0
- package/data/docs/types/DefaultPageBackLink.json +213 -0
- package/data/docs/types/DefaultPageContent.json +27 -0
- package/data/docs/types/DefaultPageFooter.json +27 -0
- package/data/docs/types/DefaultPageHeader.json +27 -0
- package/data/docs/types/DefaultPageRoot.json +106 -0
- package/data/docs/types/DefaultPageSubtitle.json +27 -0
- package/data/docs/types/DefaultPageTabNav.json +28 -0
- package/data/docs/types/DefaultPageTitle.json +27 -0
- package/data/docs/types/DialogBody.json +27 -0
- package/data/docs/types/DialogCloseTrigger.json +939 -0
- package/data/docs/types/DialogContent.json +27 -0
- package/data/docs/types/DialogFooter.json +27 -0
- package/data/docs/types/DialogHeader.json +27 -0
- package/data/docs/types/DialogRoot.json +138 -0
- package/data/docs/types/DialogTitle.json +27 -0
- package/data/docs/types/DialogTrigger.json +80 -0
- package/data/docs/types/DraggableList.json +12 -0
- package/data/docs/types/DraggableListField.json +894 -0
- package/data/docs/types/DraggableListItem.json +574 -0
- package/data/docs/types/DraggableListRoot.json +745 -0
- package/data/docs/types/Drawer.json +12 -0
- package/data/docs/types/DrawerBody.json +27 -0
- package/data/docs/types/DrawerCloseTrigger.json +939 -0
- package/data/docs/types/DrawerContent.json +27 -0
- package/data/docs/types/DrawerFooter.json +27 -0
- package/data/docs/types/DrawerHeader.json +27 -0
- package/data/docs/types/DrawerRoot.json +142 -0
- package/data/docs/types/DrawerTitle.json +27 -0
- package/data/docs/types/DrawerTrigger.json +80 -0
- package/data/docs/types/FieldErrors.getBuiltInMessage.json +11 -0
- package/data/docs/types/FieldErrors.getCustomMessage.json +9 -0
- package/data/docs/types/FieldErrors.json +109 -0
- package/data/docs/types/Flex.json +238 -0
- package/data/docs/types/Footer.json +67 -0
- package/data/docs/types/FormFieldDescription.json +11 -0
- package/data/docs/types/FormFieldError.json +11 -0
- package/data/docs/types/FormFieldInfoBox.json +27 -0
- package/data/docs/types/FormFieldInput.json +11 -0
- package/data/docs/types/FormFieldLabel.json +11 -0
- package/data/docs/types/FormFieldRoot.json +148 -0
- package/data/docs/types/Grid.json +253 -0
- package/data/docs/types/GridProps.json +11 -0
- package/data/docs/types/Group.json +143 -0
- package/data/docs/types/Header.json +67 -0
- package/data/docs/types/Heading.json +109 -0
- package/data/docs/types/Icon.json +112 -0
- package/data/docs/types/IconButton.json +1019 -0
- package/data/docs/types/IconToggleButton.json +787 -0
- package/data/docs/types/Image.json +373 -0
- package/data/docs/types/Indicator.json +67 -0
- package/data/docs/types/InlineSvg.json +98 -0
- package/data/docs/types/Item.json +67 -0
- package/data/docs/types/Kbd.json +118 -0
- package/data/docs/types/Link.json +380 -0
- package/data/docs/types/List.json +12 -0
- package/data/docs/types/ListIndicator.json +70 -0
- package/data/docs/types/ListItem.json +70 -0
- package/data/docs/types/ListRoot.json +124 -0
- package/data/docs/types/LoadingSpinner.json +87 -0
- package/data/docs/types/LocalizedField.json +460 -0
- package/data/docs/types/LocalizedStringFormatter.json +9 -0
- package/data/docs/types/MakeElementFocusable.json +196 -0
- package/data/docs/types/MenuContent.json +111 -0
- package/data/docs/types/MenuItem.json +671 -0
- package/data/docs/types/MenuRoot.json +670 -0
- package/data/docs/types/MenuSection.json +364 -0
- package/data/docs/types/MenuSubmenu.json +111 -0
- package/data/docs/types/MenuSubmenuTrigger.json +67 -0
- package/data/docs/types/MenuTrigger.json +906 -0
- package/data/docs/types/ModalPage.json +12 -0
- package/data/docs/types/ModalPageActions.json +27 -0
- package/data/docs/types/ModalPageContent.json +27 -0
- package/data/docs/types/ModalPageFooter.json +27 -0
- package/data/docs/types/ModalPageHeader.json +27 -0
- package/data/docs/types/ModalPageRoot.json +87 -0
- package/data/docs/types/ModalPageSubtitle.json +27 -0
- package/data/docs/types/ModalPageTabNav.json +28 -0
- package/data/docs/types/ModalPageTitle.json +27 -0
- package/data/docs/types/ModalPageTopBar.json +57 -0
- package/data/docs/types/MoneyInput.isEmpty.json +40 -0
- package/data/docs/types/MoneyInput.json +282 -0
- package/data/docs/types/MoneyInputField.json +379 -0
- package/data/docs/types/MoneyInputFieldProps.json +9 -0
- package/data/docs/types/MultilineTextInput.json +1194 -0
- package/data/docs/types/MultilineTextInputField.json +1269 -0
- package/data/docs/types/MultilineTextInputFieldProps.json +9 -0
- package/data/docs/types/NimbusI18nProvider.json +42 -0
- package/data/docs/types/NimbusI18nProviderProps.json +9 -0
- package/data/docs/types/NimbusProvider.json +270 -0
- package/data/docs/types/NumberInput.json +952 -0
- package/data/docs/types/NumberInputField.json +1004 -0
- package/data/docs/types/NumberInputFieldProps.json +9 -0
- package/data/docs/types/PageContent.json +11 -0
- package/data/docs/types/PageContentColumn.json +99 -0
- package/data/docs/types/PageContentRoot.json +114 -0
- package/data/docs/types/Pagination.json +159 -0
- package/data/docs/types/PasswordInput.json +1120 -0
- package/data/docs/types/PasswordInputField.json +1216 -0
- package/data/docs/types/PasswordInputFieldProps.json +9 -0
- package/data/docs/types/ProgressBar.json +280 -0
- package/data/docs/types/RadioInputOption.json +550 -0
- package/data/docs/types/RadioInputRoot.json +514 -0
- package/data/docs/types/RangeCalendar.json +618 -0
- package/data/docs/types/RichTextInput.json +134 -0
- package/data/docs/types/Root.json +122 -0
- package/data/docs/types/Row.json +67 -0
- package/data/docs/types/ScopedSearchInput.isEmpty.json +40 -0
- package/data/docs/types/ScopedSearchInput.json +253 -0
- package/data/docs/types/ScrollArea.json +179 -0
- package/data/docs/types/ScrollAreaElementIds.json +9 -0
- package/data/docs/types/ScrollAreaProps.json +9 -0
- package/data/docs/types/SearchInput.json +1165 -0
- package/data/docs/types/SearchInputField.json +1240 -0
- package/data/docs/types/Select.json +12 -0
- package/data/docs/types/SelectOption.json +572 -0
- package/data/docs/types/SelectOptionGroup.json +215 -0
- package/data/docs/types/SelectOptions.json +693 -0
- package/data/docs/types/SelectRoot.json +926 -0
- package/data/docs/types/Separator.json +65 -0
- package/data/docs/types/SimpleGrid.json +291 -0
- package/data/docs/types/Spacer.json +27 -0
- package/data/docs/types/SpacerProps.json +9 -0
- package/data/docs/types/SplitButton.json +203 -0
- package/data/docs/types/Stack.json +144 -0
- package/data/docs/types/Steps.json +12 -0
- package/data/docs/types/StepsChangeDetails.json +9 -0
- package/data/docs/types/StepsCompletedContent.json +28 -0
- package/data/docs/types/StepsCompletedContentProps.json +9 -0
- package/data/docs/types/StepsContent.json +43 -0
- package/data/docs/types/StepsContentProps.json +9 -0
- package/data/docs/types/StepsDescription.json +28 -0
- package/data/docs/types/StepsDescriptionProps.json +9 -0
- package/data/docs/types/StepsIndicator.json +28 -0
- package/data/docs/types/StepsIndicatorProps.json +9 -0
- package/data/docs/types/StepsItem.json +43 -0
- package/data/docs/types/StepsItemProps.json +9 -0
- package/data/docs/types/StepsList.json +28 -0
- package/data/docs/types/StepsListProps.json +9 -0
- package/data/docs/types/StepsNextTrigger.json +62 -0
- package/data/docs/types/StepsNextTriggerProps.json +9 -0
- package/data/docs/types/StepsNumber.json +28 -0
- package/data/docs/types/StepsNumberProps.json +9 -0
- package/data/docs/types/StepsPrevTrigger.json +62 -0
- package/data/docs/types/StepsPrevTriggerProps.json +9 -0
- package/data/docs/types/StepsRoot.json +183 -0
- package/data/docs/types/StepsRootProps.json +11 -0
- package/data/docs/types/StepsSeparator.json +28 -0
- package/data/docs/types/StepsSeparatorProps.json +9 -0
- package/data/docs/types/StepsStatus.json +57 -0
- package/data/docs/types/StepsStatusProps.json +9 -0
- package/data/docs/types/StepsTitle.json +28 -0
- package/data/docs/types/StepsTitleProps.json +9 -0
- package/data/docs/types/StepsTrigger.json +47 -0
- package/data/docs/types/StepsTriggerProps.json +9 -0
- package/data/docs/types/Switch.json +371 -0
- package/data/docs/types/TabListProps.json +9 -0
- package/data/docs/types/TabNav.json +12 -0
- package/data/docs/types/TabNavItem.json +300 -0
- package/data/docs/types/TabNavItemProps.json +9 -0
- package/data/docs/types/TabNavProps.json +9 -0
- package/data/docs/types/TabNavRoot.json +80 -0
- package/data/docs/types/TabPanelProps.json +9 -0
- package/data/docs/types/TabPanelsProps.json +9 -0
- package/data/docs/types/TabProps.json +9 -0
- package/data/docs/types/Table.json +9 -0
- package/data/docs/types/TableBody.json +67 -0
- package/data/docs/types/TableBodyProps.json +9 -0
- package/data/docs/types/TableCaption.json +67 -0
- package/data/docs/types/TableCaptionProps.json +9 -0
- package/data/docs/types/TableCell.json +227 -0
- package/data/docs/types/TableCellProps.json +9 -0
- package/data/docs/types/TableColumn.json +101 -0
- package/data/docs/types/TableColumnGroup.json +101 -0
- package/data/docs/types/TableColumnGroupProps.json +9 -0
- package/data/docs/types/TableColumnHeader.json +193 -0
- package/data/docs/types/TableColumnHeaderProps.json +9 -0
- package/data/docs/types/TableColumnProps.json +9 -0
- package/data/docs/types/TableFooter.json +67 -0
- package/data/docs/types/TableFooterProps.json +9 -0
- package/data/docs/types/TableHeader.json +67 -0
- package/data/docs/types/TableHeaderProps.json +9 -0
- package/data/docs/types/TableRoot.json +365 -0
- package/data/docs/types/TableRootProps.json +12 -0
- package/data/docs/types/TableRow.json +67 -0
- package/data/docs/types/TableRowProps.json +9 -0
- package/data/docs/types/TableScrollArea.json +82 -0
- package/data/docs/types/TableScrollAreaProps.json +9 -0
- package/data/docs/types/Tabs.json +12 -0
- package/data/docs/types/TabsList.json +110 -0
- package/data/docs/types/TabsPanel.json +112 -0
- package/data/docs/types/TabsPanels.json +108 -0
- package/data/docs/types/TabsRoot.json +211 -0
- package/data/docs/types/TabsTab.json +174 -0
- package/data/docs/types/TagGroup.json +12 -0
- package/data/docs/types/TagGroupRoot.json +306 -0
- package/data/docs/types/TagGroupTag.json +595 -0
- package/data/docs/types/TagGroupTagList.json +166 -0
- package/data/docs/types/Text.json +119 -0
- package/data/docs/types/TextInput.json +1156 -0
- package/data/docs/types/TextInputField.json +1263 -0
- package/data/docs/types/TimeInput.json +752 -0
- package/data/docs/types/ToastAction.json +9 -0
- package/data/docs/types/ToastManagerApi.json +9 -0
- package/data/docs/types/ToastOptions.json +9 -0
- package/data/docs/types/ToastOutlet.json +12 -0
- package/data/docs/types/ToastPlacement.json +9 -0
- package/data/docs/types/ToastPromiseOptions.json +9 -0
- package/data/docs/types/ToastType.json +9 -0
- package/data/docs/types/ToastVariant.json +9 -0
- package/data/docs/types/ToggleButton.json +789 -0
- package/data/docs/types/ToggleButtonGroup.json +9 -0
- package/data/docs/types/ToggleButtonGroupButton.json +331 -0
- package/data/docs/types/ToggleButtonGroupRoot.json +269 -0
- package/data/docs/types/Toolbar.json +176 -0
- package/data/docs/types/Tooltip.json +12 -0
- package/data/docs/types/TooltipContent.json +372 -0
- package/data/docs/types/TooltipRoot.json +179 -0
- package/data/docs/types/Trigger.json +69 -0
- package/data/docs/types/VisuallyHidden.json +93 -0
- package/data/docs/types/__object.json +12 -0
- package/data/docs/types/filters.json +11 -0
- package/data/docs/types/manifest.json +280 -0
- package/data/docs/types/toast.json +234 -0
- package/data/docs/types/useColorMode.json +13 -0
- package/data/docs/types/useColorModeValue.json +13 -0
- package/data/docs/types/useColorScheme.json +12 -0
- package/data/docs/types/useLocalizedStringFormatter.json +14 -0
- package/data/icons.json +21940 -0
- package/data/tokens.json +40061 -0
- package/dist/index.js +2516 -17
- package/package.json +25 -6
- package/dist/data-loader.d.ts +0 -102
- package/dist/data-loader.js +0 -104
- package/dist/index.d.ts +0 -13
- package/dist/server.d.ts +0 -9
- package/dist/server.js +0 -22
- package/dist/server.spec.d.ts +0 -1
- package/dist/server.spec.js +0 -69
- package/dist/tools/list-components.d.ts +0 -9
- package/dist/tools/list-components.js +0 -42
- package/dist/types.d.ts +0 -28
- package/dist/types.js +0 -4
- package/src/data-loader.ts +0 -226
- package/src/index.ts +0 -29
- package/src/server.spec.ts +0 -86
- package/src/server.ts +0 -28
- package/src/tools/list-components.ts +0 -49
- package/src/types.ts +0 -31
- package/tsconfig.json +0 -14
- package/vitest.config.ts +0 -9
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"id": "Components-Menu",
|
|
4
|
+
"title": "Menu",
|
|
5
|
+
"exportName": "Menu",
|
|
6
|
+
"description": "A temporary surface that displays a list of choices or actions. It typically appears when a user interacts with an element like a button or icon, or performs a specific action.",
|
|
7
|
+
"lifecycleState": "Stable",
|
|
8
|
+
"order": 999,
|
|
9
|
+
"repoPath": "packages/nimbus/src/components/menu/menu.mdx",
|
|
10
|
+
"menu": [
|
|
11
|
+
"Components",
|
|
12
|
+
"Navigation",
|
|
13
|
+
"Menu"
|
|
14
|
+
],
|
|
15
|
+
"route": "components/navigation/menu",
|
|
16
|
+
"tags": [
|
|
17
|
+
"component",
|
|
18
|
+
"menu",
|
|
19
|
+
"dropdown",
|
|
20
|
+
"actions",
|
|
21
|
+
"context menu"
|
|
22
|
+
],
|
|
23
|
+
"toc": [
|
|
24
|
+
{
|
|
25
|
+
"value": "Overview",
|
|
26
|
+
"href": "#overview",
|
|
27
|
+
"depth": 2,
|
|
28
|
+
"numbering": [
|
|
29
|
+
1,
|
|
30
|
+
1
|
|
31
|
+
],
|
|
32
|
+
"parent": "root"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"value": "Resources",
|
|
36
|
+
"href": "#resources",
|
|
37
|
+
"depth": 3,
|
|
38
|
+
"numbering": [
|
|
39
|
+
1,
|
|
40
|
+
1,
|
|
41
|
+
1
|
|
42
|
+
],
|
|
43
|
+
"parent": "root"
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
"figmaLink": "https://www.figma.com/design/AvtPX6g7OGGCRvNlatGOIY/NIMBUS-design-system?node-id=346-2569",
|
|
47
|
+
"layout": "app-frame",
|
|
48
|
+
"tabs": [
|
|
49
|
+
{
|
|
50
|
+
"key": "overview",
|
|
51
|
+
"title": "Overview",
|
|
52
|
+
"order": 0
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"key": "guidelines",
|
|
56
|
+
"title": "Guidelines",
|
|
57
|
+
"order": 2
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"key": "dev",
|
|
61
|
+
"title": "Implementation",
|
|
62
|
+
"order": 3
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"key": "a11y",
|
|
66
|
+
"title": "Accessibility",
|
|
67
|
+
"order": 4
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
"mdx": "\n## Overview\n\nMenus present short, actionable items in a vertical list, ensuring easy\nnavigation and selection. They display below the trigger with a 8px space. To\nclose a menu, a user makes a selection, or in the case several selections may be\nmade, after a confirm button or a click off the active area.\n\n### Resources\n\nDeep dive into implementation details and access the Nimbus design library.\n\n[React ARIA](https://react-spectrum.adobe.com/react-aria/Menu.html)\n[ARIA Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menu/)\n[Figma library](https://www.figma.com/design/AvtPX6g7OGGCRvNlatGOIY/NIMBUS-design-system?node-id=346-2569)\n",
|
|
72
|
+
"views": {
|
|
73
|
+
"overview": {
|
|
74
|
+
"mdx": "\n## Overview\n\nMenus present short, actionable items in a vertical list, ensuring easy\nnavigation and selection. They display below the trigger with a 8px space. To\nclose a menu, a user makes a selection, or in the case several selections may be\nmade, after a confirm button or a click off the active area.\n\n### Resources\n\nDeep dive into implementation details and access the Nimbus design library.\n\n[React ARIA](https://react-spectrum.adobe.com/react-aria/Menu.html)\n[ARIA Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menu/)\n[Figma library](https://www.figma.com/design/AvtPX6g7OGGCRvNlatGOIY/NIMBUS-design-system?node-id=346-2569)\n",
|
|
75
|
+
"toc": [
|
|
76
|
+
{
|
|
77
|
+
"value": "Overview",
|
|
78
|
+
"href": "#overview",
|
|
79
|
+
"depth": 2,
|
|
80
|
+
"numbering": [
|
|
81
|
+
1,
|
|
82
|
+
1
|
|
83
|
+
],
|
|
84
|
+
"parent": "root"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"value": "Resources",
|
|
88
|
+
"href": "#resources",
|
|
89
|
+
"depth": 3,
|
|
90
|
+
"numbering": [
|
|
91
|
+
1,
|
|
92
|
+
1,
|
|
93
|
+
1
|
|
94
|
+
],
|
|
95
|
+
"parent": "root"
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
"a11y": {
|
|
100
|
+
"mdx": "\n## Accessibility\n\nA dropdown popover is a temporary, compact list of options or actions that\nappears on user interaction, designed for quick selections and efficient\nnavigation.\n\n```jsx live\nconst App = () => (\n <Menu.Root>\n <Menu.Trigger asChild>\n <Button variant=\"solid\" colorPalette=\"primary\">\n <Icons.FolderOpen />\n File Menu\n </Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"duplicate\">\n <Icon slot=\"icon\"><Icons.ContentCopy /></Icon>\n <Text slot=\"label\">Duplicate</Text>\n <Kbd slot=\"keyboard\">⌘T</Kbd>\n </Menu.Item>\n <Menu.Item id=\"rename\">\n <Icon slot=\"icon\"><Icons.Create /></Icon>\n <Text slot=\"label\">Rename</Text>\n <Kbd slot=\"keyboard\">⌘R</Kbd>\n </Menu.Item>\n <Menu.Item id=\"share\">\n <Icon slot=\"icon\"><Icons.IosShare /></Icon>\n <Text slot=\"label\">Share</Text>\n <Kbd slot=\"keyboard\">⌘W</Kbd>\n </Menu.Item>\n <Menu.Item id=\"pin\">\n <Icon slot=\"icon\"><Icons.PushPin /></Icon>\n <Text slot=\"label\">Pin</Text>\n <Kbd slot=\"keyboard\">⌘P</Kbd>\n </Menu.Item>\n <Separator />\n <Menu.Item id=\"delete\" isCritical>\n <Icon slot=\"icon\"><Icons.Delete /></Icon>\n <Text slot=\"label\">Delete</Text>\n <Kbd slot=\"keyboard\">⌘D</Kbd>\n </Menu.Item>\n </Menu.Content>\n </Menu.Root>\n);\n```\n\n### Accessibility standards\n\n- **Keyboard Navigation:** Ensure users can open, navigate (arrow keys), select\n (Enter/Space), and close (Esc) the menu using only the keyboard.\n- **ARIA Roles & States:** Properly apply ARIA roles (e.g., `role=\"menu\"`,\n `role=\"menuitem\"`, `aria-haspopup`) and states (e.g., `aria-expanded`,\n `aria-checked`) to convey semantic meaning.\n- **Focus Management:** Confirm focus correctly moves into the menu when opened,\n cycles within it, and returns to the trigger when closed.\n- **Contrast & Visibility:** Verify sufficient color contrast for menu items and\n a clear visual focus indicator for selected/hovered items.\n",
|
|
101
|
+
"toc": [
|
|
102
|
+
{
|
|
103
|
+
"value": "Accessibility",
|
|
104
|
+
"href": "#accessibility",
|
|
105
|
+
"depth": 2,
|
|
106
|
+
"numbering": [
|
|
107
|
+
1,
|
|
108
|
+
1
|
|
109
|
+
],
|
|
110
|
+
"parent": "root"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"value": "Accessibility standards",
|
|
114
|
+
"href": "#accessibility-standards",
|
|
115
|
+
"depth": 3,
|
|
116
|
+
"numbering": [
|
|
117
|
+
1,
|
|
118
|
+
1,
|
|
119
|
+
1
|
|
120
|
+
],
|
|
121
|
+
"parent": "root"
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
},
|
|
125
|
+
"dev": {
|
|
126
|
+
"mdx": "\n## Getting started\n\n### Import\n\n```tsx\nimport { Menu, type MenuRootProps, type MenuItemProps } from '@commercetools/nimbus';\n```\n\n### Basic usage\n\nThe simplest implementation creates an action menu with items:\n\n```jsx live-dev\nconst App = () => (\n <Menu.Root onAction={(key) => alert(`Action: ${key}`)}>\n <Menu.Trigger>Actions</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"edit\">Edit</Menu.Item>\n <Menu.Item id=\"duplicate\">Duplicate</Menu.Item>\n <Menu.Item id=\"delete\">Delete</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n)\n```\n\n## Usage examples\n\n### Custom triggers\n\nUse `asChild` to render custom trigger elements like Button or IconButton:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"row\" gap=\"400\">\n <Menu.Root>\n <Menu.Trigger asChild>\n <Button variant=\"solid\" colorPalette=\"primary\">\n <Icons.KeyboardArrowDown />\n Button Trigger\n </Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"option1\">Option 1</Menu.Item>\n <Menu.Item id=\"option2\">Option 2</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n\n <Menu.Root>\n <Menu.Trigger asChild>\n <IconButton\n variant=\"ghost\"\n colorPalette=\"neutral\"\n aria-label=\"More options\"\n >\n <Icons.MoreVert />\n </IconButton>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"edit\">Edit</Menu.Item>\n <Menu.Item id=\"delete\">Delete</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n </Stack>\n)\n```\n\n### Menu placement\n\nControl where the menu appears relative to the trigger with the `placement` prop:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"row\" gap=\"400\">\n <Menu.Root placement=\"bottom start\">\n <Menu.Trigger asChild>\n <Button variant=\"outline\">Bottom Start</Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"1\">Item 1</Menu.Item>\n <Menu.Item id=\"2\">Item 2</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n\n <Menu.Root placement=\"bottom end\">\n <Menu.Trigger asChild>\n <Button variant=\"outline\">Bottom End</Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"1\">Item 1</Menu.Item>\n <Menu.Item id=\"2\">Item 2</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n\n <Menu.Root placement=\"right\">\n <Menu.Trigger asChild>\n <Button variant=\"outline\">Right</Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"1\">Item 1</Menu.Item>\n <Menu.Item id=\"2\">Item 2</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n </Stack>\n)\n```\n\n### Rich item content\n\nMenu items support icons, labels, descriptions, and keyboard shortcuts using slots:\n\n```jsx live-dev\nconst App = () => (\n <Menu.Root>\n <Menu.Trigger>Edit Menu</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"copy\">\n <Icon slot=\"icon\"><Icons.ContentCopy /></Icon>\n <Text slot=\"label\">Copy</Text>\n <Text slot=\"description\">Copy to clipboard</Text>\n <Kbd slot=\"keyboard\">⌘C</Kbd>\n </Menu.Item>\n <Menu.Item id=\"paste\">\n <Icon slot=\"icon\"><Icons.ContentPaste /></Icon>\n <Text slot=\"label\">Paste</Text>\n <Text slot=\"description\">Paste from clipboard</Text>\n <Kbd slot=\"keyboard\">⌘V</Kbd>\n </Menu.Item>\n <Menu.Item id=\"cut\">\n <Icon slot=\"icon\"><Icons.ContentCut /></Icon>\n <Text slot=\"label\">Cut</Text>\n <Kbd slot=\"keyboard\">⌘X</Kbd>\n </Menu.Item>\n </Menu.Content>\n </Menu.Root>\n)\n```\n\n### Critical items\n\nUse `isCritical` to highlight destructive actions:\n\n```jsx live-dev\nconst App = () => (\n <Menu.Root>\n <Menu.Trigger>File Actions</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"rename\">\n <Icon slot=\"icon\"><Icons.Edit /></Icon>\n <Text slot=\"label\">Rename</Text>\n </Menu.Item>\n <Menu.Item id=\"archive\">\n <Icon slot=\"icon\"><Icons.Archive /></Icon>\n <Text slot=\"label\">Archive</Text>\n </Menu.Item>\n <Separator />\n <Menu.Item id=\"delete\" isCritical>\n <Icon slot=\"icon\"><Icons.Delete /></Icon>\n <Text slot=\"label\">Delete</Text>\n <Text slot=\"description\">This action cannot be undone</Text>\n </Menu.Item>\n </Menu.Content>\n </Menu.Root>\n)\n```\n\n### Disabled items\n\nUse `isDisabled` on individual items to prevent interaction:\n\n```jsx live-dev\nconst App = () => (\n <Menu.Root>\n <Menu.Trigger>Edit</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"undo\">\n <Text slot=\"label\">Undo</Text>\n <Kbd slot=\"keyboard\">⌘Z</Kbd>\n </Menu.Item>\n <Menu.Item id=\"redo\" isDisabled>\n <Text slot=\"label\">Redo</Text>\n <Text slot=\"description\">Nothing to redo</Text>\n <Kbd slot=\"keyboard\">⌘⇧Z</Kbd>\n </Menu.Item>\n <Separator />\n <Menu.Item id=\"paste\" isDisabled>\n <Text slot=\"label\">Paste</Text>\n <Text slot=\"description\">Clipboard is empty</Text>\n <Kbd slot=\"keyboard\">⌘V</Kbd>\n </Menu.Item>\n </Menu.Content>\n </Menu.Root>\n)\n```\n\n### Sections with labels\n\nGroup related items using `Menu.Section` with a label:\n\n```jsx live-dev\nconst App = () => (\n <Menu.Root>\n <Menu.Trigger>Application Menu</Menu.Trigger>\n <Menu.Content>\n <Menu.Section label=\"File\">\n <Menu.Item id=\"new\">New Document</Menu.Item>\n <Menu.Item id=\"open\">Open</Menu.Item>\n <Menu.Item id=\"save\">Save</Menu.Item>\n </Menu.Section>\n <Separator />\n <Menu.Section label=\"Edit\">\n <Menu.Item id=\"undo\">Undo</Menu.Item>\n <Menu.Item id=\"redo\">Redo</Menu.Item>\n </Menu.Section>\n </Menu.Content>\n </Menu.Root>\n)\n```\n\n### Single selection mode\n\nUse `selectionMode=\"single\"` for radio-button-like behavior within a section:\n\n```jsx live-dev\nconst App = () => {\n const [selected, setSelected] = useState<string>(\"medium\");\n\n return (\n <Stack direction=\"row\" gap=\"400\" alignItems=\"center\">\n <Menu.Root\n selectionMode=\"single\"\n selectedKeys={new Set([selected])}\n onSelectionChange={(keys) => {\n if (keys !== \"all\") {\n const newKey = Array.from(keys)[0] as string;\n setSelected(newKey);\n }\n }}\n >\n <Menu.Trigger asChild>\n <Button variant=\"outline\">Text Size: {selected}</Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Section label=\"Choose Size\">\n <Menu.Item id=\"small\">\n <Text slot=\"label\">Small</Text>\n </Menu.Item>\n <Menu.Item id=\"medium\">\n <Text slot=\"label\">Medium</Text>\n </Menu.Item>\n <Menu.Item id=\"large\">\n <Text slot=\"label\">Large</Text>\n </Menu.Item>\n </Menu.Section>\n </Menu.Content>\n </Menu.Root>\n <Text fontSize=\"sm\">Selected: {selected}</Text>\n </Stack>\n );\n}\n```\n\n### Multiple selection mode\n\nUse `selectionMode=\"multiple\"` for checkbox-like behavior:\n\n```jsx live-dev\nconst App = () => {\n const [selected, setSelected] = useState<Set<string>>(new Set([\"bold\"]));\n\n return (\n <Stack direction=\"row\" gap=\"400\" alignItems=\"center\">\n <Menu.Root\n selectionMode=\"multiple\"\n selectedKeys={selected}\n onSelectionChange={(keys) => {\n if (keys !== \"all\") {\n setSelected(new Set(Array.from(keys) as string[]));\n }\n }}\n >\n <Menu.Trigger asChild>\n <Button variant=\"outline\">Text Formatting</Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Section label=\"Style Options\">\n <Menu.Item id=\"bold\">\n <Text slot=\"label\">Bold</Text>\n <Kbd slot=\"keyboard\">⌘B</Kbd>\n </Menu.Item>\n <Menu.Item id=\"italic\">\n <Text slot=\"label\">Italic</Text>\n <Kbd slot=\"keyboard\">⌘I</Kbd>\n </Menu.Item>\n <Menu.Item id=\"underline\">\n <Text slot=\"label\">Underline</Text>\n <Kbd slot=\"keyboard\">⌘U</Kbd>\n </Menu.Item>\n </Menu.Section>\n </Menu.Content>\n </Menu.Root>\n <Text fontSize=\"sm\">\n Selected: {Array.from(selected).join(\", \") || \"None\"}\n </Text>\n </Stack>\n );\n}\n```\n\n### Submenus\n\nCreate nested menus using `Menu.SubmenuTrigger` and `Menu.Submenu`:\n\n```jsx live-dev\nconst App = () => (\n <Menu.Root>\n <Menu.Trigger>Settings</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"general\">\n <Icon slot=\"icon\"><Icons.Settings /></Icon>\n <Text slot=\"label\">General</Text>\n </Menu.Item>\n <Menu.SubmenuTrigger>\n <Menu.Item>\n <Icon slot=\"icon\"><Icons.AccountCircle /></Icon>\n <Text slot=\"label\">Account</Text>\n <Text slot=\"description\">Manage your account</Text>\n </Menu.Item>\n <Menu.Submenu>\n <Menu.Item id=\"profile\">Profile</Menu.Item>\n <Menu.Item id=\"security\">Security</Menu.Item>\n <Menu.Item id=\"notifications\">Notifications</Menu.Item>\n </Menu.Submenu>\n </Menu.SubmenuTrigger>\n <Menu.SubmenuTrigger>\n <Menu.Item>\n <Icon slot=\"icon\"><Icons.Palette /></Icon>\n <Text slot=\"label\">Appearance</Text>\n </Menu.Item>\n <Menu.Submenu>\n <Menu.Item id=\"theme\">Theme</Menu.Item>\n <Menu.Item id=\"language\">Language</Menu.Item>\n </Menu.Submenu>\n </Menu.SubmenuTrigger>\n </Menu.Content>\n </Menu.Root>\n)\n```\n\n### Uncontrolled mode\n\nFor simpler use cases, use `defaultOpen` and `onOpenChange`:\n\n```jsx live-dev\nconst App = () => {\n const [lastAction, setLastAction] = useState<string>(\"None\");\n\n return (\n <Stack direction=\"column\" gap=\"400\">\n <Menu.Root\n onAction={(key) => setLastAction(key as string)}\n onOpenChange={(isOpen) => console.log(\"Menu open:\", isOpen)}\n placement=\"bottom end\"\n >\n <Menu.Trigger>Quick Actions</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"new\">New File</Menu.Item>\n <Menu.Item id=\"open\">Open</Menu.Item>\n <Menu.Item id=\"save\">Save</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n <Text fontSize=\"sm\">Last action: {lastAction}</Text>\n </Stack>\n );\n}\n```\n\n### Controlled mode\n\nFor programmatic control, use `isOpen` and `onOpenChange`:\n\n```jsx live-dev\nconst App = () => {\n const [isOpen, setIsOpen] = useState<boolean>(false);\n\n return (\n <Stack direction=\"row\" gap=\"400\" alignItems=\"center\">\n <Menu.Root isOpen={isOpen} onOpenChange={setIsOpen}>\n <Menu.Trigger>Controlled Menu</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"item1\">Item 1</Menu.Item>\n <Menu.Item id=\"item2\">Item 2</Menu.Item>\n <Menu.Item id=\"item3\">Item 3</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n <Button onClick={() => setIsOpen(!isOpen)}>\n {isOpen ? \"Close\" : \"Open\"} Menu\n </Button>\n <Text fontSize=\"sm\">Menu is {isOpen ? \"open\" : \"closed\"}</Text>\n </Stack>\n );\n}\n```\n\n## Component requirements\n\n## Accessibility\n\nThe Menu handles most accessibility requirements internally through React Aria. However, you must ensure proper labeling:\n\n- **For default triggers**: The trigger text serves as the accessible name\n- **For icon-only triggers**: Always provide `aria-label`:\n\n```tsx\n<Menu.Trigger asChild>\n <IconButton aria-label=\"More options\">\n <Icons.MoreVert />\n </IconButton>\n</Menu.Trigger>\n```\n\n- **For custom triggers**: Ensure the trigger element has an accessible name\n\nIf your use case requires tracking and analytics for this component, it is good practice to add a **persistent**, **unique** id to the component:\n\n```tsx\nconst PERSISTENT_ID = \"example-menu\";\n\nexport const Example = () => (\n <Menu.Root id={PERSISTENT_ID}>\n <Menu.Trigger>Actions</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"edit\">Edit</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n);\n```\n\n#### Keyboard navigation\n\nThe component supports full keyboard interaction:\n\n- `Tab` / `Shift+Tab`: Navigate to/from the menu trigger\n- `Enter` / `Space`: Open the menu when trigger is focused\n- `Arrow Down` / `Arrow Up`: Navigate through menu items\n- `Arrow Right`: Open submenu (when focused on submenu trigger)\n- `Arrow Left`: Close submenu and return to parent menu\n- `Enter`: Select the focused item\n- `Space`: Toggle selection in selection modes\n- `Escape`: Close the menu\n- `Home` / `End`: Jump to first/last item\n- Type to search: Type characters to jump to matching items\n\n## API reference\n\n<PropsTable id=\"Menu\" />\n\n## Common patterns\n\n### Context menu for list items\n\nA common pattern for providing actions on list items:\n\n```jsx live-dev\nconst App = () => {\n const items = [\n { id: \"1\", name: \"Document A.pdf\" },\n { id: \"2\", name: \"Spreadsheet B.xlsx\" },\n { id: \"3\", name: \"Presentation C.pptx\" },\n ];\n\n const handleAction = (itemId, action) => {\n alert(`${action} on ${itemId}`);\n };\n\n return (\n <Stack direction=\"column\" gap=\"200\">\n {items.map((item) => (\n <Box\n key={item.id}\n display=\"flex\"\n justifyContent=\"space-between\"\n alignItems=\"center\"\n padding=\"300\"\n borderRadius=\"200\"\n bg=\"neutral.2\"\n >\n <Text>{item.name}</Text>\n <Menu.Root onAction={(action) => handleAction(item.id, action)}>\n <Menu.Trigger asChild>\n <IconButton\n variant=\"ghost\"\n aria-label={`Actions for ${item.name}`}\n >\n <Icons.MoreVert />\n </IconButton>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"open\">\n <Icon slot=\"icon\"><Icons.FolderOpen /></Icon>\n <Text slot=\"label\">Open</Text>\n </Menu.Item>\n <Menu.Item id=\"rename\">\n <Icon slot=\"icon\"><Icons.Edit /></Icon>\n <Text slot=\"label\">Rename</Text>\n </Menu.Item>\n <Menu.Item id=\"download\">\n <Icon slot=\"icon\"><Icons.Download /></Icon>\n <Text slot=\"label\">Download</Text>\n </Menu.Item>\n <Separator />\n <Menu.Item id=\"delete\" isCritical>\n <Icon slot=\"icon\"><Icons.Delete /></Icon>\n <Text slot=\"label\">Delete</Text>\n </Menu.Item>\n </Menu.Content>\n </Menu.Root>\n </Box>\n ))}\n </Stack>\n );\n}\n```\n\n### Dynamic menu items\n\nBuild menus from data arrays:\n\n```jsx live-dev\nconst App = () => {\n const menuItems = [\n { id: \"new\", label: \"New File\", icon: Icons.InsertDriveFile, kbd: \"⌘N\" },\n { id: \"open\", label: \"Open\", icon: Icons.FolderOpen, kbd: \"⌘O\" },\n { id: \"save\", label: \"Save\", icon: Icons.Save, kbd: \"⌘S\" },\n { id: \"divider\" },\n { id: \"delete\", label: \"Delete\", icon: Icons.Delete, critical: true },\n ];\n\n return (\n <Menu.Root onAction={(key) => alert(`Action: ${key}`)}>\n <Menu.Trigger asChild>\n <Button variant=\"outline\">\n <Icons.MoreVert />\n File Menu\n </Button>\n </Menu.Trigger>\n <Menu.Content>\n {menuItems.map((item) => {\n if (item.id === \"divider\") {\n return <Separator key={Math.random()} />;\n }\n return (\n <Menu.Item key={item.id} id={item.id} isCritical={item.critical}>\n {item.icon && (\n <Icon slot=\"icon\"><item.icon /></Icon>\n )}\n <Text slot=\"label\">{item.label}</Text>\n {item.kbd && <Kbd slot=\"keyboard\">{item.kbd}</Kbd>}\n </Menu.Item>\n );\n })}\n </Menu.Content>\n </Menu.Root>\n );\n}\n```\n\n## Testing your implementation\n\nThese examples demonstrate how to test your implementation when using Menu within your application. As the component's internal functionality is already tested by Nimbus, these patterns help you verify your integration and application-specific logic.\n\n### Basic Rendering Tests\n\nVerify the menu renders with expected elements\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, waitFor } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { Menu, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Menu - Basic rendering\", () => {\n it(\"renders menu trigger\", () => {\n render(\n <NimbusProvider>\n <Menu.Root>\n <Menu.Trigger>Actions</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"edit\">Edit</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n </NimbusProvider>\n );\n\n expect(screen.getByRole(\"button\", { name: \"Actions\" })).toBeInTheDocument();\n });\n\n it(\"renders menu items when opened\", async () => {\n const user = userEvent.setup();\n render(\n <NimbusProvider>\n <Menu.Root>\n <Menu.Trigger>Actions</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"edit\">Edit</Menu.Item>\n <Menu.Item id=\"delete\">Delete</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n </NimbusProvider>\n );\n\n await user.click(screen.getByRole(\"button\", { name: \"Actions\" }));\n\n await waitFor(() => {\n expect(screen.getByRole(\"menu\")).toBeInTheDocument();\n });\n\n expect(screen.getByRole(\"menuitem\", { name: \"Edit\" })).toBeInTheDocument();\n expect(\n screen.getByRole(\"menuitem\", { name: \"Delete\" })\n ).toBeInTheDocument();\n });\n});\n```\n\n### Interaction Tests\n\nTest user interactions with the menu\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, waitFor } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { Menu, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Menu - Interactions\", () => {\n it(\"opens menu on trigger click\", async () => {\n const user = userEvent.setup();\n render(\n <NimbusProvider>\n <Menu.Root>\n <Menu.Trigger>Actions</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"edit\">Edit</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n </NimbusProvider>\n );\n\n await user.click(screen.getByRole(\"button\", { name: \"Actions\" }));\n\n await waitFor(() => {\n expect(screen.getByRole(\"menu\")).toBeInTheDocument();\n });\n });\n\n it(\"closes menu when item is selected\", async () => {\n const user = userEvent.setup();\n const handleAction = vi.fn();\n\n render(\n <NimbusProvider>\n <Menu.Root onAction={handleAction}>\n <Menu.Trigger>Actions</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"edit\">Edit</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n </NimbusProvider>\n );\n\n await user.click(screen.getByRole(\"button\", { name: \"Actions\" }));\n\n await waitFor(() => {\n expect(screen.getByRole(\"menu\")).toBeInTheDocument();\n });\n\n await user.click(screen.getByRole(\"menuitem\", { name: \"Edit\" }));\n\n expect(handleAction).toHaveBeenCalledWith(\"edit\");\n await waitFor(() => {\n expect(screen.queryByRole(\"menu\")).not.toBeInTheDocument();\n });\n });\n\n it(\"closes menu on Escape key\", async () => {\n const user = userEvent.setup();\n render(\n <NimbusProvider>\n <Menu.Root>\n <Menu.Trigger>Actions</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"edit\">Edit</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n </NimbusProvider>\n );\n\n await user.click(screen.getByRole(\"button\", { name: \"Actions\" }));\n\n await waitFor(() => {\n expect(screen.getByRole(\"menu\")).toBeInTheDocument();\n });\n\n await user.keyboard(\"{Escape}\");\n\n await waitFor(() => {\n expect(screen.queryByRole(\"menu\")).not.toBeInTheDocument();\n });\n });\n});\n```\n\n### Action Callback Tests\n\nTest the onAction callback behavior\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, waitFor } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { Menu, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Menu - Action callback\", () => {\n it(\"calls onAction with item id when clicked\", async () => {\n const user = userEvent.setup();\n const handleAction = vi.fn();\n\n render(\n <NimbusProvider>\n <Menu.Root onAction={handleAction}>\n <Menu.Trigger>Actions</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"copy\">Copy</Menu.Item>\n <Menu.Item id=\"paste\">Paste</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n </NimbusProvider>\n );\n\n await user.click(screen.getByRole(\"button\", { name: \"Actions\" }));\n\n await waitFor(() => {\n expect(screen.getByRole(\"menu\")).toBeInTheDocument();\n });\n\n await user.click(screen.getByRole(\"menuitem\", { name: \"Copy\" }));\n\n expect(handleAction).toHaveBeenCalledWith(\"copy\");\n });\n\n it(\"calls onAction with Enter key\", async () => {\n const user = userEvent.setup();\n const handleAction = vi.fn();\n\n render(\n <NimbusProvider>\n <Menu.Root onAction={handleAction}>\n <Menu.Trigger>Actions</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"save\">Save</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n </NimbusProvider>\n );\n\n await user.click(screen.getByRole(\"button\", { name: \"Actions\" }));\n\n await waitFor(() => {\n expect(screen.getByRole(\"menu\")).toBeInTheDocument();\n });\n\n // First item should have focus\n await waitFor(() => {\n expect(screen.getByRole(\"menuitem\", { name: \"Save\" })).toHaveFocus();\n });\n\n await user.keyboard(\"{Enter}\");\n\n expect(handleAction).toHaveBeenCalledWith(\"save\");\n });\n});\n```\n\n### Controlled Mode Tests\n\nTest controlled open/close behavior\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, waitFor } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { Menu, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Menu - Controlled mode\", () => {\n it(\"opens when isOpen is true\", async () => {\n render(\n <NimbusProvider>\n <Menu.Root isOpen={true} onOpenChange={() => {}}>\n <Menu.Trigger>Actions</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"edit\">Edit</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n </NimbusProvider>\n );\n\n await waitFor(() => {\n expect(screen.getByRole(\"menu\")).toBeInTheDocument();\n });\n });\n\n it(\"calls onOpenChange when menu is opened\", async () => {\n const user = userEvent.setup();\n const handleOpenChange = vi.fn();\n\n render(\n <NimbusProvider>\n <Menu.Root isOpen={false} onOpenChange={handleOpenChange}>\n <Menu.Trigger>Actions</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"edit\">Edit</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n </NimbusProvider>\n );\n\n await user.click(screen.getByRole(\"button\", { name: \"Actions\" }));\n\n expect(handleOpenChange).toHaveBeenCalledWith(true);\n });\n});\n```\n\n### Disabled Items Tests\n\nTest disabled item behavior\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, waitFor } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { Menu, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Menu - Disabled items\", () => {\n it(\"renders disabled item with aria-disabled\", async () => {\n const user = userEvent.setup();\n render(\n <NimbusProvider>\n <Menu.Root>\n <Menu.Trigger>Actions</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"edit\">Edit</Menu.Item>\n <Menu.Item id=\"paste\" isDisabled>\n Paste\n </Menu.Item>\n </Menu.Content>\n </Menu.Root>\n </NimbusProvider>\n );\n\n await user.click(screen.getByRole(\"button\", { name: \"Actions\" }));\n\n await waitFor(() => {\n expect(screen.getByRole(\"menu\")).toBeInTheDocument();\n });\n\n const disabledItem = screen.getByRole(\"menuitem\", { name: \"Paste\" });\n expect(disabledItem).toHaveAttribute(\"aria-disabled\", \"true\");\n });\n\n it(\"does not call onAction for disabled items\", async () => {\n const user = userEvent.setup();\n const handleAction = vi.fn();\n\n render(\n <NimbusProvider>\n <Menu.Root onAction={handleAction}>\n <Menu.Trigger>Actions</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"paste\" isDisabled>\n Paste\n </Menu.Item>\n </Menu.Content>\n </Menu.Root>\n </NimbusProvider>\n );\n\n await user.click(screen.getByRole(\"button\", { name: \"Actions\" }));\n\n await waitFor(() => {\n expect(screen.getByRole(\"menu\")).toBeInTheDocument();\n });\n\n // Disabled items have pointer-events: none, so click won't fire\n // We verify the item is disabled\n const disabledItem = screen.getByRole(\"menuitem\", { name: \"Paste\" });\n expect(disabledItem).toHaveAttribute(\"aria-disabled\", \"true\");\n\n // onAction should not have been called\n expect(handleAction).not.toHaveBeenCalled();\n });\n});\n```\n\n### Selection Mode Tests\n\nTest single and multiple selection modes\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, waitFor } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { Menu, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Menu - Selection mode\", () => {\n it(\"renders radio items in single selection mode\", async () => {\n const user = userEvent.setup();\n render(\n <NimbusProvider>\n <Menu.Root selectionMode=\"single\" selectedKeys={new Set([\"medium\"])}>\n <Menu.Trigger>Size</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"small\">Small</Menu.Item>\n <Menu.Item id=\"medium\">Medium</Menu.Item>\n <Menu.Item id=\"large\">Large</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n </NimbusProvider>\n );\n\n await user.click(screen.getByRole(\"button\", { name: \"Size\" }));\n\n await waitFor(() => {\n expect(screen.getByRole(\"menu\")).toBeInTheDocument();\n });\n\n // Items should be radio items in single selection mode\n expect(\n screen.getByRole(\"menuitemradio\", { name: \"Medium\" })\n ).toHaveAttribute(\"data-selected\");\n });\n\n it(\"renders checkbox items in multiple selection mode\", async () => {\n const user = userEvent.setup();\n render(\n <NimbusProvider>\n <Menu.Root\n selectionMode=\"multiple\"\n selectedKeys={new Set([\"bold\", \"italic\"])}\n >\n <Menu.Trigger>Formatting</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"bold\">Bold</Menu.Item>\n <Menu.Item id=\"italic\">Italic</Menu.Item>\n <Menu.Item id=\"underline\">Underline</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n </NimbusProvider>\n );\n\n await user.click(screen.getByRole(\"button\", { name: \"Formatting\" }));\n\n await waitFor(() => {\n expect(screen.getByRole(\"menu\")).toBeInTheDocument();\n });\n\n // Items should be checkbox items in multiple selection mode\n expect(\n screen.getByRole(\"menuitemcheckbox\", { name: \"Bold\" })\n ).toHaveAttribute(\"data-selected\");\n expect(\n screen.getByRole(\"menuitemcheckbox\", { name: \"Italic\" })\n ).toHaveAttribute(\"data-selected\");\n expect(\n screen.getByRole(\"menuitemcheckbox\", { name: \"Underline\" })\n ).not.toHaveAttribute(\"data-selected\");\n });\n\n it(\"calls onSelectionChange when selection changes\", async () => {\n const user = userEvent.setup();\n const handleSelectionChange = vi.fn();\n\n render(\n <NimbusProvider>\n <Menu.Root\n selectionMode=\"single\"\n selectedKeys={new Set([\"small\"])}\n onSelectionChange={handleSelectionChange}\n >\n <Menu.Trigger>Size</Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"small\">Small</Menu.Item>\n <Menu.Item id=\"medium\">Medium</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n </NimbusProvider>\n );\n\n await user.click(screen.getByRole(\"button\", { name: \"Size\" }));\n\n await waitFor(() => {\n expect(screen.getByRole(\"menu\")).toBeInTheDocument();\n });\n\n await user.click(screen.getByRole(\"menuitemradio\", { name: \"Medium\" }));\n\n expect(handleSelectionChange).toHaveBeenCalled();\n });\n});\n```\n\n\n## Resources\n\n- [Storybook](https://nimbus-storybook.vercel.app/?path=/docs/components-menu--docs)\n- [React Aria Menu](https://react-spectrum.adobe.com/react-aria/Menu.html)\n- [ARIA Menu Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menu/)\n",
|
|
127
|
+
"toc": [
|
|
128
|
+
{
|
|
129
|
+
"value": "Getting started",
|
|
130
|
+
"href": "#getting-started",
|
|
131
|
+
"depth": 2,
|
|
132
|
+
"numbering": [
|
|
133
|
+
1,
|
|
134
|
+
1
|
|
135
|
+
],
|
|
136
|
+
"parent": "root"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"value": "Import",
|
|
140
|
+
"href": "#import",
|
|
141
|
+
"depth": 3,
|
|
142
|
+
"numbering": [
|
|
143
|
+
1,
|
|
144
|
+
1,
|
|
145
|
+
1
|
|
146
|
+
],
|
|
147
|
+
"parent": "root"
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"value": "Basic usage",
|
|
151
|
+
"href": "#basic-usage",
|
|
152
|
+
"depth": 3,
|
|
153
|
+
"numbering": [
|
|
154
|
+
1,
|
|
155
|
+
1,
|
|
156
|
+
2
|
|
157
|
+
],
|
|
158
|
+
"parent": "root"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"value": "Usage examples",
|
|
162
|
+
"href": "#usage-examples",
|
|
163
|
+
"depth": 2,
|
|
164
|
+
"numbering": [
|
|
165
|
+
1,
|
|
166
|
+
2
|
|
167
|
+
],
|
|
168
|
+
"parent": "root"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"value": "Custom triggers",
|
|
172
|
+
"href": "#custom-triggers",
|
|
173
|
+
"depth": 3,
|
|
174
|
+
"numbering": [
|
|
175
|
+
1,
|
|
176
|
+
2,
|
|
177
|
+
1
|
|
178
|
+
],
|
|
179
|
+
"parent": "root"
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"value": "Menu placement",
|
|
183
|
+
"href": "#menu-placement",
|
|
184
|
+
"depth": 3,
|
|
185
|
+
"numbering": [
|
|
186
|
+
1,
|
|
187
|
+
2,
|
|
188
|
+
2
|
|
189
|
+
],
|
|
190
|
+
"parent": "root"
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
"value": "Rich item content",
|
|
194
|
+
"href": "#rich-item-content",
|
|
195
|
+
"depth": 3,
|
|
196
|
+
"numbering": [
|
|
197
|
+
1,
|
|
198
|
+
2,
|
|
199
|
+
3
|
|
200
|
+
],
|
|
201
|
+
"parent": "root"
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"value": "Critical items",
|
|
205
|
+
"href": "#critical-items",
|
|
206
|
+
"depth": 3,
|
|
207
|
+
"numbering": [
|
|
208
|
+
1,
|
|
209
|
+
2,
|
|
210
|
+
4
|
|
211
|
+
],
|
|
212
|
+
"parent": "root"
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"value": "Disabled items",
|
|
216
|
+
"href": "#disabled-items",
|
|
217
|
+
"depth": 3,
|
|
218
|
+
"numbering": [
|
|
219
|
+
1,
|
|
220
|
+
2,
|
|
221
|
+
5
|
|
222
|
+
],
|
|
223
|
+
"parent": "root"
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"value": "Sections with labels",
|
|
227
|
+
"href": "#sections-with-labels",
|
|
228
|
+
"depth": 3,
|
|
229
|
+
"numbering": [
|
|
230
|
+
1,
|
|
231
|
+
2,
|
|
232
|
+
6
|
|
233
|
+
],
|
|
234
|
+
"parent": "root"
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"value": "Single selection mode",
|
|
238
|
+
"href": "#single-selection-mode",
|
|
239
|
+
"depth": 3,
|
|
240
|
+
"numbering": [
|
|
241
|
+
1,
|
|
242
|
+
2,
|
|
243
|
+
7
|
|
244
|
+
],
|
|
245
|
+
"parent": "root"
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"value": "Multiple selection mode",
|
|
249
|
+
"href": "#multiple-selection-mode",
|
|
250
|
+
"depth": 3,
|
|
251
|
+
"numbering": [
|
|
252
|
+
1,
|
|
253
|
+
2,
|
|
254
|
+
8
|
|
255
|
+
],
|
|
256
|
+
"parent": "root"
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
"value": "Submenus",
|
|
260
|
+
"href": "#submenus",
|
|
261
|
+
"depth": 3,
|
|
262
|
+
"numbering": [
|
|
263
|
+
1,
|
|
264
|
+
2,
|
|
265
|
+
9
|
|
266
|
+
],
|
|
267
|
+
"parent": "root"
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
"value": "Uncontrolled mode",
|
|
271
|
+
"href": "#uncontrolled-mode",
|
|
272
|
+
"depth": 3,
|
|
273
|
+
"numbering": [
|
|
274
|
+
1,
|
|
275
|
+
2,
|
|
276
|
+
10
|
|
277
|
+
],
|
|
278
|
+
"parent": "root"
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
"value": "Controlled mode",
|
|
282
|
+
"href": "#controlled-mode",
|
|
283
|
+
"depth": 3,
|
|
284
|
+
"numbering": [
|
|
285
|
+
1,
|
|
286
|
+
2,
|
|
287
|
+
11
|
|
288
|
+
],
|
|
289
|
+
"parent": "root"
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
"value": "Component requirements",
|
|
293
|
+
"href": "#component-requirements",
|
|
294
|
+
"depth": 2,
|
|
295
|
+
"numbering": [
|
|
296
|
+
1,
|
|
297
|
+
3
|
|
298
|
+
],
|
|
299
|
+
"parent": "root"
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
"value": "Accessibility",
|
|
303
|
+
"href": "#accessibility",
|
|
304
|
+
"depth": 2,
|
|
305
|
+
"numbering": [
|
|
306
|
+
1,
|
|
307
|
+
4
|
|
308
|
+
],
|
|
309
|
+
"parent": "root"
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
"value": "Keyboard navigation",
|
|
313
|
+
"href": "#keyboard-navigation",
|
|
314
|
+
"depth": 4,
|
|
315
|
+
"numbering": [
|
|
316
|
+
1,
|
|
317
|
+
4,
|
|
318
|
+
1,
|
|
319
|
+
1
|
|
320
|
+
],
|
|
321
|
+
"parent": "root"
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
"value": "API reference",
|
|
325
|
+
"href": "#api-reference",
|
|
326
|
+
"depth": 2,
|
|
327
|
+
"numbering": [
|
|
328
|
+
1,
|
|
329
|
+
5
|
|
330
|
+
],
|
|
331
|
+
"parent": "root"
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
"value": "Common patterns",
|
|
335
|
+
"href": "#common-patterns",
|
|
336
|
+
"depth": 2,
|
|
337
|
+
"numbering": [
|
|
338
|
+
1,
|
|
339
|
+
6
|
|
340
|
+
],
|
|
341
|
+
"parent": "root"
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
"value": "Context menu for list items",
|
|
345
|
+
"href": "#context-menu-for-list-items",
|
|
346
|
+
"depth": 3,
|
|
347
|
+
"numbering": [
|
|
348
|
+
1,
|
|
349
|
+
6,
|
|
350
|
+
1
|
|
351
|
+
],
|
|
352
|
+
"parent": "root"
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
"value": "Dynamic menu items",
|
|
356
|
+
"href": "#dynamic-menu-items",
|
|
357
|
+
"depth": 3,
|
|
358
|
+
"numbering": [
|
|
359
|
+
1,
|
|
360
|
+
6,
|
|
361
|
+
2
|
|
362
|
+
],
|
|
363
|
+
"parent": "root"
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
"value": "Testing your implementation",
|
|
367
|
+
"href": "#testing-your-implementation",
|
|
368
|
+
"depth": 2,
|
|
369
|
+
"numbering": [
|
|
370
|
+
1,
|
|
371
|
+
7
|
|
372
|
+
],
|
|
373
|
+
"parent": "root"
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
"value": "Basic Rendering Tests",
|
|
377
|
+
"href": "#basic-rendering-tests",
|
|
378
|
+
"depth": 3,
|
|
379
|
+
"numbering": [
|
|
380
|
+
1,
|
|
381
|
+
7,
|
|
382
|
+
1
|
|
383
|
+
],
|
|
384
|
+
"parent": "root"
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
"value": "Interaction Tests",
|
|
388
|
+
"href": "#interaction-tests",
|
|
389
|
+
"depth": 3,
|
|
390
|
+
"numbering": [
|
|
391
|
+
1,
|
|
392
|
+
7,
|
|
393
|
+
2
|
|
394
|
+
],
|
|
395
|
+
"parent": "root"
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
"value": "Action Callback Tests",
|
|
399
|
+
"href": "#action-callback-tests",
|
|
400
|
+
"depth": 3,
|
|
401
|
+
"numbering": [
|
|
402
|
+
1,
|
|
403
|
+
7,
|
|
404
|
+
3
|
|
405
|
+
],
|
|
406
|
+
"parent": "root"
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
"value": "Controlled Mode Tests",
|
|
410
|
+
"href": "#controlled-mode-tests",
|
|
411
|
+
"depth": 3,
|
|
412
|
+
"numbering": [
|
|
413
|
+
1,
|
|
414
|
+
7,
|
|
415
|
+
4
|
|
416
|
+
],
|
|
417
|
+
"parent": "root"
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
"value": "Disabled Items Tests",
|
|
421
|
+
"href": "#disabled-items-tests",
|
|
422
|
+
"depth": 3,
|
|
423
|
+
"numbering": [
|
|
424
|
+
1,
|
|
425
|
+
7,
|
|
426
|
+
5
|
|
427
|
+
],
|
|
428
|
+
"parent": "root"
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
"value": "Selection Mode Tests",
|
|
432
|
+
"href": "#selection-mode-tests",
|
|
433
|
+
"depth": 3,
|
|
434
|
+
"numbering": [
|
|
435
|
+
1,
|
|
436
|
+
7,
|
|
437
|
+
6
|
|
438
|
+
],
|
|
439
|
+
"parent": "root"
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
"value": "Resources",
|
|
443
|
+
"href": "#resources",
|
|
444
|
+
"depth": 2,
|
|
445
|
+
"numbering": [
|
|
446
|
+
1,
|
|
447
|
+
8
|
|
448
|
+
],
|
|
449
|
+
"parent": "root"
|
|
450
|
+
}
|
|
451
|
+
]
|
|
452
|
+
},
|
|
453
|
+
"guidelines": {
|
|
454
|
+
"mdx": "\n## Guidelines\n\nMenu guidelines focus on providing temporary, contextual information or actions\nin a clear and accessible manner, ensuring they are easily triggered, navigable\nvia keyboard, and don't disrupt the user's primary workflow.\n\n### Best practices\n\n- **Clear trigger:** Make the trigger element visually distinct and interactive.\n Use consistent icons or labels for dropdown triggers.\n- **Logical content:** Order options logically (alphabetical, frequency, etc.).\n Keep content concise and actionable.\n- **Easy interaction:** If interaction involves a single selection, close the\n popover upon selection. Keep the popover open if more complicated content\n needs several selections.\n- **Responsive behavior:** Adapt the dropdown's position and size to different\n screen sizes. Ensure it works well on touch devices.\n- **Visual feedback:** Highlight the selected option. Use clear hover states.\n- **Keyboard navigation:** Allow users to navigate options with arrow keys.\n Enable selection with Enter/Spacebar. Enable closing the popover with the\n Escape key.\n- **ARIA attributes:** Use `aria-haspopup`, `aria-expanded`, and `aria-label`\n for screen reader support. Manage focus correctly when the popover opens and\n closes.\n- **Avoid nested dropdowns:** Keep the structure simple and avoid nested menus.\n- **Contextual placement:** Position the dropdown near the trigger element\n without obscuring important content.\n- **Limit content:** Keep the content to simple actions, or short text.\n- **Use sections correctly:** Use sections only if you have more than 2 groups\n to organize. It is unneeded to have sections if the information is collected\n together.\n\n#### Common popover content\n\nThese are some of the most seen uses of popover content. These are included in\nthe figma library components to make designing common shared uses easier.\n\n**Simple list**\n\nAllows the user to select one option, add a search to allow users to make\nselection easier if there are many options. For options 5 or fewer, a search is\nnot needed.\n\n```jsx live\nconst App = () => (\n <Menu.Root>\n <Menu.Trigger asChild>\n <IconButton\n variant=\"ghost\"\n colorPalette=\"neutral\"\n aria-label=\"More options\"\n >\n <Icons.MoreVert />\n </IconButton>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"menu-item-1\">Menu Item</Menu.Item>\n <Menu.Item id=\"menu-item-2\">Menu Item</Menu.Item>\n <Menu.Item id=\"menu-item-3\">Menu Item</Menu.Item>\n <Menu.Item id=\"menu-item-4\">Menu Item</Menu.Item>\n <Menu.Item id=\"menu-item-5\">Menu Item</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n);\n```\n\n**Action list**\n\nInclude icons, offer tips or shortcuts, color coding for semantic clues, and\nsectioning. For options 5 or fewer, a search is not needed.\n\n```jsx live\nconst App = () => (\n <Menu.Root>\n <Menu.Trigger asChild>\n <Button variant=\"solid\" colorPalette=\"primary\">\n <Icons.FolderOpen />\n File Menu\n </Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"duplicate\">\n <Icon slot=\"icon\">\n <Icons.ContentCopy />\n </Icon>\n <Text slot=\"label\">Duplicate</Text>\n <Kbd slot=\"keyboard\">⌘T</Kbd>\n </Menu.Item>\n <Menu.Item id=\"rename\">\n <Icon slot=\"icon\">\n <Icons.Create />\n </Icon>\n <Text slot=\"label\">Rename</Text>\n <Kbd slot=\"keyboard\">⌘R</Kbd>\n </Menu.Item>\n <Menu.Item id=\"share\">\n <Icon slot=\"icon\">\n <Icons.IosShare />\n </Icon>\n <Text slot=\"label\">Share</Text>\n <Kbd slot=\"keyboard\">⌘W</Kbd>\n </Menu.Item>\n <Menu.Item id=\"pin\">\n <Icon slot=\"icon\">\n <Icons.PushPin />\n </Icon>\n <Text slot=\"label\">Pin</Text>\n <Kbd slot=\"keyboard\">⌘P</Kbd>\n </Menu.Item>\n <Separator />\n <Menu.Item id=\"delete\" isCritical>\n <Icon slot=\"icon\">\n <Icons.Delete />\n </Icon>\n <Text slot=\"label\">Delete</Text>\n <Kbd slot=\"keyboard\">⌘D</Kbd>\n </Menu.Item>\n </Menu.Content>\n </Menu.Root>\n);\n```\n\n**Section list**\n\nLets the user perform a one time action. Features optional section titles and\ndescriptions. For options 5 or fewer, a search is not needed.\n\n```jsx live\nconst App = () => (\n <Menu.Root>\n <Menu.Trigger asChild>\n <Button variant=\"outline\" colorPalette=\"primary\">\n Actions\n </Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Section label=\"Import\">\n <Menu.Item id=\"import-csv\">Import from CSV</Menu.Item>\n <Menu.Item id=\"import-drive\">Import from Drive</Menu.Item>\n </Menu.Section>\n <Separator />\n <Menu.Section label=\"Export\">\n <Menu.Item id=\"export-csv\">Export to CSV</Menu.Item>\n <Menu.Item id=\"export-drive\">Export to Drive</Menu.Item>\n </Menu.Section>\n </Menu.Content>\n </Menu.Root>\n);\n```\n\n**Custom content**\n\nProvide a different experience to suit what your user needs within a popover.\nMake sure that this content is best suited for smaller areas. Options are very\ncustomizable to suit your needs.\n\n## Usage\n\nMenus are essential to hold actions and tools in a compact and handy area of the\nUI for a user. Make sure to use them correctly to allow the user to work more\nefficiently and not to overwhelm. Recognizing experience patterns in your\nproduct will also help in creating successful interactions for your users.\n\n> [!TIP]\\\n> When to use\n\n- **Short, actionable lists:** Lists of options for filtering, sorting, or\n selecting specific actions. Menu items that are clearly labeled and easily\n understood.\n- **Simple form elements:** Basic form inputs like radio buttons or checkboxes\n for quick selections.\n- **Contextual actions:** Actions related to the item or element that triggered\n the dropdown. Quick links to related settings or preferences.\n\n> [!CAUTION]\\\n> When not to use\n\n- **Long paragraphs of text:** Menus are not suitable for displaying large\n amounts of text. Keep content concise and focused.\n- **Complex forms or interactions:** Avoid placing complex forms or multi-step\n processes within a menu dropdown. These should be handled on dedicated pages\n or modals.\n- **Critical information:** Do not rely on menu dropdown to display essential\n information that users need to see immediately. Important content should be\n readily visible on the page.\n- **Unrelated content:** Ensure that the content of the menu is directly related\n to the trigger element. Avoid including unrelated or irrelevant information.\n- **Nested dropdown:** Nested drop down within menu can be confusing and\n difficult to navigate.\n- **Content that changes the page layout:** Avoid content that will cause the\n page to reflow when the menu opens.\n\n### Solid-styled widths\n\nThese placements are more regular, they have either a maximum width of 268px or\nform wide. The menu width should match the width of the field itself.\n\n> [!TIP]\\\n> **Do**\n>\n> - The form is at maximum size (when not in a full page form) and the menu\n> matches the width of the field.\n> - Longer options flow to the next lines, and when chosen, those longer texts\n> are truncated so the user can still see the icons clearly.\n\n```jsx live\nconst App = () => (\n <Stack direction=\"horizontal\" gap=\"400\" alignItems=\"flex-start\">\n <Menu.Root>\n <Menu.Trigger asChild>\n <Button variant=\"outline\" colorPalette=\"neutral\">\n Project 1\n <Icons.KeyboardArrowDown />\n </Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"long-name\">Project with a very long name</Menu.Item>\n <Menu.Item id=\"project-1\">Project 1</Menu.Item>\n <Menu.Item id=\"abc\">ABC</Menu.Item>\n <Menu.Item id=\"even-longer\">\n Project with an even longer name that breaks into 2 lines\n </Menu.Item>\n </Menu.Content>\n </Menu.Root>\n <Menu.Root>\n <Menu.Trigger asChild>\n <Button variant=\"ghost\" colorPalette=\"neutral\">\n Project 1\n <Icons.KeyboardArrowDown />\n </Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"long-name-2\">Project with a very long name</Menu.Item>\n <Menu.Item id=\"project-1-2\">Project 1</Menu.Item>\n <Menu.Item id=\"abc-2\">ABC</Menu.Item>\n <Menu.Item id=\"even-longer-2\">\n Project with an even longer name that breaks into 2 lines\n </Menu.Item>\n </Menu.Content>\n </Menu.Root>\n </Stack>\n);\n```\n\n> [!CAUTION]\\\n> **Don't**\n>\n> - Do not have different widths for select inputs.\n> - Do not change the width of the field to match the content once selected.\n\n```jsx live\nconst App = () => (\n <Menu.Root>\n <Menu.Trigger asChild>\n <Button variant=\"ghost\" colorPalette=\"neutral\">\n Project 1\n <Icons.KeyboardArrowDown />\n </Button>\n </Menu.Trigger>\n <Menu.Content maxW=\"130px\">\n <Menu.Item id=\"long-name\">Project with a very long name</Menu.Item>\n <Menu.Item id=\"project-1\">Project 1</Menu.Item>\n <Menu.Item id=\"abc\">ABC</Menu.Item>\n <Menu.Item id=\"even-longer\">\n Project with an even longer name that breaks into 2 lines\n </Menu.Item>\n </Menu.Content>\n </Menu.Root>\n);\n```\n\n### Icons within action lists\n\nHaving icons can make actions easier for a user to select quickly, especially\nfor common and repetitive actions across products. Make sure to keep aligned\nwith familiar patterns to ensure user recognition. Actions can also be organized\nwith sections.\n\n> [!TIP]\\\n> **Do**\n>\n> - Use common icons and clear and concise labels that are easily understood by\n> users.\n> - Use destructive-styled icons for the actions that apply.\n\n```jsx live\nconst App = () => (\n <Menu.Root>\n <Menu.Trigger asChild>\n <Button variant=\"outline\" colorPalette=\"neutral\">\n Actions\n </Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"duplicate\">\n <Icon slot=\"icon\">\n <Icons.ContentCopy />\n </Icon>\n <Text slot=\"label\">Duplicate</Text>\n </Menu.Item>\n <Menu.Item id=\"upload\">\n <Icon slot=\"icon\">\n <Icons.IosShare />\n </Icon>\n <Text slot=\"label\">Upload</Text>\n </Menu.Item>\n <Menu.Item id=\"delete\" isCritical>\n <Icon slot=\"icon\">\n <Icons.Delete />\n </Icon>\n <Text slot=\"label\">Delete</Text>\n </Menu.Item>\n </Menu.Content>\n </Menu.Root>\n);\n```\n\n> [!CAUTION]\\\n> **Don't**\n>\n> - Do not use uncommon icons, and do not shorten labels of actions unless it is\n> common and user tested.\n> - Do not use destructive styled actions for actions that are not destructive\n\n```jsx live\nconst App = () => (\n <Menu.Root>\n <Menu.Trigger asChild>\n <Button variant=\"outline\" colorPalette=\"neutral\">\n Actions\n </Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"dupli\">\n <Icon slot=\"icon\">\n <Icons.FilterList />\n </Icon>\n <Text slot=\"label\">Dupli</Text>\n </Menu.Item>\n <Menu.Item id=\"upload\" isCritical>\n <Icon slot=\"icon\">\n <Icons.IosShare />\n </Icon>\n <Text slot=\"label\">Upload</Text>\n </Menu.Item>\n <Menu.Item id=\"delete\" isCritical>\n <Icon slot=\"icon\">\n <Icons.Delete />\n </Icon>\n <Text slot=\"label\">Delete</Text>\n </Menu.Item>\n </Menu.Content>\n </Menu.Root>\n);\n```\n\n### Keep menu items concise\n\nKeep menu items short and concise. Long menu items that cause text to wrap\nmultiple lines are discouraged. If text wrapping becomes a frequent concern,\nconsider revising the text or use alternative UI patterns that will give your\ncontent more space.\n\n> [!TIP]\\\n> **Do**\n>\n> - Use a short and easily understandable label. Describe, do not use labels as\n> instructions.\n> - Text can flow to three lines, but truncate further text.\n\n```jsx live\nconst App = () => (\n <Menu.Root>\n <Menu.Trigger asChild>\n <Button variant=\"outline\" colorPalette=\"neutral\">\n Discount type\n <Icons.KeyboardArrowDown />\n </Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Section label=\"Product discounts\">\n <Menu.Item id=\"pct-off-product\">Percentage off product</Menu.Item>\n <Menu.Item id=\"amt-off-product\">Amount off product</Menu.Item>\n </Menu.Section>\n <Separator />\n <Menu.Section label=\"Cart discounts with line items\">\n <Menu.Item id=\"pct-off-cart\">Percentage off item(s) on cart</Menu.Item>\n <Menu.Item id=\"amt-off-cart\">Amount off item(s) in cart</Menu.Item>\n <Menu.Item id=\"buy-x-get-x\">Buy x get x with percentage off</Menu.Item>\n <Menu.Item id=\"fixed-price\">Fixed-price in cart</Menu.Item>\n <Menu.Item id=\"shipping\">Discounted shipping</Menu.Item>\n <Menu.Item id=\"gift\">Gift with purchase</Menu.Item>\n <Menu.Item id=\"amt-total\">Amount off based on total spend</Menu.Item>\n <Menu.Item id=\"pct-total\">\n Percentage off based on total spend\n </Menu.Item>\n </Menu.Section>\n <Separator />\n <Menu.Section label=\"Cart discounts with custom line items\">\n <Menu.Item id=\"custom-pct-off\">\n Percentage off item(s) on cart\n </Menu.Item>\n <Menu.Item id=\"custom-amt-off\">Amount off item(s) in cart</Menu.Item>\n <Menu.Item id=\"custom-buy-x\">Buy x get x with percentage off</Menu.Item>\n </Menu.Section>\n </Menu.Content>\n </Menu.Root>\n);\n```\n\n> [!CAUTION]\\\n> **Don't**\n>\n> - Keep content short or make sure that the location has enough room to display\n> content with more space.\n> - Don’t use additional labels or explainers when unneeded.\n> - Do not encourage lengthy text for drop down experiences. Text can flow to\n> three lines, but truncate further text.\n> - Punctuation is not needed.\n\n```jsx live\nconst App = () => (\n <Menu.Root>\n <Menu.Trigger asChild>\n <Button variant=\"outline\" colorPalette=\"neutral\">\n Discount type\n <Icons.KeyboardArrowDown />\n </Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Section label=\"Product discounts\">\n <Menu.Item id=\"pct-off-product\">\n <Text slot=\"label\">\n Discount the target item(s) relative to its price.\n </Text>\n <Text slot=\"description\">Discount type: relative</Text>\n </Menu.Item>\n <Menu.Item id=\"amt-off-product\">\n <Text slot=\"label\">\n Discount the target item(s) by an absolute amount.\n </Text>\n <Text slot=\"description\">Discount type: absolute</Text>\n </Menu.Item>\n </Menu.Section>\n <Separator />\n <Menu.Section label=\"Cart discounts with line items\">\n <Menu.Item id=\"pct-off-cart\">\n <Text slot=\"label\">\n Discount the target item(s) relative to its price.\n </Text>\n <Text slot=\"description\">Discount type: relative</Text>\n </Menu.Item>\n <Menu.Item id=\"amt-off-cart\">\n <Text slot=\"label\">\n Discount the target item(s) by an absolute amount.\n </Text>\n <Text slot=\"description\">Discount type: absolute</Text>\n </Menu.Item>\n <Menu.Item id=\"buy-x-get-x\">\n <Text slot=\"label\">\n A relative (% off) discount is applied when the shopper buys a\n specified quantity of an item.\n </Text>\n <Text slot=\"description\">Discount type: multi-buy</Text>\n </Menu.Item>\n <Menu.Item id=\"fixed-price\">\n <Text slot=\"label\">\n Discount the target item(s) by setting a fixed price.\n </Text>\n <Text slot=\"description\">Discount type: fixed-price</Text>\n </Menu.Item>\n <Menu.Item id=\"shipping\">\n <Text slot=\"label\">\n Discount the cart's shipping cost for the customer.\n </Text>\n <Text slot=\"description\">Discount type: shipping</Text>\n </Menu.Item>\n <Menu.Item id=\"gift\">\n <Text slot=\"label\">\n Discount adds a free line item(s) to the cart when the specified\n conditions are met.\n </Text>\n <Text slot=\"description\">Discount type: gift line item</Text>\n </Menu.Item>\n <Menu.Item id=\"amt-total\">\n <Text slot=\"label\">\n Discount an absolute amount based on cart total.\n </Text>\n <Text slot=\"description\">Discount type: absolute</Text>\n </Menu.Item>\n <Menu.Item id=\"pct-total\">\n <Text slot=\"label\">\n Discount an amount relative to the cart total.\n </Text>\n <Text slot=\"description\">Discount type: relative</Text>\n </Menu.Item>\n </Menu.Section>\n <Separator />\n <Menu.Section label=\"Cart discounts with custom line items\">\n <Menu.Item id=\"custom-pct-off\">\n <Text slot=\"label\">\n Discount the target custom line item(s) relative to its price.\n </Text>\n <Text slot=\"description\">Discount type: relative</Text>\n </Menu.Item>\n <Menu.Item id=\"custom-amt-off\">\n <Text slot=\"label\">\n Discount the target custom line item(s) by an absolute amount.\n </Text>\n <Text slot=\"description\">Discount type: absolute</Text>\n </Menu.Item>\n <Menu.Item id=\"custom-buy-x\">\n <Text slot=\"label\">\n A relative (% off) discount is applied when the shopper buys a\n specified quantity of an item defined as a custom line item.\n </Text>\n <Text slot=\"description\">Discount type: multibuy</Text>\n </Menu.Item>\n </Menu.Section>\n </Menu.Content>\n </Menu.Root>\n);\n```\n\n### Organize dropdown content when possible\n\nUse grouping structures if all items in a list can be grouped for a better user\nexperience. By default, organize by alphabetical order.\n\n> [!TIP]\\\n> **Do**\n>\n> - Use labels within popover/drop downs to organize content.\n> - If actions lists become bulky and hard to scan, consider another experience\n> for the user.\n\n```jsx live\nconst App = () => (\n <Menu.Root>\n <Menu.Trigger asChild>\n <Button variant=\"outline\" colorPalette=\"neutral\">\n Actions\n <Icons.KeyboardArrowDown />\n </Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Section label=\"Common actions\">\n <Menu.Item id=\"publish\">Publish</Menu.Item>\n <Menu.Item id=\"unpublish\">Unpublish</Menu.Item>\n <Menu.Item id=\"delete\">Delete</Menu.Item>\n </Menu.Section>\n <Separator />\n <Menu.Section label=\"Import\">\n <Menu.Item id=\"import-csv\">Import via CSV</Menu.Item>\n <Menu.Item id=\"bulk-unpublish\">Bulk unpublish via CSV</Menu.Item>\n <Menu.Item id=\"bulk-delete\">Bulk delete via CSV</Menu.Item>\n <Menu.Item id=\"import-inventories\">Import inventories</Menu.Item>\n </Menu.Section>\n <Separator />\n <Menu.Section label=\"Export\">\n <Menu.Item id=\"export-products\">Export products</Menu.Item>\n <Menu.Item id=\"export-inventories\">Export Inventories</Menu.Item>\n </Menu.Section>\n </Menu.Content>\n </Menu.Root>\n);\n```\n\n> [!CAUTION]\\\n> **Don't**\n>\n> - Don't bury frequently used actions within a dropdown or menu; instead,\n> prioritize them at the top and group related actions together to facilitate\n> quick user selection.\n\n```jsx live\nconst App = () => (\n <Menu.Root>\n <Menu.Trigger asChild>\n <Button variant=\"outline\" colorPalette=\"neutral\">\n Actions\n <Icons.KeyboardArrowDown />\n </Button>\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item id=\"bulk-delete\">Bulk delete via CSV</Menu.Item>\n <Menu.Item id=\"bulk-unpublish\">Bulk unpublish via CSV</Menu.Item>\n <Menu.Item id=\"delete\">Delete</Menu.Item>\n <Menu.Item id=\"export-inventories\">Export Inventories</Menu.Item>\n <Menu.Item id=\"export-products\">Export products</Menu.Item>\n <Menu.Item id=\"import-inventories\">Import inventories</Menu.Item>\n <Menu.Item id=\"import-csv\">Import via CSV</Menu.Item>\n <Menu.Item id=\"publish\">Publish</Menu.Item>\n <Menu.Item id=\"unpublish\">Unpublish</Menu.Item>\n </Menu.Content>\n </Menu.Root>\n);\n```\n",
|
|
455
|
+
"toc": [
|
|
456
|
+
{
|
|
457
|
+
"value": "Guidelines",
|
|
458
|
+
"href": "#guidelines",
|
|
459
|
+
"depth": 2,
|
|
460
|
+
"numbering": [
|
|
461
|
+
1,
|
|
462
|
+
1
|
|
463
|
+
],
|
|
464
|
+
"parent": "root"
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
"value": "Best practices",
|
|
468
|
+
"href": "#best-practices",
|
|
469
|
+
"depth": 3,
|
|
470
|
+
"numbering": [
|
|
471
|
+
1,
|
|
472
|
+
1,
|
|
473
|
+
1
|
|
474
|
+
],
|
|
475
|
+
"parent": "root"
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
"value": "Common popover content",
|
|
479
|
+
"href": "#common-popover-content",
|
|
480
|
+
"depth": 4,
|
|
481
|
+
"numbering": [
|
|
482
|
+
1,
|
|
483
|
+
1,
|
|
484
|
+
1,
|
|
485
|
+
1
|
|
486
|
+
],
|
|
487
|
+
"parent": "root"
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
"value": "Usage",
|
|
491
|
+
"href": "#usage",
|
|
492
|
+
"depth": 2,
|
|
493
|
+
"numbering": [
|
|
494
|
+
1,
|
|
495
|
+
2
|
|
496
|
+
],
|
|
497
|
+
"parent": "root"
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
"value": "Solid-styled widths",
|
|
501
|
+
"href": "#solid-styled-widths",
|
|
502
|
+
"depth": 3,
|
|
503
|
+
"numbering": [
|
|
504
|
+
1,
|
|
505
|
+
2,
|
|
506
|
+
1
|
|
507
|
+
],
|
|
508
|
+
"parent": "root"
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
"value": "Icons within action lists",
|
|
512
|
+
"href": "#icons-within-action-lists",
|
|
513
|
+
"depth": 3,
|
|
514
|
+
"numbering": [
|
|
515
|
+
1,
|
|
516
|
+
2,
|
|
517
|
+
2
|
|
518
|
+
],
|
|
519
|
+
"parent": "root"
|
|
520
|
+
},
|
|
521
|
+
{
|
|
522
|
+
"value": "Keep menu items concise",
|
|
523
|
+
"href": "#keep-menu-items-concise",
|
|
524
|
+
"depth": 3,
|
|
525
|
+
"numbering": [
|
|
526
|
+
1,
|
|
527
|
+
2,
|
|
528
|
+
3
|
|
529
|
+
],
|
|
530
|
+
"parent": "root"
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
"value": "Organize dropdown content when possible",
|
|
534
|
+
"href": "#organize-dropdown-content-when-possible",
|
|
535
|
+
"depth": 3,
|
|
536
|
+
"numbering": [
|
|
537
|
+
1,
|
|
538
|
+
2,
|
|
539
|
+
4
|
|
540
|
+
],
|
|
541
|
+
"parent": "root"
|
|
542
|
+
}
|
|
543
|
+
]
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|