@commercetools/nimbus-mcp 0.1.0 → 2.10.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 +10913 -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-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 +82 -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 +278 -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,960 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"id": "Components-Select",
|
|
4
|
+
"title": "Select",
|
|
5
|
+
"exportName": "Select",
|
|
6
|
+
"description": "A select input is a form field that presents users with a dropdown menu of options to choose from.",
|
|
7
|
+
"lifecycleState": "Stable",
|
|
8
|
+
"order": 999,
|
|
9
|
+
"repoPath": "packages/nimbus/src/components/select/select.mdx",
|
|
10
|
+
"menu": [
|
|
11
|
+
"Components",
|
|
12
|
+
"Inputs",
|
|
13
|
+
"Select input"
|
|
14
|
+
],
|
|
15
|
+
"route": "components/inputs/select-input",
|
|
16
|
+
"tags": [
|
|
17
|
+
"component",
|
|
18
|
+
"select",
|
|
19
|
+
"dropdown",
|
|
20
|
+
"picker",
|
|
21
|
+
"options"
|
|
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
|
+
"value": "Variables",
|
|
47
|
+
"href": "#variables",
|
|
48
|
+
"depth": 2,
|
|
49
|
+
"numbering": [
|
|
50
|
+
1,
|
|
51
|
+
2
|
|
52
|
+
],
|
|
53
|
+
"parent": "root"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"value": "Height options",
|
|
57
|
+
"href": "#height-options",
|
|
58
|
+
"depth": 3,
|
|
59
|
+
"numbering": [
|
|
60
|
+
1,
|
|
61
|
+
2,
|
|
62
|
+
1
|
|
63
|
+
],
|
|
64
|
+
"parent": "root"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"value": "Medium",
|
|
68
|
+
"href": "#medium",
|
|
69
|
+
"depth": 4,
|
|
70
|
+
"numbering": [
|
|
71
|
+
1,
|
|
72
|
+
2,
|
|
73
|
+
1,
|
|
74
|
+
1
|
|
75
|
+
],
|
|
76
|
+
"parent": "root"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"value": "Small",
|
|
80
|
+
"href": "#small",
|
|
81
|
+
"depth": 4,
|
|
82
|
+
"numbering": [
|
|
83
|
+
1,
|
|
84
|
+
2,
|
|
85
|
+
1,
|
|
86
|
+
2
|
|
87
|
+
],
|
|
88
|
+
"parent": "root"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"value": "Fixed width",
|
|
92
|
+
"href": "#fixed-width",
|
|
93
|
+
"depth": 3,
|
|
94
|
+
"numbering": [
|
|
95
|
+
1,
|
|
96
|
+
2,
|
|
97
|
+
2
|
|
98
|
+
],
|
|
99
|
+
"parent": "root"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"value": "Solid-styled",
|
|
103
|
+
"href": "#solid-styled",
|
|
104
|
+
"depth": 4,
|
|
105
|
+
"numbering": [
|
|
106
|
+
1,
|
|
107
|
+
2,
|
|
108
|
+
2,
|
|
109
|
+
1
|
|
110
|
+
],
|
|
111
|
+
"parent": "root"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"value": "Ghost-styled",
|
|
115
|
+
"href": "#ghost-styled",
|
|
116
|
+
"depth": 4,
|
|
117
|
+
"numbering": [
|
|
118
|
+
1,
|
|
119
|
+
2,
|
|
120
|
+
2,
|
|
121
|
+
2
|
|
122
|
+
],
|
|
123
|
+
"parent": "root"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"value": "Text wrapping",
|
|
127
|
+
"href": "#text-wrapping",
|
|
128
|
+
"depth": 3,
|
|
129
|
+
"numbering": [
|
|
130
|
+
1,
|
|
131
|
+
2,
|
|
132
|
+
3
|
|
133
|
+
],
|
|
134
|
+
"parent": "root"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"value": "Text wrapping within popover",
|
|
138
|
+
"href": "#text-wrapping-within-popover",
|
|
139
|
+
"depth": 4,
|
|
140
|
+
"numbering": [
|
|
141
|
+
1,
|
|
142
|
+
2,
|
|
143
|
+
3,
|
|
144
|
+
1
|
|
145
|
+
],
|
|
146
|
+
"parent": "root"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"value": "Truncate when long line item is selected",
|
|
150
|
+
"href": "#truncate-when-long-line-item-is-selected",
|
|
151
|
+
"depth": 4,
|
|
152
|
+
"numbering": [
|
|
153
|
+
1,
|
|
154
|
+
2,
|
|
155
|
+
3,
|
|
156
|
+
2
|
|
157
|
+
],
|
|
158
|
+
"parent": "root"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"value": "Validation",
|
|
162
|
+
"href": "#validation",
|
|
163
|
+
"depth": 3,
|
|
164
|
+
"numbering": [
|
|
165
|
+
1,
|
|
166
|
+
2,
|
|
167
|
+
4
|
|
168
|
+
],
|
|
169
|
+
"parent": "root"
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"value": "Default",
|
|
173
|
+
"href": "#default",
|
|
174
|
+
"depth": 4,
|
|
175
|
+
"numbering": [
|
|
176
|
+
1,
|
|
177
|
+
2,
|
|
178
|
+
4,
|
|
179
|
+
1
|
|
180
|
+
],
|
|
181
|
+
"parent": "root"
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"value": "Invalid",
|
|
185
|
+
"href": "#invalid",
|
|
186
|
+
"depth": 4,
|
|
187
|
+
"numbering": [
|
|
188
|
+
1,
|
|
189
|
+
2,
|
|
190
|
+
4,
|
|
191
|
+
2
|
|
192
|
+
],
|
|
193
|
+
"parent": "root"
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"value": "Disabled",
|
|
197
|
+
"href": "#disabled",
|
|
198
|
+
"depth": 4,
|
|
199
|
+
"numbering": [
|
|
200
|
+
1,
|
|
201
|
+
2,
|
|
202
|
+
4,
|
|
203
|
+
3
|
|
204
|
+
],
|
|
205
|
+
"parent": "root"
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"value": "Placeholder",
|
|
209
|
+
"href": "#placeholder",
|
|
210
|
+
"depth": 4,
|
|
211
|
+
"numbering": [
|
|
212
|
+
1,
|
|
213
|
+
2,
|
|
214
|
+
4,
|
|
215
|
+
4
|
|
216
|
+
],
|
|
217
|
+
"parent": "root"
|
|
218
|
+
}
|
|
219
|
+
],
|
|
220
|
+
"figmaLink": "https://www.figma.com/design/AvtPX6g7OGGCRvNlatGOIY/NIMBUS-design-system?node-id=2304-22847&m=dev",
|
|
221
|
+
"layout": "app-frame",
|
|
222
|
+
"tabs": [
|
|
223
|
+
{
|
|
224
|
+
"key": "overview",
|
|
225
|
+
"title": "Overview",
|
|
226
|
+
"order": 0
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
"key": "guidelines",
|
|
230
|
+
"title": "Guidelines",
|
|
231
|
+
"order": 2
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
"key": "dev",
|
|
235
|
+
"title": "Implementation",
|
|
236
|
+
"order": 3
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"key": "a11y",
|
|
240
|
+
"title": "Accessibility",
|
|
241
|
+
"order": 4
|
|
242
|
+
}
|
|
243
|
+
]
|
|
244
|
+
},
|
|
245
|
+
"mdx": "\n## Overview\n\nSelect inputs have two main appearances, two sizes, and several states that will\nrespond to validation status. **Currently, this is a single value selector, this\nwill be reworked to bring in multi-select in the future.**\n\n### Resources\n\n[ARIA APG: Listbox Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/listbox/)\n[React ARIA: Select](https://react-spectrum.adobe.com/react-aria/Select.html)\n[Figma Library](https://www.figma.com/design/AvtPX6g7OGGCRvNlatGOIY/NIMBUS-design-system?node-id=2304-22847&m=dev)\n\n## Variables\n\nGet familiar with the features.\n\n### Height options\n\n#### Medium\n\nThis is the default size for the select input.\n\n```jsx live\nconst App = () => (\n <Select.Root size=\"md\" aria-label=\"Select a fruit\">\n <Select.Options>\n <Select.Option>Apples</Select.Option>\n <Select.Option>Bananas</Select.Option>\n <Select.Option>Oranges</Select.Option>\n <Select.Option>Cherries</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n#### Small\n\nFor use in areas that require more condensed styling.\n\n```jsx live\nconst App = () => (\n <Select.Root size=\"sm\" aria-label=\"Select a fruit\">\n <Select.Options>\n <Select.Option>Apples</Select.Option>\n <Select.Option>Bananas</Select.Option>\n <Select.Option>Oranges</Select.Option>\n <Select.Option>Cherries</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n### Fixed width\n\n#### Solid-styled\n\nMax width when not in a page wide form should be 268px. If the solid-styled\nselect input field is inline a page wide form match popover width to match the\nsize of the form fields.\n\n```jsx live\nconst App = () => (\n <Select.Root aria-label=\"Select a fruit\">\n <Select.Options>\n <Select.Option>Apples</Select.Option>\n <Select.Option>Bananas</Select.Option>\n <Select.Option>Oranges</Select.Option>\n <Select.Option>Cherries</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n#### Ghost-styled\n\nHug the select-input field, this styling needs closer placement to the drop down\nicon than a solid-styled version. The popover width has two options with this\nplacement based on content. Short content should match the hug width of the\nfield. Longer content should have a max width of 268px.\n\n```jsx live\nconst App = () => (\n <Select.Root variant=\"ghost\" aria-label=\"Select a fruit\">\n <Select.Options>\n <Select.Option>Apples</Select.Option>\n <Select.Option>Bananas</Select.Option>\n <Select.Option>Oranges</Select.Option>\n <Select.Option>Cherries</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n### Text wrapping\n\n#### Text wrapping within popover\n\nPlease encourage short text when possible. When applicable, wrap text onto\nanother line when needed.\n\n```jsx live\nconst App = () => (\n <Select.Root defaultSelectedKey=\"project-1\" w=\"6400\">\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"project-long\">\n Project with a very long name\n </Select.Option>\n <Select.Option id=\"project-1\">Project 1</Select.Option>\n <Select.Option id=\"abc\">ABC</Select.Option>\n <Select.Option id=\"project-2lines\">\n Project with an even longer name that breaks into 2 lines\n </Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n#### Truncate when long line item is selected\n\nIf selected, truncate text so it does not overlap over the icons in the select\ninput field.\n\n```jsx live\nconst App = () => (\n <Select.Root defaultSelectedKey=\"project-2lines\" w=\"6400\">\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"project-long\">\n Project with a very long name\n </Select.Option>\n <Select.Option id=\"project-1\">Project 1</Select.Option>\n <Select.Option id=\"abc\">ABC</Select.Option>\n <Select.Option id=\"project-2lines\">\n Project with an even longer name that breaks into 2 lines\n </Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n### Validation\n\n#### Default\n\nA select input's prompting the user to make a choice without implying a specific\nselection.\n\n```jsx live\nconst App = () => (\n <Select.Root aria-label=\"Select a fruit\">\n <Select.Options>\n <Select.Option>Apples</Select.Option>\n <Select.Option>Bananas</Select.Option>\n <Select.Option>Oranges</Select.Option>\n <Select.Option>Cherries</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n#### Invalid\n\nUse to immediately communicate the error to the user. Utilize error text when\nneeded.\n\n```jsx live\nconst App = () => (\n <Select.Root aria-label=\"Select a fruit\" isInvalid>\n <Select.Options>\n <Select.Option>Apples</Select.Option>\n <Select.Option>Bananas</Select.Option>\n <Select.Option>Oranges</Select.Option>\n <Select.Option>Cherries</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n#### Disabled\n\nThis is the disabled state.\n\n```jsx live\nconst App = () => (\n <Select.Root aria-label=\"Select a fruit\" isDisabled>\n <Select.Options>\n <Select.Option>Apples</Select.Option>\n <Select.Option>Bananas</Select.Option>\n <Select.Option>Oranges</Select.Option>\n <Select.Option>Cherries</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n#### Placeholder\n\nThe purpose of placeholder text is to provide a clear prompt or instruction,\nguiding the user on what action is expected.\n\n```jsx live\nconst App = () => (\n <Select.Root placeholder=\"Select a fruit\" aria-label=\"Select a fruit\">\n <Select.Options>\n <Select.Option>Apples</Select.Option>\n <Select.Option>Bananas</Select.Option>\n <Select.Option>Oranges</Select.Option>\n <Select.Option>Cherries</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n",
|
|
246
|
+
"views": {
|
|
247
|
+
"overview": {
|
|
248
|
+
"mdx": "\n## Overview\n\nSelect inputs have two main appearances, two sizes, and several states that will\nrespond to validation status. **Currently, this is a single value selector, this\nwill be reworked to bring in multi-select in the future.**\n\n### Resources\n\n[ARIA APG: Listbox Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/listbox/)\n[React ARIA: Select](https://react-spectrum.adobe.com/react-aria/Select.html)\n[Figma Library](https://www.figma.com/design/AvtPX6g7OGGCRvNlatGOIY/NIMBUS-design-system?node-id=2304-22847&m=dev)\n\n## Variables\n\nGet familiar with the features.\n\n### Height options\n\n#### Medium\n\nThis is the default size for the select input.\n\n```jsx live\nconst App = () => (\n <Select.Root size=\"md\" aria-label=\"Select a fruit\">\n <Select.Options>\n <Select.Option>Apples</Select.Option>\n <Select.Option>Bananas</Select.Option>\n <Select.Option>Oranges</Select.Option>\n <Select.Option>Cherries</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n#### Small\n\nFor use in areas that require more condensed styling.\n\n```jsx live\nconst App = () => (\n <Select.Root size=\"sm\" aria-label=\"Select a fruit\">\n <Select.Options>\n <Select.Option>Apples</Select.Option>\n <Select.Option>Bananas</Select.Option>\n <Select.Option>Oranges</Select.Option>\n <Select.Option>Cherries</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n### Fixed width\n\n#### Solid-styled\n\nMax width when not in a page wide form should be 268px. If the solid-styled\nselect input field is inline a page wide form match popover width to match the\nsize of the form fields.\n\n```jsx live\nconst App = () => (\n <Select.Root aria-label=\"Select a fruit\">\n <Select.Options>\n <Select.Option>Apples</Select.Option>\n <Select.Option>Bananas</Select.Option>\n <Select.Option>Oranges</Select.Option>\n <Select.Option>Cherries</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n#### Ghost-styled\n\nHug the select-input field, this styling needs closer placement to the drop down\nicon than a solid-styled version. The popover width has two options with this\nplacement based on content. Short content should match the hug width of the\nfield. Longer content should have a max width of 268px.\n\n```jsx live\nconst App = () => (\n <Select.Root variant=\"ghost\" aria-label=\"Select a fruit\">\n <Select.Options>\n <Select.Option>Apples</Select.Option>\n <Select.Option>Bananas</Select.Option>\n <Select.Option>Oranges</Select.Option>\n <Select.Option>Cherries</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n### Text wrapping\n\n#### Text wrapping within popover\n\nPlease encourage short text when possible. When applicable, wrap text onto\nanother line when needed.\n\n```jsx live\nconst App = () => (\n <Select.Root defaultSelectedKey=\"project-1\" w=\"6400\">\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"project-long\">\n Project with a very long name\n </Select.Option>\n <Select.Option id=\"project-1\">Project 1</Select.Option>\n <Select.Option id=\"abc\">ABC</Select.Option>\n <Select.Option id=\"project-2lines\">\n Project with an even longer name that breaks into 2 lines\n </Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n#### Truncate when long line item is selected\n\nIf selected, truncate text so it does not overlap over the icons in the select\ninput field.\n\n```jsx live\nconst App = () => (\n <Select.Root defaultSelectedKey=\"project-2lines\" w=\"6400\">\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"project-long\">\n Project with a very long name\n </Select.Option>\n <Select.Option id=\"project-1\">Project 1</Select.Option>\n <Select.Option id=\"abc\">ABC</Select.Option>\n <Select.Option id=\"project-2lines\">\n Project with an even longer name that breaks into 2 lines\n </Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n### Validation\n\n#### Default\n\nA select input's prompting the user to make a choice without implying a specific\nselection.\n\n```jsx live\nconst App = () => (\n <Select.Root aria-label=\"Select a fruit\">\n <Select.Options>\n <Select.Option>Apples</Select.Option>\n <Select.Option>Bananas</Select.Option>\n <Select.Option>Oranges</Select.Option>\n <Select.Option>Cherries</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n#### Invalid\n\nUse to immediately communicate the error to the user. Utilize error text when\nneeded.\n\n```jsx live\nconst App = () => (\n <Select.Root aria-label=\"Select a fruit\" isInvalid>\n <Select.Options>\n <Select.Option>Apples</Select.Option>\n <Select.Option>Bananas</Select.Option>\n <Select.Option>Oranges</Select.Option>\n <Select.Option>Cherries</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n#### Disabled\n\nThis is the disabled state.\n\n```jsx live\nconst App = () => (\n <Select.Root aria-label=\"Select a fruit\" isDisabled>\n <Select.Options>\n <Select.Option>Apples</Select.Option>\n <Select.Option>Bananas</Select.Option>\n <Select.Option>Oranges</Select.Option>\n <Select.Option>Cherries</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n#### Placeholder\n\nThe purpose of placeholder text is to provide a clear prompt or instruction,\nguiding the user on what action is expected.\n\n```jsx live\nconst App = () => (\n <Select.Root placeholder=\"Select a fruit\" aria-label=\"Select a fruit\">\n <Select.Options>\n <Select.Option>Apples</Select.Option>\n <Select.Option>Bananas</Select.Option>\n <Select.Option>Oranges</Select.Option>\n <Select.Option>Cherries</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n",
|
|
249
|
+
"toc": [
|
|
250
|
+
{
|
|
251
|
+
"value": "Overview",
|
|
252
|
+
"href": "#overview",
|
|
253
|
+
"depth": 2,
|
|
254
|
+
"numbering": [
|
|
255
|
+
1,
|
|
256
|
+
1
|
|
257
|
+
],
|
|
258
|
+
"parent": "root"
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"value": "Resources",
|
|
262
|
+
"href": "#resources",
|
|
263
|
+
"depth": 3,
|
|
264
|
+
"numbering": [
|
|
265
|
+
1,
|
|
266
|
+
1,
|
|
267
|
+
1
|
|
268
|
+
],
|
|
269
|
+
"parent": "root"
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"value": "Variables",
|
|
273
|
+
"href": "#variables",
|
|
274
|
+
"depth": 2,
|
|
275
|
+
"numbering": [
|
|
276
|
+
1,
|
|
277
|
+
2
|
|
278
|
+
],
|
|
279
|
+
"parent": "root"
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"value": "Height options",
|
|
283
|
+
"href": "#height-options",
|
|
284
|
+
"depth": 3,
|
|
285
|
+
"numbering": [
|
|
286
|
+
1,
|
|
287
|
+
2,
|
|
288
|
+
1
|
|
289
|
+
],
|
|
290
|
+
"parent": "root"
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
"value": "Medium",
|
|
294
|
+
"href": "#medium",
|
|
295
|
+
"depth": 4,
|
|
296
|
+
"numbering": [
|
|
297
|
+
1,
|
|
298
|
+
2,
|
|
299
|
+
1,
|
|
300
|
+
1
|
|
301
|
+
],
|
|
302
|
+
"parent": "root"
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"value": "Small",
|
|
306
|
+
"href": "#small",
|
|
307
|
+
"depth": 4,
|
|
308
|
+
"numbering": [
|
|
309
|
+
1,
|
|
310
|
+
2,
|
|
311
|
+
1,
|
|
312
|
+
2
|
|
313
|
+
],
|
|
314
|
+
"parent": "root"
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
"value": "Fixed width",
|
|
318
|
+
"href": "#fixed-width",
|
|
319
|
+
"depth": 3,
|
|
320
|
+
"numbering": [
|
|
321
|
+
1,
|
|
322
|
+
2,
|
|
323
|
+
2
|
|
324
|
+
],
|
|
325
|
+
"parent": "root"
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
"value": "Solid-styled",
|
|
329
|
+
"href": "#solid-styled",
|
|
330
|
+
"depth": 4,
|
|
331
|
+
"numbering": [
|
|
332
|
+
1,
|
|
333
|
+
2,
|
|
334
|
+
2,
|
|
335
|
+
1
|
|
336
|
+
],
|
|
337
|
+
"parent": "root"
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
"value": "Ghost-styled",
|
|
341
|
+
"href": "#ghost-styled",
|
|
342
|
+
"depth": 4,
|
|
343
|
+
"numbering": [
|
|
344
|
+
1,
|
|
345
|
+
2,
|
|
346
|
+
2,
|
|
347
|
+
2
|
|
348
|
+
],
|
|
349
|
+
"parent": "root"
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
"value": "Text wrapping",
|
|
353
|
+
"href": "#text-wrapping",
|
|
354
|
+
"depth": 3,
|
|
355
|
+
"numbering": [
|
|
356
|
+
1,
|
|
357
|
+
2,
|
|
358
|
+
3
|
|
359
|
+
],
|
|
360
|
+
"parent": "root"
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
"value": "Text wrapping within popover",
|
|
364
|
+
"href": "#text-wrapping-within-popover",
|
|
365
|
+
"depth": 4,
|
|
366
|
+
"numbering": [
|
|
367
|
+
1,
|
|
368
|
+
2,
|
|
369
|
+
3,
|
|
370
|
+
1
|
|
371
|
+
],
|
|
372
|
+
"parent": "root"
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
"value": "Truncate when long line item is selected",
|
|
376
|
+
"href": "#truncate-when-long-line-item-is-selected",
|
|
377
|
+
"depth": 4,
|
|
378
|
+
"numbering": [
|
|
379
|
+
1,
|
|
380
|
+
2,
|
|
381
|
+
3,
|
|
382
|
+
2
|
|
383
|
+
],
|
|
384
|
+
"parent": "root"
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
"value": "Validation",
|
|
388
|
+
"href": "#validation",
|
|
389
|
+
"depth": 3,
|
|
390
|
+
"numbering": [
|
|
391
|
+
1,
|
|
392
|
+
2,
|
|
393
|
+
4
|
|
394
|
+
],
|
|
395
|
+
"parent": "root"
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
"value": "Default",
|
|
399
|
+
"href": "#default",
|
|
400
|
+
"depth": 4,
|
|
401
|
+
"numbering": [
|
|
402
|
+
1,
|
|
403
|
+
2,
|
|
404
|
+
4,
|
|
405
|
+
1
|
|
406
|
+
],
|
|
407
|
+
"parent": "root"
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
"value": "Invalid",
|
|
411
|
+
"href": "#invalid",
|
|
412
|
+
"depth": 4,
|
|
413
|
+
"numbering": [
|
|
414
|
+
1,
|
|
415
|
+
2,
|
|
416
|
+
4,
|
|
417
|
+
2
|
|
418
|
+
],
|
|
419
|
+
"parent": "root"
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
"value": "Disabled",
|
|
423
|
+
"href": "#disabled",
|
|
424
|
+
"depth": 4,
|
|
425
|
+
"numbering": [
|
|
426
|
+
1,
|
|
427
|
+
2,
|
|
428
|
+
4,
|
|
429
|
+
3
|
|
430
|
+
],
|
|
431
|
+
"parent": "root"
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
"value": "Placeholder",
|
|
435
|
+
"href": "#placeholder",
|
|
436
|
+
"depth": 4,
|
|
437
|
+
"numbering": [
|
|
438
|
+
1,
|
|
439
|
+
2,
|
|
440
|
+
4,
|
|
441
|
+
4
|
|
442
|
+
],
|
|
443
|
+
"parent": "root"
|
|
444
|
+
}
|
|
445
|
+
]
|
|
446
|
+
},
|
|
447
|
+
"a11y": {
|
|
448
|
+
"mdx": "\n## Accessibility\n\nAccessibility ensures that digital content and functionality are usable by\neveryone, including people with disabilities, by addressing visual, auditory,\ncognitive, and physical limitations.\n\n```jsx live\nconst App = () => (\n <Select.Root size=\"md\" aria-label=\"Select a fruit\">\n <Select.Options>\n <Select.Option>Apples</Select.Option>\n <Select.Option>Bananas</Select.Option>\n <Select.Option>Oranges</Select.Option>\n <Select.Option>Cherries</Select.Option>\n </Select.Options>\n </Select.Root>\n)\n```\n\n### Accessibility standards\n\n- **Provide clear labels:** Use the `<label>` element to programmatically\n associate a clear, descriptive label with the select input.\n- **Group related inputs:** Group related select inputs within a `<fieldset>`\n and provide a `<legend>` to give context to the group.\n- **Don't rely on color alone:** Avoid relying solely on color to convey\n information or the state of the select input. Ensure other visual cues convey\n the necessary information.\n- **Ensure sufficient contrast:** Ensure sufficient color contrast exists\n between the select input's text, background, and border. Use a contrast\n checking tool to verify contrast ratios meet minimum requirements.\n- **Keyboard navigation:** Make the select input fully operable using the\n keyboard. Allow users to navigate using Tab, open/close dropdown with Spacebar\n or Enter, navigate options with arrow keys, and select with Enter.\n- **Focus visible:** Provide a clear and visible focus indicator for the select\n input when it receives keyboard focus.\n- **No unexpected changes:** Prevent the select input from unexpectedly changing\n the context of the page when it receives focus. Ensure changes are initiated\n by user selection.\n- **Clear instructions:** Provide clear and concise labels or instructions for\n the select input that accurately reflect its purpose.\n- **Error suggestions:** If an input error is automatically detected and\n suggestions for correction are known, provide the suggestions to the user.\n- **Use semantic HTML:** Use semantic HTML elements (`<select>`, `<option>`) to\n define the role, name, and value of the select input.\n- **ARIA attributes:** Use ARIA attributes when necessary to provide additional\n information to assistive technologies, especially for complex or custom\n implementations.\n\n### Resources\n\n- [W3C ARIA Authoring Practices Guide (APG) - Listbox](https://www.w3.org/WAI/ARIA/apg/patterns/listbox/)\n",
|
|
449
|
+
"toc": [
|
|
450
|
+
{
|
|
451
|
+
"value": "Accessibility",
|
|
452
|
+
"href": "#accessibility",
|
|
453
|
+
"depth": 2,
|
|
454
|
+
"numbering": [
|
|
455
|
+
1,
|
|
456
|
+
1
|
|
457
|
+
],
|
|
458
|
+
"parent": "root"
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
"value": "Accessibility standards",
|
|
462
|
+
"href": "#accessibility-standards",
|
|
463
|
+
"depth": 3,
|
|
464
|
+
"numbering": [
|
|
465
|
+
1,
|
|
466
|
+
1,
|
|
467
|
+
1
|
|
468
|
+
],
|
|
469
|
+
"parent": "root"
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
"value": "Resources",
|
|
473
|
+
"href": "#resources",
|
|
474
|
+
"depth": 3,
|
|
475
|
+
"numbering": [
|
|
476
|
+
1,
|
|
477
|
+
1,
|
|
478
|
+
2
|
|
479
|
+
],
|
|
480
|
+
"parent": "root"
|
|
481
|
+
}
|
|
482
|
+
]
|
|
483
|
+
},
|
|
484
|
+
"dev": {
|
|
485
|
+
"mdx": "\n## Getting started\n\n### Import\n\n```tsx\nimport { Select, type SelectProps } from '@commercetools/nimbus';\n```\n\n### Basic usage\n\nThe simplest implementation uses uncontrolled mode:\n\n```jsx live-dev\nconst App = () => (\n <Select.Root aria-label=\"Select a fruit\">\n <Select.Options placeholder=\"Select an option\">\n <Select.Option id=\"apple\">Apple</Select.Option>\n <Select.Option id=\"banana\">Banana</Select.Option>\n <Select.Option id=\"orange\">Orange</Select.Option>\n </Select.Options>\n </Select.Root>\n)\n```\n\n## Working with selection values\n\nThe Select component uses React Aria's selection pattern, which uses keys (strings or numbers) to identify selected options.\n\n### Selection value types\n\nThe component accepts and returns selection keys:\n\n```tsx\n// String keys \n<Select.Option id=\"apple\">Apple</Select.Option>\n\n// Number keys\n<Select.Option id={1}>Option 1</Select.Option>\n```\n\n\n### Selection structure\n\n```tsx\n// Uncontrolled mode\n<Select.Root\n defaultSelectedKey=\"apple\"\n onSelectionChange={(key) => {}}\n>\n <Select.Options>\n <Select.Option id=\"apple\">Apple</Select.Option>\n </Select.Options>\n</Select.Root>\n\n// Controlled mode\nconst [selectedKey, setSelectedKey] = useState<Key | null>(null);\n\n<Select.Root\n selectedKey={selectedKey}\n onSelectionChange={setSelectedKey}\n>\n <Select.Options>\n <Select.Option id=\"apple\">Apple</Select.Option>\n </Select.Options>\n</Select.Root>\n```\n\n## Usage examples\n\n### Size options\n\nThe `sm` and `md` size variants are available to match your interface density:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n <Select.Root size=\"sm\" aria-label=\"Small select\">\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"1\">Option 1</Select.Option>\n <Select.Option id=\"2\">Option 2</Select.Option>\n </Select.Options>\n </Select.Root>\n <Select.Root size=\"md\" aria-label=\"Medium select\">\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"1\">Option 1</Select.Option>\n <Select.Option id=\"2\">Option 2</Select.Option>\n </Select.Options>\n </Select.Root>\n </Stack>\n)\n```\n\n### Disabled state\n\nUse `isDisabled` to disable the select:\n\n```jsx live-dev\nconst App = () => (\n <Select.Root isDisabled aria-label=\"Disabled select\">\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"1\">Option 1</Select.Option>\n <Select.Option id=\"2\">Option 2</Select.Option>\n </Select.Options>\n </Select.Root>\n)\n```\n\n### Visual variants\n\nChoose between `outline` and `ghost` variants to match your design context:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n <Select.Root variant=\"outline\" aria-label=\"Outline select\">\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"1\">Option 1</Select.Option>\n <Select.Option id=\"2\">Option 2</Select.Option>\n </Select.Options>\n </Select.Root>\n <Select.Root variant=\"ghost\" aria-label=\"Ghost select\">\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"1\">Option 1</Select.Option>\n <Select.Option id=\"2\">Option 2</Select.Option>\n </Select.Options>\n </Select.Root>\n </Stack>\n)\n```\n\n### Uncontrolled mode\n\nFor simpler use cases, use uncontrolled mode with `defaultSelectedKey` and `onSelectionChange`:\n\n```jsx live-dev\nconst App = () => {\n const [selectedValue, setSelectedValue] = useState<string>('Selected: banana');\n\n return (\n <Stack direction=\"column\" gap=\"400\">\n <Select.Root\n defaultSelectedKey=\"banana\"\n onSelectionChange={(key) => {\n setSelectedValue(key ? `Selected: ${key}` : 'No selection');\n }}\n aria-label=\"Select a fruit\"\n >\n <Select.Options placeholder=\"Choose a fruit\">\n <Select.Option id=\"apple\">Apple</Select.Option>\n <Select.Option id=\"banana\">Banana</Select.Option>\n <Select.Option id=\"orange\">Orange</Select.Option>\n </Select.Options>\n </Select.Root>\n <Text fontSize=\"sm\">{selectedValue}</Text>\n </Stack>\n );\n}\n```\n\n\n### Controlled mode\n\n\nFor scenarios requiring programmatic control or coordination with other components, use controlled mode:\n\n```jsx live-dev\nconst App = () => {\n const [selectedKey, setSelectedKey] = useState<Key | null>(null);\n\n return (\n <Stack direction=\"column\" gap=\"400\">\n <Select.Root\n selectedKey={selectedKey}\n onSelectionChange={setSelectedKey}\n aria-label=\"Select a fruit\"\n >\n <Select.Options placeholder=\"Choose a fruit\">\n <Select.Option id=\"apple\">Apple</Select.Option>\n <Select.Option id=\"banana\">Banana</Select.Option>\n <Select.Option id=\"orange\">Orange</Select.Option>\n </Select.Options>\n </Select.Root>\n <Text fontSize=\"sm\">\n {selectedKey ? `Selected: ${selectedKey}` : 'No selection'}\n </Text>\n </Stack>\n );\n}\n```\n\n### Option groups\n\nGroup related options with `Select.OptionGroup`:\n\n```jsx live-dev\nconst App = () => (\n <Select.Root aria-label=\"Select a food\">\n <Select.Options placeholder=\"Choose a food\">\n <Select.OptionGroup label=\"Fruits\">\n <Select.Option id=\"apple\">Apple</Select.Option>\n <Select.Option id=\"banana\">Banana</Select.Option>\n <Select.Option id=\"orange\">Orange</Select.Option>\n </Select.OptionGroup>\n <Select.OptionGroup label=\"Vegetables\">\n <Select.Option id=\"carrot\">Carrot</Select.Option>\n <Select.Option id=\"broccoli\">Broccoli</Select.Option>\n <Select.Option id=\"spinach\">Spinach</Select.Option>\n </Select.OptionGroup>\n </Select.Options>\n </Select.Root>\n)\n```\n\n### Dynamic options with items\n\n`Select.Options` supports the `items` prop, a pattern unique to React Aria Components (inherited from React Aria's `ListBox` component). This pattern provides an efficient way to render dynamic or large lists of options.\n\n**When to use `items` vs static children:**\n\n- **Use `items` when:**\n - Rendering options from dynamic data (API responses, filtered lists, computed arrays)\n - Working with large lists (better performance through virtualization support)\n - Options change frequently based on user input or state\n - You need to map over data structures\n\n- **Use static children when:**\n - Options are known at compile time\n - You have a small, fixed set of options\n - You prefer the simpler JSX syntax for readability\n\n**Static children example:**\n\n```jsx live-dev\nconst App = () => (\n <Select.Root aria-label=\"Select a fruit\">\n <Select.Options placeholder=\"Choose a fruit\">\n <Select.Option id=\"apple\">Apple</Select.Option>\n <Select.Option id=\"banana\">Banana</Select.Option>\n <Select.Option id=\"orange\">Orange</Select.Option>\n </Select.Options>\n </Select.Root>\n)\n```\n\n**Dynamic items example:**\n\nWhen using `items`, children must be a render function that receives each item and returns a `Select.Option`. This example demonstrates using `items` with data that could come from an API, state, or computed values:\n\n```jsx live-dev\nconst App = () => {\n // In a real app, this data might come from an API, props, or state.\n const fruits = [\n { id: 'apple', name: 'Apple' },\n { id: 'banana', name: 'Banana' },\n { id: 'orange', name: 'Orange' },\n ];\n\n return (\n <Select.Root aria-label=\"Select a fruit\">\n <Select.Options items={fruits} placeholder=\"Choose a fruit\">\n {(item) => (\n <Select.Option id={item.id}>{item.name}</Select.Option>\n )}\n </Select.Options>\n </Select.Root>\n );\n}\n```\n\nThe `items` pattern enables React Aria to optimize rendering and provides better support for features like virtualization, which can improve performance with large option lists.\n\n> [!TIP]\\\n> See [React Aria's ListBox documentation](https://react-spectrum.adobe.com/react-aria/ListBox.html#sections) for complete API reference and advanced usage, including static and dynamic items.\n\n### Clearable selection\n\nUse `isClearable` to show a clear button:\n\n```jsx live-dev\nconst App = () => (\n <Select.Root\n isClearable\n defaultSelectedKey=\"banana\"\n aria-label=\"Select a fruit\"\n >\n <Select.Options placeholder=\"Choose a fruit\">\n <Select.Option id=\"apple\">Apple</Select.Option>\n <Select.Option id=\"banana\">Banana</Select.Option>\n <Select.Option id=\"orange\">Orange</Select.Option>\n </Select.Options>\n </Select.Root>\n)\n```\n\n\n### Leading element\n\nUse `leadingElement` to add an icon or element at the start of the trigger:\n\n```jsx live-dev\nconst App = () => (\n <Select.Root\n leadingElement={<Icon as={Icons.SentimentSatisfied} />}\n aria-label=\"Select an option\"\n >\n <Select.Options placeholder=\"Choose...\">\n <Select.Option id=\"1\">Option 1</Select.Option>\n <Select.Option id=\"2\">Option 2</Select.Option>\n </Select.Options>\n </Select.Root>\n)\n```\n\n\n\n## Component requirements\n\n### Selection value types\n\nSelection values **must** be keys (strings or numbers) that match the `id` prop of `Select.Option` components.\n\n## Accessibility\n\nThe Select handles most accessibility requirements internally. However, you must always associate an internationalized label with the component. Visual labels are preferable, and can be set by:\n\n- Associating a `<label>` element with the `Select.Root` using `aria-labelledby`:\n\n```tsx\n<label id=\"label-id\">\n {msg.format(labelMessage)}\n</label>\n<Select.Root aria-labelledby=\"label-id\">\n <Select.Options>\n <Select.Option id=\"1\">Option 1</Select.Option>\n </Select.Options>\n</Select.Root>\n```\n\n- Associating a `<label>` element with the `Select.Root` using `htmlFor`:\n\n```tsx\n<label htmlFor=\"select-id\">\n {msg.format(labelMessage)}\n</label>\n<Select.Root id=\"select-id\">\n <Select.Options>\n <Select.Option id=\"1\">Option 1</Select.Option>\n </Select.Options>\n</Select.Root>\n```\n\nFor hidden labels, use `aria-label`:\n\n```tsx\n<Select.Root aria-label={msg.format(labelMessage)}>\n <Select.Options>\n <Select.Option id=\"1\">Option 1</Select.Option>\n </Select.Options>\n</Select.Root>\n```\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-select\";\n\nexport const Example = () => (\n <Select.Root id={PERSISTENT_ID} aria-label=\"Select an option\">\n <Select.Options>\n <Select.Option id=\"1\">Option 1</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n#### Keyboard navigation\n\nThe component supports full keyboard interaction:\n- `Tab` / `Shift+Tab`: Navigate to/from the select\n- `Enter` / `Space`: Open the dropdown\n- `Arrow keys`: Navigate through options when open\n- `Enter`: Select the focused option\n- `Escape`: Close the dropdown\n- `Home` / `End`: Jump to first/last option\n- Type to search: Type characters to jump to matching options\n\n## API reference\n\n<PropsTable id=\"Select\" />\n\n## Common patterns\n\n### Filtering data by selection\n\nA common use case is filtering lists or tables by a selected option:\n\n```jsx live-dev\nconst App = () => {\n const [selectedCategory, setSelectedCategory] = useState<Key | null>(null);\n\n // Filter data based on selectedCategory\n const appliedFilter = selectedCategory\n ? `Showing items in category: ${selectedCategory}`\n : 'No filter applied';\n\n return (\n <Stack direction=\"column\" gap=\"400\">\n <Select.Root\n selectedKey={selectedCategory}\n onSelectionChange={setSelectedCategory}\n aria-label=\"Filter by category\"\n >\n <Select.Options placeholder=\"All categories\">\n <Select.Option id=\"electronics\">Electronics</Select.Option>\n <Select.Option id=\"clothing\">Clothing</Select.Option>\n <Select.Option id=\"books\">Books</Select.Option>\n </Select.Options>\n </Select.Root>\n <Text fontSize=\"sm\">{appliedFilter}</Text>\n </Stack>\n );\n}\n```\n\n### Country/region selection\n\nExample for selecting a country, region, or category:\n\n```jsx live-dev\nconst App = () => {\n const [country, setCountry] = useState<Key | null>(null);\n\n return (\n <Stack direction=\"column\" gap=\"400\">\n <Select.Root\n selectedKey={country}\n onSelectionChange={setCountry}\n aria-label=\"Select country\"\n isRequired\n >\n <Select.Options placeholder=\"Choose a country\">\n <Select.Option id=\"us\">United States</Select.Option>\n <Select.Option id=\"uk\">United Kingdom</Select.Option>\n <Select.Option id=\"ca\">Canada</Select.Option>\n <Select.Option id=\"de\">Germany</Select.Option>\n </Select.Options>\n </Select.Root>\n {country && (\n <Text fontSize=\"sm\">\n Selected country: {country}\n </Text>\n )}\n </Stack>\n );\n}\n```\n\n## Testing your implementation\n\nThese examples demonstrate how to test your implementation when using Select 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 component 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 { useState } from \"react\";\nimport type { Key } from \"react-aria-components\";\nimport { Select, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Select - Basic rendering\", () => {\n it(\"renders select trigger button\", () => {\n render(\n <NimbusProvider>\n <Select.Root aria-label=\"Select an option\">\n <Select.Options>\n <Select.Option id=\"1\">Option 1</Select.Option>\n </Select.Options>\n </Select.Root>\n </NimbusProvider>\n );\n\n expect(\n screen.getByRole(\"button\", { name: /Select an option/ })\n ).toBeInTheDocument();\n });\n\n it(\"displays default placeholder text\", () => {\n render(\n <NimbusProvider>\n <Select.Root aria-label=\"Select an option\">\n <Select.Options>\n <Select.Option id=\"1\">Option 1</Select.Option>\n </Select.Options>\n </Select.Root>\n </NimbusProvider>\n );\n\n // Default placeholder is \"Select an item\"\n expect(screen.getByText(\"Select an item\")).toBeInTheDocument();\n });\n});\n```\n\n### Interaction Tests\n\nTest user interactions with the component\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 { useState } from \"react\";\nimport type { Key } from \"react-aria-components\";\nimport { Select, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Select - Interactions\", () => {\n it(\"opens dropdown when button is clicked\", async () => {\n const user = userEvent.setup();\n render(\n <NimbusProvider>\n <Select.Root aria-label=\"Select an option\">\n <Select.Options>\n <Select.Option id=\"1\">Option 1</Select.Option>\n <Select.Option id=\"2\">Option 2</Select.Option>\n </Select.Options>\n </Select.Root>\n </NimbusProvider>\n );\n\n const select = screen.getByRole(\"button\", { name: /Select an option/ });\n await user.click(select);\n\n // The popover is rendered via a react portal outside of the select root\n // and can only be found by querying the document directly\n await waitFor(() => {\n const listbox = document.querySelector('[role=\"listbox\"]');\n expect(listbox).toBeInTheDocument();\n });\n });\n\n it(\"selects an option when clicked\", async () => {\n const user = userEvent.setup();\n const handleSelectionChange = vi.fn();\n render(\n <NimbusProvider>\n <Select.Root\n aria-label=\"Select an option\"\n onSelectionChange={handleSelectionChange}\n >\n <Select.Options>\n <Select.Option id=\"1\">Option 1</Select.Option>\n <Select.Option id=\"2\">Option 2</Select.Option>\n </Select.Options>\n </Select.Root>\n </NimbusProvider>\n );\n\n const select = screen.getByRole(\"button\", { name: /Select an option/ });\n await user.click(select);\n\n // Options are in the portal, query the document directly\n await waitFor(() => {\n const options = document.querySelectorAll('[role=\"option\"]');\n expect(options.length).toBeGreaterThan(0);\n });\n const options = document.querySelectorAll('[role=\"option\"]');\n await user.click(options[1]);\n\n expect(handleSelectionChange).toHaveBeenCalledWith(\"2\");\n });\n});\n```\n\n### Controlled State Tests\n\nTest controlled selection state\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 { useState } from \"react\";\nimport type { Key } from \"react-aria-components\";\nimport { Select, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Select - Controlled state\", () => {\n it(\"displays selected value\", () => {\n const TestComponent = () => {\n const [selectedKey] = useState<Key | null>(\"2\");\n return (\n <NimbusProvider>\n <Select.Root\n selectedKey={selectedKey}\n onSelectionChange={() => {}}\n aria-label=\"Select an option\"\n >\n <Select.Options>\n <Select.Option id=\"1\">Option 1</Select.Option>\n <Select.Option id=\"2\">Option 2</Select.Option>\n </Select.Options>\n </Select.Root>\n </NimbusProvider>\n );\n };\n\n render(<TestComponent />);\n\n // The selected value appears in the button label\n const button = screen.getByRole(\"button\", { name: /Select an option/ });\n expect(button).toHaveTextContent(\"Option 2\");\n });\n});\n```\n\n### Option Group Tests\n\nTest rendering with option groups\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 { useState } from \"react\";\nimport type { Key } from \"react-aria-components\";\nimport { Select, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Select - Option groups\", () => {\n it(\"renders grouped options\", async () => {\n const user = userEvent.setup();\n render(\n <NimbusProvider>\n <Select.Root aria-label=\"Select an option\">\n <Select.Options>\n <Select.OptionGroup label=\"Fruits\">\n <Select.Option id=\"apple\">Apple</Select.Option>\n <Select.Option id=\"banana\">Banana</Select.Option>\n </Select.OptionGroup>\n <Select.OptionGroup label=\"Vegetables\">\n <Select.Option id=\"carrot\">Carrot</Select.Option>\n </Select.OptionGroup>\n </Select.Options>\n </Select.Root>\n </NimbusProvider>\n );\n\n const select = screen.getByRole(\"button\", { name: /Select an option/ });\n await user.click(select);\n\n await waitFor(() => {\n expect(screen.getByText(\"Fruits\")).toBeInTheDocument();\n expect(screen.getByText(\"Vegetables\")).toBeInTheDocument();\n });\n });\n});\n```\n\n### Disabled State Tests\n\nTest that the select is properly disabled\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 { useState } from \"react\";\nimport type { Key } from \"react-aria-components\";\nimport { Select, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Select - Disabled state\", () => {\n it(\"renders disabled select\", () => {\n render(\n <NimbusProvider>\n <Select.Root isDisabled aria-label=\"Select an option\">\n <Select.Options>\n <Select.Option id=\"1\">Option 1</Select.Option>\n </Select.Options>\n </Select.Root>\n </NimbusProvider>\n );\n\n const select = screen.getByRole(\"button\", { name: /Select an option/ });\n expect(select).toBeDisabled();\n });\n});\n```\n\n### Invalid State Tests\n\nTest that the select is properly marked as invalid\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 { useState } from \"react\";\nimport type { Key } from \"react-aria-components\";\nimport { Select, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Select - Invalid state\", () => {\n it(\"renders invalid select\", () => {\n render(\n <NimbusProvider>\n <Select.Root isInvalid aria-label=\"Select an option\">\n <Select.Options>\n <Select.Option id=\"1\">Option 1</Select.Option>\n </Select.Options>\n </Select.Root>\n </NimbusProvider>\n );\n\n // Invalid state is on the root element.\n const button = screen.getByRole(\"button\", { name: /Select an option/ });\n const selectRoot = button.closest('[data-invalid=\"true\"]');\n expect(selectRoot).toBeInTheDocument();\n });\n});\n```\n\n\n## Resources\n\n- [Storybook](https://nimbus-storybook.vercel.app/?path=/docs/components-select--docs)\n- [React Aria Select](https://react-spectrum.adobe.com/react-aria/Select.html)\n- [ARIA Listbox Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/listbox/)",
|
|
486
|
+
"toc": [
|
|
487
|
+
{
|
|
488
|
+
"value": "Getting started",
|
|
489
|
+
"href": "#getting-started",
|
|
490
|
+
"depth": 2,
|
|
491
|
+
"numbering": [
|
|
492
|
+
1,
|
|
493
|
+
1
|
|
494
|
+
],
|
|
495
|
+
"parent": "root"
|
|
496
|
+
},
|
|
497
|
+
{
|
|
498
|
+
"value": "Import",
|
|
499
|
+
"href": "#import",
|
|
500
|
+
"depth": 3,
|
|
501
|
+
"numbering": [
|
|
502
|
+
1,
|
|
503
|
+
1,
|
|
504
|
+
1
|
|
505
|
+
],
|
|
506
|
+
"parent": "root"
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
"value": "Basic usage",
|
|
510
|
+
"href": "#basic-usage",
|
|
511
|
+
"depth": 3,
|
|
512
|
+
"numbering": [
|
|
513
|
+
1,
|
|
514
|
+
1,
|
|
515
|
+
2
|
|
516
|
+
],
|
|
517
|
+
"parent": "root"
|
|
518
|
+
},
|
|
519
|
+
{
|
|
520
|
+
"value": "Working with selection values",
|
|
521
|
+
"href": "#working-with-selection-values",
|
|
522
|
+
"depth": 2,
|
|
523
|
+
"numbering": [
|
|
524
|
+
1,
|
|
525
|
+
2
|
|
526
|
+
],
|
|
527
|
+
"parent": "root"
|
|
528
|
+
},
|
|
529
|
+
{
|
|
530
|
+
"value": "Selection value types",
|
|
531
|
+
"href": "#selection-value-types",
|
|
532
|
+
"depth": 3,
|
|
533
|
+
"numbering": [
|
|
534
|
+
1,
|
|
535
|
+
2,
|
|
536
|
+
1
|
|
537
|
+
],
|
|
538
|
+
"parent": "root"
|
|
539
|
+
},
|
|
540
|
+
{
|
|
541
|
+
"value": "Selection structure",
|
|
542
|
+
"href": "#selection-structure",
|
|
543
|
+
"depth": 3,
|
|
544
|
+
"numbering": [
|
|
545
|
+
1,
|
|
546
|
+
2,
|
|
547
|
+
2
|
|
548
|
+
],
|
|
549
|
+
"parent": "root"
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
"value": "Usage examples",
|
|
553
|
+
"href": "#usage-examples",
|
|
554
|
+
"depth": 2,
|
|
555
|
+
"numbering": [
|
|
556
|
+
1,
|
|
557
|
+
3
|
|
558
|
+
],
|
|
559
|
+
"parent": "root"
|
|
560
|
+
},
|
|
561
|
+
{
|
|
562
|
+
"value": "Size options",
|
|
563
|
+
"href": "#size-options",
|
|
564
|
+
"depth": 3,
|
|
565
|
+
"numbering": [
|
|
566
|
+
1,
|
|
567
|
+
3,
|
|
568
|
+
1
|
|
569
|
+
],
|
|
570
|
+
"parent": "root"
|
|
571
|
+
},
|
|
572
|
+
{
|
|
573
|
+
"value": "Disabled state",
|
|
574
|
+
"href": "#disabled-state",
|
|
575
|
+
"depth": 3,
|
|
576
|
+
"numbering": [
|
|
577
|
+
1,
|
|
578
|
+
3,
|
|
579
|
+
2
|
|
580
|
+
],
|
|
581
|
+
"parent": "root"
|
|
582
|
+
},
|
|
583
|
+
{
|
|
584
|
+
"value": "Visual variants",
|
|
585
|
+
"href": "#visual-variants",
|
|
586
|
+
"depth": 3,
|
|
587
|
+
"numbering": [
|
|
588
|
+
1,
|
|
589
|
+
3,
|
|
590
|
+
3
|
|
591
|
+
],
|
|
592
|
+
"parent": "root"
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
"value": "Uncontrolled mode",
|
|
596
|
+
"href": "#uncontrolled-mode",
|
|
597
|
+
"depth": 3,
|
|
598
|
+
"numbering": [
|
|
599
|
+
1,
|
|
600
|
+
3,
|
|
601
|
+
4
|
|
602
|
+
],
|
|
603
|
+
"parent": "root"
|
|
604
|
+
},
|
|
605
|
+
{
|
|
606
|
+
"value": "Controlled mode",
|
|
607
|
+
"href": "#controlled-mode",
|
|
608
|
+
"depth": 3,
|
|
609
|
+
"numbering": [
|
|
610
|
+
1,
|
|
611
|
+
3,
|
|
612
|
+
5
|
|
613
|
+
],
|
|
614
|
+
"parent": "root"
|
|
615
|
+
},
|
|
616
|
+
{
|
|
617
|
+
"value": "Option groups",
|
|
618
|
+
"href": "#option-groups",
|
|
619
|
+
"depth": 3,
|
|
620
|
+
"numbering": [
|
|
621
|
+
1,
|
|
622
|
+
3,
|
|
623
|
+
6
|
|
624
|
+
],
|
|
625
|
+
"parent": "root"
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
"value": "Dynamic options with items",
|
|
629
|
+
"href": "#dynamic-options-with-items",
|
|
630
|
+
"depth": 3,
|
|
631
|
+
"numbering": [
|
|
632
|
+
1,
|
|
633
|
+
3,
|
|
634
|
+
7
|
|
635
|
+
],
|
|
636
|
+
"parent": "root"
|
|
637
|
+
},
|
|
638
|
+
{
|
|
639
|
+
"value": "Clearable selection",
|
|
640
|
+
"href": "#clearable-selection",
|
|
641
|
+
"depth": 3,
|
|
642
|
+
"numbering": [
|
|
643
|
+
1,
|
|
644
|
+
3,
|
|
645
|
+
8
|
|
646
|
+
],
|
|
647
|
+
"parent": "root"
|
|
648
|
+
},
|
|
649
|
+
{
|
|
650
|
+
"value": "Leading element",
|
|
651
|
+
"href": "#leading-element",
|
|
652
|
+
"depth": 3,
|
|
653
|
+
"numbering": [
|
|
654
|
+
1,
|
|
655
|
+
3,
|
|
656
|
+
9
|
|
657
|
+
],
|
|
658
|
+
"parent": "root"
|
|
659
|
+
},
|
|
660
|
+
{
|
|
661
|
+
"value": "Component requirements",
|
|
662
|
+
"href": "#component-requirements",
|
|
663
|
+
"depth": 2,
|
|
664
|
+
"numbering": [
|
|
665
|
+
1,
|
|
666
|
+
4
|
|
667
|
+
],
|
|
668
|
+
"parent": "root"
|
|
669
|
+
},
|
|
670
|
+
{
|
|
671
|
+
"value": "Selection value types",
|
|
672
|
+
"href": "#selection-value-types-1",
|
|
673
|
+
"depth": 3,
|
|
674
|
+
"numbering": [
|
|
675
|
+
1,
|
|
676
|
+
4,
|
|
677
|
+
1
|
|
678
|
+
],
|
|
679
|
+
"parent": "root"
|
|
680
|
+
},
|
|
681
|
+
{
|
|
682
|
+
"value": "Accessibility",
|
|
683
|
+
"href": "#accessibility",
|
|
684
|
+
"depth": 2,
|
|
685
|
+
"numbering": [
|
|
686
|
+
1,
|
|
687
|
+
5
|
|
688
|
+
],
|
|
689
|
+
"parent": "root"
|
|
690
|
+
},
|
|
691
|
+
{
|
|
692
|
+
"value": "Keyboard navigation",
|
|
693
|
+
"href": "#keyboard-navigation",
|
|
694
|
+
"depth": 4,
|
|
695
|
+
"numbering": [
|
|
696
|
+
1,
|
|
697
|
+
5,
|
|
698
|
+
1,
|
|
699
|
+
1
|
|
700
|
+
],
|
|
701
|
+
"parent": "root"
|
|
702
|
+
},
|
|
703
|
+
{
|
|
704
|
+
"value": "API reference",
|
|
705
|
+
"href": "#api-reference",
|
|
706
|
+
"depth": 2,
|
|
707
|
+
"numbering": [
|
|
708
|
+
1,
|
|
709
|
+
6
|
|
710
|
+
],
|
|
711
|
+
"parent": "root"
|
|
712
|
+
},
|
|
713
|
+
{
|
|
714
|
+
"value": "Common patterns",
|
|
715
|
+
"href": "#common-patterns",
|
|
716
|
+
"depth": 2,
|
|
717
|
+
"numbering": [
|
|
718
|
+
1,
|
|
719
|
+
7
|
|
720
|
+
],
|
|
721
|
+
"parent": "root"
|
|
722
|
+
},
|
|
723
|
+
{
|
|
724
|
+
"value": "Filtering data by selection",
|
|
725
|
+
"href": "#filtering-data-by-selection",
|
|
726
|
+
"depth": 3,
|
|
727
|
+
"numbering": [
|
|
728
|
+
1,
|
|
729
|
+
7,
|
|
730
|
+
1
|
|
731
|
+
],
|
|
732
|
+
"parent": "root"
|
|
733
|
+
},
|
|
734
|
+
{
|
|
735
|
+
"value": "Country/region selection",
|
|
736
|
+
"href": "#countryregion-selection",
|
|
737
|
+
"depth": 3,
|
|
738
|
+
"numbering": [
|
|
739
|
+
1,
|
|
740
|
+
7,
|
|
741
|
+
2
|
|
742
|
+
],
|
|
743
|
+
"parent": "root"
|
|
744
|
+
},
|
|
745
|
+
{
|
|
746
|
+
"value": "Testing your implementation",
|
|
747
|
+
"href": "#testing-your-implementation",
|
|
748
|
+
"depth": 2,
|
|
749
|
+
"numbering": [
|
|
750
|
+
1,
|
|
751
|
+
8
|
|
752
|
+
],
|
|
753
|
+
"parent": "root"
|
|
754
|
+
},
|
|
755
|
+
{
|
|
756
|
+
"value": "Basic Rendering Tests",
|
|
757
|
+
"href": "#basic-rendering-tests",
|
|
758
|
+
"depth": 3,
|
|
759
|
+
"numbering": [
|
|
760
|
+
1,
|
|
761
|
+
8,
|
|
762
|
+
1
|
|
763
|
+
],
|
|
764
|
+
"parent": "root"
|
|
765
|
+
},
|
|
766
|
+
{
|
|
767
|
+
"value": "Interaction Tests",
|
|
768
|
+
"href": "#interaction-tests",
|
|
769
|
+
"depth": 3,
|
|
770
|
+
"numbering": [
|
|
771
|
+
1,
|
|
772
|
+
8,
|
|
773
|
+
2
|
|
774
|
+
],
|
|
775
|
+
"parent": "root"
|
|
776
|
+
},
|
|
777
|
+
{
|
|
778
|
+
"value": "Controlled State Tests",
|
|
779
|
+
"href": "#controlled-state-tests",
|
|
780
|
+
"depth": 3,
|
|
781
|
+
"numbering": [
|
|
782
|
+
1,
|
|
783
|
+
8,
|
|
784
|
+
3
|
|
785
|
+
],
|
|
786
|
+
"parent": "root"
|
|
787
|
+
},
|
|
788
|
+
{
|
|
789
|
+
"value": "Option Group Tests",
|
|
790
|
+
"href": "#option-group-tests",
|
|
791
|
+
"depth": 3,
|
|
792
|
+
"numbering": [
|
|
793
|
+
1,
|
|
794
|
+
8,
|
|
795
|
+
4
|
|
796
|
+
],
|
|
797
|
+
"parent": "root"
|
|
798
|
+
},
|
|
799
|
+
{
|
|
800
|
+
"value": "Disabled State Tests",
|
|
801
|
+
"href": "#disabled-state-tests",
|
|
802
|
+
"depth": 3,
|
|
803
|
+
"numbering": [
|
|
804
|
+
1,
|
|
805
|
+
8,
|
|
806
|
+
5
|
|
807
|
+
],
|
|
808
|
+
"parent": "root"
|
|
809
|
+
},
|
|
810
|
+
{
|
|
811
|
+
"value": "Invalid State Tests",
|
|
812
|
+
"href": "#invalid-state-tests",
|
|
813
|
+
"depth": 3,
|
|
814
|
+
"numbering": [
|
|
815
|
+
1,
|
|
816
|
+
8,
|
|
817
|
+
6
|
|
818
|
+
],
|
|
819
|
+
"parent": "root"
|
|
820
|
+
},
|
|
821
|
+
{
|
|
822
|
+
"value": "Resources",
|
|
823
|
+
"href": "#resources",
|
|
824
|
+
"depth": 2,
|
|
825
|
+
"numbering": [
|
|
826
|
+
1,
|
|
827
|
+
9
|
|
828
|
+
],
|
|
829
|
+
"parent": "root"
|
|
830
|
+
}
|
|
831
|
+
]
|
|
832
|
+
},
|
|
833
|
+
"guidelines": {
|
|
834
|
+
"mdx": "\n## Guidelines\n\nDesign guidelines offer a set of standardized rules and recommendations that\nensure consistency, usability, and accessibility across all design elements and\ninteractions.\n\n### Best practice\n\n- **Include a label:** Give the users context on what is being asked for when\n making a selection. A picker without a label is ambiguous and not accessible.\n Use \"Select\" or \"Search and select\" as a default placeholder label wording.\n - In rare cases where context is sufficient to not need a label, these\n placements should still be given an aria-label in HTML.\n - **Placeholders:** Should function as a prompt not a value. Do not use a\n placeholder as a label.\n- **Keep contents concise:** Long menu items that wrap to multiple lines should\n be kept to a minimum. If this becomes a frequent concern, consider an\n alternate UI component or pattern to allow for more breathing room for\n content.\n- **Organize content:** The default organization is alphabetical, if a user\n benefits from better organization please improve their experience with better\n categories.\n- **Include help text when needed:** If more information is needed to provide\n context, include helper text below the field for the user. Replace helper text\n with error text if applicable and needed.\n- **Don't neglect ARIA attributes:** If you are building a custom select input,\n ensure that you use proper ARIA attributes to make the select box accessible\n to screen readers.\n\n#### When to use a solid vs. ghost styled select input\n\n| **Type** | **Use this instead** |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Solid-style** | <ul><li>The default option to use in forms.</li><li>Typically the best experience to use with content created by a user.</li><li>When you want to include search for the content.</li></ul> |\n| **Ghost-style** | <ul><li>The default option to use to filter or build rules around content. Ex: filtering assets for the user.</li><li>Best used within rule building experiences such as discounts.</li><li>Ideal to be used in condensed areas, with condensed and familiar options for the user, as in simple filters or quick actions like \"delete\".</li></ul> |\n\n### Usage\n\nSelect inputs are common and users are familiar with their uses. Keeping\nconsistent with the guidelines will help our products intuitive and easy to\nunderstand, even through complicated areas.\n\n### Solid-styled widths\n\nThese placements are more regular, they have either a maximum width of 268px or\nform wide. The popover 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 pull page form) and the popover\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 <Select.Root defaultSelectedKey=\"project-1\" w=\"6400\">\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"project-long\">\n Project with a very long name\n </Select.Option>\n <Select.Option id=\"project-1\">Project 1</Select.Option>\n <Select.Option id=\"abc\">ABC</Select.Option>\n <Select.Option id=\"project-2lines\">\n Project with an even longer name that breaks into 2 lines\n </Select.Option>\n </Select.Options>\n </Select.Root>\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 <Select.Root variant=\"ghost\" defaultSelectedKey=\"project-1\">\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"project-long\">\n Project with a very long name\n </Select.Option>\n <Select.Option id=\"project-1\">Project 1</Select.Option>\n <Select.Option id=\"abc\">ABC</Select.Option>\n <Select.Option id=\"project-2lines\">\n Project with an even longer name that breaks into 2 lines\n </Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n### Ghost-styled widths\n\nThere are a few differences that ghost-styled select inputs have that aren't\nneeded with solid-style placements. Ghost-styled fields should hug width, with\npopovers having a min width matching the field, and max width being 268px unless\non a page wide form.\n\n> [!TIP]\\\n> **Do**\n>\n> - Select input field width set to \"hug\" with max width popover at 268px.\n> - Content flows to next line when needed.\n\n```jsx live\nconst App = () => (\n <Select.Root variant=\"ghost\" defaultSelectedKey=\"project-1\">\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"project-long\">\n Project with a very long name\n </Select.Option>\n <Select.Option id=\"project-1\">Project 1</Select.Option>\n <Select.Option id=\"abc\">ABC</Select.Option>\n <Select.Option id=\"project-2lines\">\n Project with an even longer name that breaks into 2 lines\n </Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n> [!CAUTION]\\\n> **Don't**\n>\n> - This drop down icon looks like it is not related to the select input field.\n> - Do not truncate options that should flow to the next line.\n\n```jsx live\nconst App = () => (\n <Select.Root defaultSelectedKey=\"project-1\" w=\"6400\">\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"project-long\">\n Project with a very long name\n </Select.Option>\n <Select.Option id=\"project-1\">Project 1</Select.Option>\n <Select.Option id=\"abc\">ABC</Select.Option>\n <Select.Option\n id=\"project-2lines\"\n overflow=\"hidden\"\n textOverflow=\"ellipsis\"\n whiteSpace=\"nowrap\"\n >\n Project with an even longer name that breaks into 2 lines\n </Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n> [!TIP]\\\n> **Do**\n>\n> - With short selectable content, match content width to match the select input\n> \"hug\" width.\n\n```jsx live\nconst App = () => (\n <Select.Root variant=\"ghost\" defaultSelectedKey=\"1\">\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"0\">0</Select.Option>\n <Select.Option id=\"1\">1</Select.Option>\n <Select.Option id=\"2\">2</Select.Option>\n <Select.Option id=\"3\">3</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n> [!CAUTION]\\\n> **Don't**\n>\n> - Do not set the popover width to \"hug\", this content should match the width\n> of the field.\n\n```jsx live\nconst App = () => (\n <Select.Root variant=\"ghost\" defaultSelectedKey=\"1\" w=\"6400\">\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"0\">0</Select.Option>\n <Select.Option id=\"1\">1</Select.Option>\n <Select.Option id=\"2\">2</Select.Option>\n <Select.Option id=\"3\">3</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n### Labels and preselection\n\nMake sure to place tooltips in areas where they will be seen easily.\n\n> [!TIP]\\\n> **Do**\n>\n> - Use a short and easily understandable label. Describe, do not use labels as\n> instructions.\n> - Use placeholder if there isn't a most common or default choice.\n\n```jsx live\nconst App = () => (\n <FormField.Root>\n <FormField.Label>Favorite color</FormField.Label>\n <FormField.Input>\n <Select.Root aria-label=\"Favorite color\">\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"red\">Red</Select.Option>\n <Select.Option id=\"blue\">Blue</Select.Option>\n <Select.Option id=\"green\">Green</Select.Option>\n <Select.Option id=\"teal\">Teal</Select.Option>\n </Select.Options>\n </Select.Root>\n </FormField.Input>\n </FormField.Root>\n);\n```\n\n> [!CAUTION]\\\n> **Don't**\n>\n> - Do not rely on placeholders instead of labels.\n> - Do not preselect a random option unless it's genuinely the most common or\n> default choice.\n\n```jsx live\nconst App = () => (\n <Select.Root\n isClearable\n defaultSelectedKey=\"green\"\n aria-label=\"Favorite color\"\n >\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"red\">Red</Select.Option>\n <Select.Option id=\"blue\">Blue</Select.Option>\n <Select.Option id=\"green\">Green</Select.Option>\n <Select.Option id=\"teal\">Teal</Select.Option>\n </Select.Options>\n </Select.Root>\n);\n```\n\n### Labels and layout exceptions\n\nWith the ghost styling for labels, there are some placements that can be used\nwithout labels and have varying widths based on placement. These are most\ncommonly found in filters and with rule builders.\n\n> [!TIP]\\\n> **Do**\n>\n> - Use a short and easily understandable label.\n> - Use placeholder if there isn't a most common or default choice.\n\n```jsx live\nconst App = () => (\n <Flex alignItems=\"center\" gap=\"200\">\n <Text>Color</Text>\n <Text>is</Text>\n <Select.Root variant=\"ghost\" aria-label=\"Color value\">\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"red\">Red</Select.Option>\n <Select.Option id=\"blue\">Blue</Select.Option>\n <Select.Option id=\"green\">Green</Select.Option>\n <Select.Option id=\"teal\">Teal</Select.Option>\n </Select.Options>\n </Select.Root>\n </Flex>\n);\n```\n\n> [!CAUTION]\\\n> **Don't**\n>\n> - Try not to overuse drop downs. Do not make it unclear what parts of a\n> ghost-styled are interactive to the user.\n> - Make sure that if logic is being used that it goes through user testing and\n> is understandable for the targeted user.\n\n```jsx live\nconst App = () => (\n <Stack gap=\"200\">\n <Flex alignItems=\"center\" gap=\"100\" flexWrap=\"wrap\">\n <Text>item's location is</Text>\n <Select.Root\n variant=\"ghost\"\n defaultSelectedKey=\"us\"\n aria-label=\"Location\"\n isClearable={false}\n >\n <Select.Options>\n <Select.Option id=\"us\">United States</Select.Option>\n <Select.Option id=\"uk\">United Kingdom</Select.Option>\n <Select.Option id=\"ca\">Canada</Select.Option>\n </Select.Options>\n </Select.Root>\n <Text>and color</Text>\n <Select.Root\n variant=\"ghost\"\n defaultSelectedKey=\"is-blue\"\n aria-label=\"Color condition\"\n isClearable={false}\n >\n <Select.Options>\n <Select.Option id=\"is-blue\">is blue</Select.Option>\n <Select.Option id=\"is-red\">is red</Select.Option>\n <Select.Option id=\"is-teal\">is teal</Select.Option>\n </Select.Options>\n </Select.Root>\n </Flex>\n <Flex alignItems=\"center\" gap=\"100\" flexWrap=\"wrap\">\n <Text>apply discounts to</Text>\n <Select.Root\n variant=\"ghost\"\n defaultSelectedKey=\"all\"\n aria-label=\"Apply to\"\n isClearable={false}\n >\n <Select.Options>\n <Select.Option id=\"all\">all of matching items</Select.Option>\n <Select.Option id=\"some\">some of matching items</Select.Option>\n </Select.Options>\n </Select.Root>\n </Flex>\n <Flex alignItems=\"center\" gap=\"100\" flexWrap=\"wrap\">\n <Text>except</Text>\n <Select.Root\n variant=\"ghost\"\n defaultSelectedKey=\"if-teal\"\n aria-label=\"Exception\"\n isClearable={false}\n >\n <Select.Options>\n <Select.Option id=\"if-teal\">if item is teal</Select.Option>\n <Select.Option id=\"if-blue\">if item is blue</Select.Option>\n </Select.Options>\n </Select.Root>\n </Flex>\n </Stack>\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 <FormField.Root>\n <FormField.Label>Discount templates</FormField.Label>\n <FormField.Input>\n <Select.Root aria-label=\"Discount templates\">\n <Select.Options placeholder=\"Select...\">\n <Select.OptionGroup label=\"Product discounts\">\n <Select.Option id=\"pct-off-product\">\n Percentage off product\n </Select.Option>\n <Select.Option id=\"amt-off-product\">\n Amount off product\n </Select.Option>\n </Select.OptionGroup>\n <Select.OptionGroup label=\"Cart discounts with line items\">\n <Select.Option id=\"pct-off-cart\">\n Percentage off item(s) on cart\n </Select.Option>\n <Select.Option id=\"amt-off-cart\">\n Amount off item(s) in cart\n </Select.Option>\n <Select.Option id=\"buy-x-get-x\">\n Buy x get x with percentage off\n </Select.Option>\n <Select.Option id=\"fixed-price\">Fixed-price in cart</Select.Option>\n <Select.Option id=\"discounted-shipping\">\n Discounted shipping\n </Select.Option>\n <Select.Option id=\"gift\">Gift with purchase</Select.Option>\n <Select.Option id=\"amt-total-spend\">\n Amount off based on total spend\n </Select.Option>\n <Select.Option id=\"pct-total-spend\">\n Percentage off based on total spend\n </Select.Option>\n </Select.OptionGroup>\n <Select.OptionGroup label=\"Cart discounts with custom line items\">\n <Select.Option id=\"custom-pct\">\n Percentage off item(s) in cart\n </Select.Option>\n <Select.Option id=\"custom-amt\">\n Amount off item(s) in cart\n </Select.Option>\n <Select.Option id=\"custom-buy-x\">\n Buy x get x with percentage off\n </Select.Option>\n </Select.OptionGroup>\n </Select.Options>\n </Select.Root>\n </FormField.Input>\n </FormField.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\n```jsx live\nconst App = () => (\n <FormField.Root>\n <FormField.Label>Discount templates</FormField.Label>\n <FormField.Input>\n <Select.Root aria-label=\"Discount templates\">\n <Select.Options placeholder=\"Select...\">\n <Select.OptionGroup label=\"Product discounts\">\n <Select.Option\n id=\"pct-off-product\"\n textValue=\"Percentage off product\"\n >\n Discount the target item(s) relative to its price.\n <Text slot=\"description\">Discount type: relative</Text>\n </Select.Option>\n <Select.Option id=\"amt-off-product\" textValue=\"Amount off product\">\n Discount the target item(s) by an absolute amount.\n <Text slot=\"description\">Discount type: absolute</Text>\n </Select.Option>\n </Select.OptionGroup>\n <Select.OptionGroup label=\"Cart discounts with line items\">\n <Select.Option id=\"pct-off-cart\" textValue=\"Percentage off cart\">\n Discount the target item(s) relative to its price.\n <Text slot=\"description\">Discount type: relative</Text>\n </Select.Option>\n <Select.Option id=\"amt-off-cart\" textValue=\"Amount off cart\">\n Discount the target item(s) by an absolute amount.\n <Text slot=\"description\">Discount type: absolute</Text>\n </Select.Option>\n <Select.Option id=\"buy-x-get-x\" textValue=\"Buy x get x\">\n A relative (% off) discount is applied when the shopper buys a\n specified quantity of an item.\n <Text slot=\"description\">Discount type: multi-buy</Text>\n </Select.Option>\n <Select.Option id=\"fixed-price\" textValue=\"Fixed price\">\n Discount the target item(s) by setting a fixed price.\n <Text slot=\"description\">Discount type: fixed-price</Text>\n </Select.Option>\n <Select.Option\n id=\"discounted-shipping\"\n textValue=\"Discounted shipping\"\n >\n Discount the cart's shipping cost for the customer.\n <Text slot=\"description\">Discount type: shipping</Text>\n </Select.Option>\n <Select.Option id=\"gift\" textValue=\"Gift with purchase\">\n Discount adds a free line item(s) to the cart when the specified\n conditions are met.\n <Text slot=\"description\">Discount type: gift line item</Text>\n </Select.Option>\n <Select.Option\n id=\"amt-total-spend\"\n textValue=\"Amount off total spend\"\n >\n Discount an absolute amount based on cart total.\n <Text slot=\"description\">Discount type: absolute</Text>\n </Select.Option>\n <Select.Option\n id=\"pct-total-spend\"\n textValue=\"Percentage off total spend\"\n >\n Discount an amount relative to the cart total.\n <Text slot=\"description\">Discount type: relative</Text>\n </Select.Option>\n </Select.OptionGroup>\n <Select.OptionGroup label=\"Cart discounts with custom line items\">\n <Select.Option id=\"custom-pct\" textValue=\"Custom percentage off\">\n Discount the target custom line item(s) relative to its price.\n <Text slot=\"description\">Discount type: relative</Text>\n </Select.Option>\n <Select.Option id=\"custom-amt\" textValue=\"Custom amount off\">\n Discount the target custom line item(s) by an absolute amount.\n <Text slot=\"description\">Discount type: absolute</Text>\n </Select.Option>\n <Select.Option id=\"custom-buy-x\" textValue=\"Custom buy x get x\">\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 slot=\"description\">Discount type: multibuy</Text>\n </Select.Option>\n </Select.OptionGroup>\n </Select.Options>\n </Select.Root>\n </FormField.Input>\n </FormField.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> - Allow if possible for the user to search for items with type ahead fuzzy\n> search.\n> - If actions lists become bulky and hard to scan, consider another experience\n> for the user.\n\n```jsx live\nconst App = () => (\n <FormField.Root>\n <FormField.Label>Actions</FormField.Label>\n <FormField.Input>\n <Select.Root aria-label=\"Actions\">\n <Select.Options placeholder=\"Select...\">\n <Select.OptionGroup label=\"Common actions\">\n <Select.Option id=\"publish\">Publish</Select.Option>\n <Select.Option id=\"unpublish\">Unpublish</Select.Option>\n <Select.Option id=\"delete\">Delete</Select.Option>\n </Select.OptionGroup>\n <Select.OptionGroup label=\"Import\">\n <Select.Option id=\"import-csv\">Import via CSV</Select.Option>\n <Select.Option id=\"bulk-unpublish-csv\">\n Bulk unpublish via CSV\n </Select.Option>\n <Select.Option id=\"bulk-delete-csv\">\n Bulk delete via CSV\n </Select.Option>\n <Select.Option id=\"import-inventories\">\n Import inventories\n </Select.Option>\n </Select.OptionGroup>\n <Select.OptionGroup label=\"Export\">\n <Select.Option id=\"export-products\">Export products</Select.Option>\n <Select.Option id=\"export-inventories\">\n Export Inventories\n </Select.Option>\n </Select.OptionGroup>\n </Select.Options>\n </Select.Root>\n </FormField.Input>\n </FormField.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 <FormField.Root>\n <FormField.Label>Actions</FormField.Label>\n <FormField.Input>\n <Select.Root defaultSelectedKey=\"bulk-unpublish-csv\" aria-label=\"Actions\">\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"bulk-delete-csv\">\n Bulk delete via CSV\n </Select.Option>\n <Select.Option id=\"bulk-unpublish-csv\">\n Bulk unpublish via CSV\n </Select.Option>\n <Select.Option id=\"delete\">Delete</Select.Option>\n <Select.Option id=\"export-inventories\">\n Export Inventories\n </Select.Option>\n <Select.Option id=\"export-products\">Export products</Select.Option>\n <Select.Option id=\"import-inventories\">\n Import inventories\n </Select.Option>\n <Select.Option id=\"import-csv\">Import via CSV</Select.Option>\n <Select.Option id=\"publish\">Publish</Select.Option>\n <Select.Option id=\"unpublish\">Unpublish</Select.Option>\n </Select.Options>\n </Select.Root>\n </FormField.Input>\n </FormField.Root>\n);\n```\n\n### Help and error text inclusion\n\nUse helper text when needed, and replace helper text with error text if\ntriggered.\n\n> [!TIP]\\\n> **Do**\n>\n> - Use helper text to give more context to the select input when needed. Omit\n> if self explanatory.\n> - Error and helper text should be short and easily understood.\n\n```jsx live\nconst App = () => (\n <FormField.Root>\n <FormField.Label>Store restriction</FormField.Label>\n <FormField.Input>\n <Select.Root aria-label=\"Store restriction\">\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"store-1\">Europe store</Select.Option>\n <Select.Option id=\"store-2\">North America store</Select.Option>\n <Select.Option id=\"store-3\">Asia Pacific store</Select.Option>\n </Select.Options>\n </Select.Root>\n </FormField.Input>\n <FormField.Description>\n Restrict this account to only make future purchases to these stores.\n </FormField.Description>\n </FormField.Root>\n);\n```\n\n> [!CAUTION]\\\n> **Don't**\n>\n> - Don't show both helper text and information text simultaneously.\n\n```jsx live\nconst App = () => (\n <FormField.Root isInvalid>\n <FormField.Label>Store restriction</FormField.Label>\n <FormField.Input>\n <Select.Root\n isClearable\n defaultSelectedKey=\"valencia\"\n aria-label=\"Store restriction\"\n >\n <Select.Options placeholder=\"Select...\">\n <Select.Option id=\"valencia\">Valencia, Spain</Select.Option>\n <Select.Option id=\"madrid\">Madrid, Spain</Select.Option>\n <Select.Option id=\"barcelona\">Barcelona, Spain</Select.Option>\n </Select.Options>\n </Select.Root>\n </FormField.Input>\n <FormField.Description>\n Restrict this account to only make future purchases to these stores.\n </FormField.Description>\n <FormField.Error>Cannot perform this action</FormField.Error>\n </FormField.Root>\n);\n```\n",
|
|
835
|
+
"toc": [
|
|
836
|
+
{
|
|
837
|
+
"value": "Guidelines",
|
|
838
|
+
"href": "#guidelines",
|
|
839
|
+
"depth": 2,
|
|
840
|
+
"numbering": [
|
|
841
|
+
1,
|
|
842
|
+
1
|
|
843
|
+
],
|
|
844
|
+
"parent": "root"
|
|
845
|
+
},
|
|
846
|
+
{
|
|
847
|
+
"value": "Best practice",
|
|
848
|
+
"href": "#best-practice",
|
|
849
|
+
"depth": 3,
|
|
850
|
+
"numbering": [
|
|
851
|
+
1,
|
|
852
|
+
1,
|
|
853
|
+
1
|
|
854
|
+
],
|
|
855
|
+
"parent": "root"
|
|
856
|
+
},
|
|
857
|
+
{
|
|
858
|
+
"value": "When to use a solid vs. ghost styled select input",
|
|
859
|
+
"href": "#when-to-use-a-solid-vs-ghost-styled-select-input",
|
|
860
|
+
"depth": 4,
|
|
861
|
+
"numbering": [
|
|
862
|
+
1,
|
|
863
|
+
1,
|
|
864
|
+
1,
|
|
865
|
+
1
|
|
866
|
+
],
|
|
867
|
+
"parent": "root"
|
|
868
|
+
},
|
|
869
|
+
{
|
|
870
|
+
"value": "Usage",
|
|
871
|
+
"href": "#usage",
|
|
872
|
+
"depth": 3,
|
|
873
|
+
"numbering": [
|
|
874
|
+
1,
|
|
875
|
+
1,
|
|
876
|
+
2
|
|
877
|
+
],
|
|
878
|
+
"parent": "root"
|
|
879
|
+
},
|
|
880
|
+
{
|
|
881
|
+
"value": "Solid-styled widths",
|
|
882
|
+
"href": "#solid-styled-widths",
|
|
883
|
+
"depth": 3,
|
|
884
|
+
"numbering": [
|
|
885
|
+
1,
|
|
886
|
+
1,
|
|
887
|
+
3
|
|
888
|
+
],
|
|
889
|
+
"parent": "root"
|
|
890
|
+
},
|
|
891
|
+
{
|
|
892
|
+
"value": "Ghost-styled widths",
|
|
893
|
+
"href": "#ghost-styled-widths",
|
|
894
|
+
"depth": 3,
|
|
895
|
+
"numbering": [
|
|
896
|
+
1,
|
|
897
|
+
1,
|
|
898
|
+
4
|
|
899
|
+
],
|
|
900
|
+
"parent": "root"
|
|
901
|
+
},
|
|
902
|
+
{
|
|
903
|
+
"value": "Labels and preselection",
|
|
904
|
+
"href": "#labels-and-preselection",
|
|
905
|
+
"depth": 3,
|
|
906
|
+
"numbering": [
|
|
907
|
+
1,
|
|
908
|
+
1,
|
|
909
|
+
5
|
|
910
|
+
],
|
|
911
|
+
"parent": "root"
|
|
912
|
+
},
|
|
913
|
+
{
|
|
914
|
+
"value": "Labels and layout exceptions",
|
|
915
|
+
"href": "#labels-and-layout-exceptions",
|
|
916
|
+
"depth": 3,
|
|
917
|
+
"numbering": [
|
|
918
|
+
1,
|
|
919
|
+
1,
|
|
920
|
+
6
|
|
921
|
+
],
|
|
922
|
+
"parent": "root"
|
|
923
|
+
},
|
|
924
|
+
{
|
|
925
|
+
"value": "Keep menu items concise",
|
|
926
|
+
"href": "#keep-menu-items-concise",
|
|
927
|
+
"depth": 3,
|
|
928
|
+
"numbering": [
|
|
929
|
+
1,
|
|
930
|
+
1,
|
|
931
|
+
7
|
|
932
|
+
],
|
|
933
|
+
"parent": "root"
|
|
934
|
+
},
|
|
935
|
+
{
|
|
936
|
+
"value": "Organize dropdown content when possible",
|
|
937
|
+
"href": "#organize-dropdown-content-when-possible",
|
|
938
|
+
"depth": 3,
|
|
939
|
+
"numbering": [
|
|
940
|
+
1,
|
|
941
|
+
1,
|
|
942
|
+
8
|
|
943
|
+
],
|
|
944
|
+
"parent": "root"
|
|
945
|
+
},
|
|
946
|
+
{
|
|
947
|
+
"value": "Help and error text inclusion",
|
|
948
|
+
"href": "#help-and-error-text-inclusion",
|
|
949
|
+
"depth": 3,
|
|
950
|
+
"numbering": [
|
|
951
|
+
1,
|
|
952
|
+
1,
|
|
953
|
+
9
|
|
954
|
+
],
|
|
955
|
+
"parent": "root"
|
|
956
|
+
}
|
|
957
|
+
]
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
}
|