@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,600 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"id": "Components-Drawer",
|
|
4
|
+
"title": "Drawer",
|
|
5
|
+
"exportName": "Drawer",
|
|
6
|
+
"description": "A foundational drawer component for overlays that require user attention and interaction. Built with React Aria Components for accessibility and WCAG 2.1 AA compliance.",
|
|
7
|
+
"lifecycleState": "Stable",
|
|
8
|
+
"order": 999,
|
|
9
|
+
"repoPath": "packages/nimbus/src/components/drawer/drawer.mdx",
|
|
10
|
+
"menu": [
|
|
11
|
+
"Components",
|
|
12
|
+
"Feedback",
|
|
13
|
+
"Drawer"
|
|
14
|
+
],
|
|
15
|
+
"route": "components/feedback/drawer",
|
|
16
|
+
"tags": [
|
|
17
|
+
"component",
|
|
18
|
+
"overlay",
|
|
19
|
+
"dialog",
|
|
20
|
+
"modal",
|
|
21
|
+
"interactive"
|
|
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": "Key features",
|
|
36
|
+
"href": "#key-features",
|
|
37
|
+
"depth": 3,
|
|
38
|
+
"numbering": [
|
|
39
|
+
1,
|
|
40
|
+
1,
|
|
41
|
+
1
|
|
42
|
+
],
|
|
43
|
+
"parent": "root"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"value": "Resources",
|
|
47
|
+
"href": "#resources",
|
|
48
|
+
"depth": 3,
|
|
49
|
+
"numbering": [
|
|
50
|
+
1,
|
|
51
|
+
1,
|
|
52
|
+
2
|
|
53
|
+
],
|
|
54
|
+
"parent": "root"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"value": "Variables",
|
|
58
|
+
"href": "#variables",
|
|
59
|
+
"depth": 2,
|
|
60
|
+
"numbering": [
|
|
61
|
+
1,
|
|
62
|
+
2
|
|
63
|
+
],
|
|
64
|
+
"parent": "root"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"value": "Basic Usage",
|
|
68
|
+
"href": "#basic-usage",
|
|
69
|
+
"depth": 3,
|
|
70
|
+
"numbering": [
|
|
71
|
+
1,
|
|
72
|
+
2,
|
|
73
|
+
1
|
|
74
|
+
],
|
|
75
|
+
"parent": "root"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"value": "Size",
|
|
79
|
+
"href": "#size",
|
|
80
|
+
"depth": 3,
|
|
81
|
+
"numbering": [
|
|
82
|
+
1,
|
|
83
|
+
2,
|
|
84
|
+
2
|
|
85
|
+
],
|
|
86
|
+
"parent": "root"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"value": "Placement Options",
|
|
90
|
+
"href": "#placement-options",
|
|
91
|
+
"depth": 3,
|
|
92
|
+
"numbering": [
|
|
93
|
+
1,
|
|
94
|
+
2,
|
|
95
|
+
3
|
|
96
|
+
],
|
|
97
|
+
"parent": "root"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"value": "Controlled State",
|
|
101
|
+
"href": "#controlled-state",
|
|
102
|
+
"depth": 3,
|
|
103
|
+
"numbering": [
|
|
104
|
+
1,
|
|
105
|
+
2,
|
|
106
|
+
4
|
|
107
|
+
],
|
|
108
|
+
"parent": "root"
|
|
109
|
+
}
|
|
110
|
+
],
|
|
111
|
+
"figmaLink": "https://www.figma.com/design/gHbAJGfcrCv7f2bgzUQgHq/NIMBUS-Guidelines?node-id=1695-45519&m",
|
|
112
|
+
"layout": "app-frame",
|
|
113
|
+
"tabs": [
|
|
114
|
+
{
|
|
115
|
+
"key": "overview",
|
|
116
|
+
"title": "Overview",
|
|
117
|
+
"order": 0
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"key": "guidelines",
|
|
121
|
+
"title": "Guidelines",
|
|
122
|
+
"order": 2
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"key": "dev",
|
|
126
|
+
"title": "Implementation",
|
|
127
|
+
"order": 3
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"key": "a11y",
|
|
131
|
+
"title": "Accessibility",
|
|
132
|
+
"order": 4
|
|
133
|
+
}
|
|
134
|
+
]
|
|
135
|
+
},
|
|
136
|
+
"mdx": "\n## Overview\n\nDrawers are overlay windows that appear on top of the main content to display\nimportant information, gather user input, or require user decisions. They\ntemporarily disable the main interface until the user completes an action or\ndismisses the drawer.\n\n### Key features\n\n- **Accessibility First**: Built with React Aria Components for WCAG 2.1 AA\n compliance\n- **Flexible Positioning**: Support for left, right, top, and bottom placements\n- **Responsive Sizing**: Multiple size variants from xs to full-screen\n- **Smooth Animations**: Customizable motion presets for entrance/exit\n- **Focus Management**: Automatic focus trapping and restoration\n- **Keyboard Navigation**: Full keyboard support including Escape to close\n- **Scroll Handling**: Options for inside or outside scrolling behavior\n\n### Resources\n\nDeep dive into implementation details and access the Nimbus design library.\n\n[React Aria Drawer Docs](https://react-spectrum.adobe.com/react-aria/Drawer.html)\n[ARIA Drawer Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/)\n[Figma Design Library](https://www.figma.com/design/gHbAJGfcrCv7f2bgzUQgHq/NIMBUS-Guidelines?node-id=1695-45519&m)\n\n## Variables\n\nGet familiar with the features.\n\n### Basic Usage\n\n```jsx live\nconst App = () => (\n <Drawer.Root>\n <Drawer.Trigger>Anything can be a trigger</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>Drawer Title</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n This is a basic drawer with default settings. It includes a backdrop\n overlay (enabled by default), title, and close button for a complete\n experience.\n </Drawer.Body>\n <Drawer.Footer>\n <Button variant=\"outline\" slot=\"close\">\n Cancel\n </Button>\n <Button>Save</Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n);\n```\n\n### Size\n\nControl the drawer width by applying `width` prop on the Content component, it's\na regular style-prop, so you can use all size-tokens but also custom values.\n\n```jsx live\nconst App = () => (\n <Drawer.Root>\n <Drawer.Trigger asChild>\n <Button>Open Large Drawer</Button>\n </Drawer.Trigger>\n <Drawer.Content width=\"3xl\">\n <Drawer.Header>\n <Drawer.Title>Large Drawer</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n This drawer uses a custom width. You can change the width by adjusting\n the width prop on Drawer.Root to values like \"xs\", \"sm\", \"md\", \"lg\",\n \"xl\", or \"full\", but also raw css values.\n </Drawer.Body>\n </Drawer.Content>\n </Drawer.Root>\n);\n```\n\n### Placement Options\n\nPosition the drawer at different locations using the `placement` prop. You can\nalso control the backdrop overlay with the `showBackdrop` prop (enabled by\ndefault):\n\n```jsx live\nconst App = () => {\n const [showBackdrop, setShowBackdrop] = useState(true);\n\n const placements = [\n {\n value: \"left\",\n label: \"Left\",\n description:\n \"Slides in from the left side, ideal for navigation panels or filters\",\n },\n {\n value: \"right\",\n label: \"Right (default)\",\n description:\n \"Slides in from the right side, commonly used for details panels and forms\",\n },\n {\n value: \"top\",\n label: \"Top\",\n description: \"Slides in from the top, useful for notifications or alerts\",\n },\n {\n value: \"bottom\",\n label: \"Bottom\",\n description:\n \"Slides in from the bottom, good for mobile-friendly sheets or action panels\",\n },\n ];\n\n return (\n <Stack direction=\"column\" gap=\"400\">\n <Checkbox isSelected={showBackdrop} onChange={setShowBackdrop}>\n Show backdrop\n </Checkbox>\n\n <Stack direction=\"row\" gap=\"400\" wrap=\"wrap\">\n {placements.map((placement) => (\n <Drawer.Root\n key={placement.value}\n placement={placement.value}\n showBackdrop={showBackdrop}\n >\n <Drawer.Trigger asChild>\n <Button>{placement.label}</Button>\n </Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>{placement.label} Placement</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>{placement.description}</Drawer.Body>\n </Drawer.Content>\n </Drawer.Root>\n ))}\n </Stack>\n </Stack>\n );\n};\n```\n\n### Controlled State\n\nUse external state to control the dialog programmatically:\n\n```jsx live\nconst App = () => {\n const [isOpen, setIsOpen] = React.useState(false);\n\n return (\n <Stack>\n <Button alignSelf=\"flex-start\" onPress={() => setIsOpen(true)}>\n Open Controlled Drawer\n </Button>\n\n <Text>Drawer is currently: {isOpen ? \"open\" : \"closed\"}</Text>\n\n <Drawer.Root isOpen={isOpen} onOpenChange={setIsOpen}>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>Controlled Drawer</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n This drawer's state is controlled by the parent component. You can\n open/close it programmatically or through user interaction.\n </Drawer.Body>\n <Drawer.Footer>\n <Button variant=\"outline\" onPress={() => setIsOpen(false)}>\n Cancel\n </Button>\n <Button onPress={() => setIsOpen(false)}>Save</Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n </Stack>\n );\n};\n```\n",
|
|
137
|
+
"views": {
|
|
138
|
+
"overview": {
|
|
139
|
+
"mdx": "\n## Overview\n\nDrawers are overlay windows that appear on top of the main content to display\nimportant information, gather user input, or require user decisions. They\ntemporarily disable the main interface until the user completes an action or\ndismisses the drawer.\n\n### Key features\n\n- **Accessibility First**: Built with React Aria Components for WCAG 2.1 AA\n compliance\n- **Flexible Positioning**: Support for left, right, top, and bottom placements\n- **Responsive Sizing**: Multiple size variants from xs to full-screen\n- **Smooth Animations**: Customizable motion presets for entrance/exit\n- **Focus Management**: Automatic focus trapping and restoration\n- **Keyboard Navigation**: Full keyboard support including Escape to close\n- **Scroll Handling**: Options for inside or outside scrolling behavior\n\n### Resources\n\nDeep dive into implementation details and access the Nimbus design library.\n\n[React Aria Drawer Docs](https://react-spectrum.adobe.com/react-aria/Drawer.html)\n[ARIA Drawer Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/)\n[Figma Design Library](https://www.figma.com/design/gHbAJGfcrCv7f2bgzUQgHq/NIMBUS-Guidelines?node-id=1695-45519&m)\n\n## Variables\n\nGet familiar with the features.\n\n### Basic Usage\n\n```jsx live\nconst App = () => (\n <Drawer.Root>\n <Drawer.Trigger>Anything can be a trigger</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>Drawer Title</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n This is a basic drawer with default settings. It includes a backdrop\n overlay (enabled by default), title, and close button for a complete\n experience.\n </Drawer.Body>\n <Drawer.Footer>\n <Button variant=\"outline\" slot=\"close\">\n Cancel\n </Button>\n <Button>Save</Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n);\n```\n\n### Size\n\nControl the drawer width by applying `width` prop on the Content component, it's\na regular style-prop, so you can use all size-tokens but also custom values.\n\n```jsx live\nconst App = () => (\n <Drawer.Root>\n <Drawer.Trigger asChild>\n <Button>Open Large Drawer</Button>\n </Drawer.Trigger>\n <Drawer.Content width=\"3xl\">\n <Drawer.Header>\n <Drawer.Title>Large Drawer</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n This drawer uses a custom width. You can change the width by adjusting\n the width prop on Drawer.Root to values like \"xs\", \"sm\", \"md\", \"lg\",\n \"xl\", or \"full\", but also raw css values.\n </Drawer.Body>\n </Drawer.Content>\n </Drawer.Root>\n);\n```\n\n### Placement Options\n\nPosition the drawer at different locations using the `placement` prop. You can\nalso control the backdrop overlay with the `showBackdrop` prop (enabled by\ndefault):\n\n```jsx live\nconst App = () => {\n const [showBackdrop, setShowBackdrop] = useState(true);\n\n const placements = [\n {\n value: \"left\",\n label: \"Left\",\n description:\n \"Slides in from the left side, ideal for navigation panels or filters\",\n },\n {\n value: \"right\",\n label: \"Right (default)\",\n description:\n \"Slides in from the right side, commonly used for details panels and forms\",\n },\n {\n value: \"top\",\n label: \"Top\",\n description: \"Slides in from the top, useful for notifications or alerts\",\n },\n {\n value: \"bottom\",\n label: \"Bottom\",\n description:\n \"Slides in from the bottom, good for mobile-friendly sheets or action panels\",\n },\n ];\n\n return (\n <Stack direction=\"column\" gap=\"400\">\n <Checkbox isSelected={showBackdrop} onChange={setShowBackdrop}>\n Show backdrop\n </Checkbox>\n\n <Stack direction=\"row\" gap=\"400\" wrap=\"wrap\">\n {placements.map((placement) => (\n <Drawer.Root\n key={placement.value}\n placement={placement.value}\n showBackdrop={showBackdrop}\n >\n <Drawer.Trigger asChild>\n <Button>{placement.label}</Button>\n </Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>{placement.label} Placement</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>{placement.description}</Drawer.Body>\n </Drawer.Content>\n </Drawer.Root>\n ))}\n </Stack>\n </Stack>\n );\n};\n```\n\n### Controlled State\n\nUse external state to control the dialog programmatically:\n\n```jsx live\nconst App = () => {\n const [isOpen, setIsOpen] = React.useState(false);\n\n return (\n <Stack>\n <Button alignSelf=\"flex-start\" onPress={() => setIsOpen(true)}>\n Open Controlled Drawer\n </Button>\n\n <Text>Drawer is currently: {isOpen ? \"open\" : \"closed\"}</Text>\n\n <Drawer.Root isOpen={isOpen} onOpenChange={setIsOpen}>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>Controlled Drawer</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n This drawer's state is controlled by the parent component. You can\n open/close it programmatically or through user interaction.\n </Drawer.Body>\n <Drawer.Footer>\n <Button variant=\"outline\" onPress={() => setIsOpen(false)}>\n Cancel\n </Button>\n <Button onPress={() => setIsOpen(false)}>Save</Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n </Stack>\n );\n};\n```\n",
|
|
140
|
+
"toc": [
|
|
141
|
+
{
|
|
142
|
+
"value": "Overview",
|
|
143
|
+
"href": "#overview",
|
|
144
|
+
"depth": 2,
|
|
145
|
+
"numbering": [
|
|
146
|
+
1,
|
|
147
|
+
1
|
|
148
|
+
],
|
|
149
|
+
"parent": "root"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"value": "Key features",
|
|
153
|
+
"href": "#key-features",
|
|
154
|
+
"depth": 3,
|
|
155
|
+
"numbering": [
|
|
156
|
+
1,
|
|
157
|
+
1,
|
|
158
|
+
1
|
|
159
|
+
],
|
|
160
|
+
"parent": "root"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"value": "Resources",
|
|
164
|
+
"href": "#resources",
|
|
165
|
+
"depth": 3,
|
|
166
|
+
"numbering": [
|
|
167
|
+
1,
|
|
168
|
+
1,
|
|
169
|
+
2
|
|
170
|
+
],
|
|
171
|
+
"parent": "root"
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"value": "Variables",
|
|
175
|
+
"href": "#variables",
|
|
176
|
+
"depth": 2,
|
|
177
|
+
"numbering": [
|
|
178
|
+
1,
|
|
179
|
+
2
|
|
180
|
+
],
|
|
181
|
+
"parent": "root"
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"value": "Basic Usage",
|
|
185
|
+
"href": "#basic-usage",
|
|
186
|
+
"depth": 3,
|
|
187
|
+
"numbering": [
|
|
188
|
+
1,
|
|
189
|
+
2,
|
|
190
|
+
1
|
|
191
|
+
],
|
|
192
|
+
"parent": "root"
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"value": "Size",
|
|
196
|
+
"href": "#size",
|
|
197
|
+
"depth": 3,
|
|
198
|
+
"numbering": [
|
|
199
|
+
1,
|
|
200
|
+
2,
|
|
201
|
+
2
|
|
202
|
+
],
|
|
203
|
+
"parent": "root"
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"value": "Placement Options",
|
|
207
|
+
"href": "#placement-options",
|
|
208
|
+
"depth": 3,
|
|
209
|
+
"numbering": [
|
|
210
|
+
1,
|
|
211
|
+
2,
|
|
212
|
+
3
|
|
213
|
+
],
|
|
214
|
+
"parent": "root"
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"value": "Controlled State",
|
|
218
|
+
"href": "#controlled-state",
|
|
219
|
+
"depth": 3,
|
|
220
|
+
"numbering": [
|
|
221
|
+
1,
|
|
222
|
+
2,
|
|
223
|
+
4
|
|
224
|
+
],
|
|
225
|
+
"parent": "root"
|
|
226
|
+
}
|
|
227
|
+
]
|
|
228
|
+
},
|
|
229
|
+
"a11y": {
|
|
230
|
+
"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 <Drawer.Root>\n <Drawer.Trigger>\n <Button>Open drawer</Button>\n </Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>Drawer Title</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n This is a basic drawer with default settings. It includes a backdrop overlay\n (enabled by default), title, and close button for a complete experience.\n </Drawer.Body>\n <Drawer.Footer>\n <Button variant=\"outline\" slot=\"close\">Cancel</Button>\n <Button>Save</Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n)\n```\n\n### Accessibility standards\n\n- **Role identification:** Drawer has `dialog` role with proper labeling.\n- **Focus management:** Focus moves to drawer on open and returns to trigger on\n close.\n- **Focus containment:** Tab navigation stays within drawer boundaries.\n- **Accessible names:** Title and description properly associate with drawer.\n- **State announcements:** Screen readers announce when drawer opens/closes.\n- **Info and relationships:** Proper semantic structure with header, body, and\n footer.\n- **Contrast:** All text meets minimum contrast requirements.\n- **Non-text contrast:** Focus indicators and UI components meet contrast\n standards.\n- **Keyboard navigation:** Full keyboard navigation support.\n- **No keyboard trap:** Focus contained but escapable via Escape key.\n- **Focus order:** Logical focus progression through drawer elements.\n- **Focus visible:** Clear focus indicators on all interactive elements.\n- **On focus:** No unexpected context changes when focusing elements.\n- **On input:** Predictable behavior for all user interactions.\n- **Labels or instructions:** Clear labeling and instructions where needed.\n- **Name, role, value:** Proper semantic markup and ARIA attributes.\n- **Status messages:** Appropriate announcements for state changes.\n\n### Resources\n\n- [W3C ARIA Authoring Practices Guide (APG) - Dialog](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/)\n- [WCAG 2.1 Guidelines](https://www.w3.org/WAI/WCAG21/quickref/)\n",
|
|
231
|
+
"toc": [
|
|
232
|
+
{
|
|
233
|
+
"value": "Accessibility",
|
|
234
|
+
"href": "#accessibility",
|
|
235
|
+
"depth": 2,
|
|
236
|
+
"numbering": [
|
|
237
|
+
1,
|
|
238
|
+
1
|
|
239
|
+
],
|
|
240
|
+
"parent": "root"
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"value": "Accessibility standards",
|
|
244
|
+
"href": "#accessibility-standards",
|
|
245
|
+
"depth": 3,
|
|
246
|
+
"numbering": [
|
|
247
|
+
1,
|
|
248
|
+
1,
|
|
249
|
+
1
|
|
250
|
+
],
|
|
251
|
+
"parent": "root"
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
"value": "Resources",
|
|
255
|
+
"href": "#resources",
|
|
256
|
+
"depth": 3,
|
|
257
|
+
"numbering": [
|
|
258
|
+
1,
|
|
259
|
+
1,
|
|
260
|
+
2
|
|
261
|
+
],
|
|
262
|
+
"parent": "root"
|
|
263
|
+
}
|
|
264
|
+
]
|
|
265
|
+
},
|
|
266
|
+
"dev": {
|
|
267
|
+
"mdx": "\n## Getting started\n\n### Import\n\n```tsx\nimport { Drawer } from '@commercetools/nimbus';\n```\n\n### Basic usage\n\nThe Drawer component is a compound component with multiple parts that work together. This basic implementation shows a `Trigger` element that toggles the drawer's `Content` wrapper which contains `Header`, `Body`, and `Footer` sections:\n\n```jsx live-dev\nconst App = () => (\n <Drawer.Root>\n <Drawer.Trigger>Open Drawer</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>Drawer Title</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n <Text>This is the drawer body content.</Text>\n </Drawer.Body>\n <Drawer.Footer>\n <Button variant=\"outline\" slot=\"close\">Cancel</Button>\n <Button variant=\"solid\" slot=\"close\">Confirm</Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n)\n```\n\n## Usage examples\n\n### Placement options\n\nControl where the drawer appears on screen using the `placement` prop on `Drawer.Root`. Available placements are `left`, `right` (default), `top`, and `bottom`:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"row\" gap=\"400\" flexWrap=\"wrap\">\n {['left', 'right', 'top', 'bottom'].map((placement) => (\n <Drawer.Root key={placement} placement={placement}>\n <Drawer.Trigger>{placement}</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>Placement: {placement}</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n <Text>This drawer slides in from the {placement}.</Text>\n </Drawer.Body>\n <Drawer.Footer>\n <Button slot=\"close\">Close</Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n ))}\n </Stack>\n)\n```\n\n**Placement behavior:**\n- `placement=\"left\"`: Slides in from the left edge, full viewport height\n- `placement=\"right\"`: Slides in from the right edge, full viewport height (default)\n- `placement=\"top\"`: Slides in from the top edge, full viewport width\n- `placement=\"bottom\"`: Slides in from the bottom edge, full viewport width\n\n### Backdrop variants\n\nControl whether to show a backdrop overlay behind the drawer using the `showBackdrop` prop (enabled by default):\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"row\" gap=\"400\">\n <Drawer.Root showBackdrop={false}>\n <Drawer.Trigger>No Backdrop</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>No Backdrop</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n <Text>This drawer has no backdrop overlay.</Text>\n </Drawer.Body>\n <Drawer.Footer>\n <Button slot=\"close\">Close</Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n\n <Drawer.Root showBackdrop={true}>\n <Drawer.Trigger>With Backdrop</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>With Backdrop</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n <Text>This drawer has a blurred backdrop overlay.</Text>\n </Drawer.Body>\n <Drawer.Footer>\n <Button slot=\"close\">Close</Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n </Stack>\n)\n```\n\n**Backdrop behavior:**\n- `showBackdrop={true}`: Blurred backdrop overlay with semi-transparent background (default)\n- `showBackdrop={false}`: No backdrop overlay\n\n### Custom trigger with asChild\n\nUse your own button or interactive element as the trigger using the `asChild` prop:\n\n```jsx live-dev\nconst App = () => (\n <Drawer.Root>\n <Drawer.Trigger asChild>\n <Button variant=\"solid\">Custom Button Trigger</Button>\n </Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>Custom Trigger</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n <Text>This drawer was opened with a custom Button component.</Text>\n </Drawer.Body>\n <Drawer.Footer>\n <Button slot=\"close\">Close</Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n)\n```\n\n### Size control\n\nControl the drawer content width using style props on `Drawer.Content`. You can use design tokens or custom values:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"row\" gap=\"400\" flexWrap=\"wrap\">\n {['sm', 'md', 'lg', '512px', 'full'].map((size) => (\n <Drawer.Root key={size}>\n <Drawer.Trigger>{size}</Drawer.Trigger>\n <Drawer.Content width={size}>\n <Drawer.Header>\n <Drawer.Title>Width: {size}</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n <Text>\n This drawer uses <Code>width=\"{size}\"</Code> on Drawer.Content.\n </Text>\n </Drawer.Body>\n <Drawer.Footer>\n <Button slot=\"close\">Close</Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n ))}\n </Stack>\n)\n```\n\n### Scrollable content\n\nThe drawer body automatically handles overflow with scroll support when content exceeds available height:\n\n```jsx live-dev\nconst App = () => (\n <Drawer.Root>\n <Drawer.Trigger>Open Scrollable Drawer</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>Scrollable Content</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n <Stack direction=\"column\" gap=\"400\">\n {Array.from({ length: 20 }, (_, i) => (\n <Text key={i}>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n This is paragraph {i + 1} of scrollable content.\n </Text>\n ))}\n </Stack>\n </Drawer.Body>\n <Drawer.Footer>\n <Button slot=\"close\">Close</Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n)\n```\n\n### Dismissal control\n\nControl how users can dismiss the drawer using `isDismissable` and `isKeyboardDismissDisabled` props:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n <Drawer.Root isDismissable={true} isKeyboardDismissDisabled={false}>\n <Drawer.Trigger>Fully Dismissable</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>Fully Dismissable</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n <Text>Can dismiss by: backdrop click, Escape key, or close button</Text>\n </Drawer.Body>\n <Drawer.Footer>\n <Button slot=\"close\">Close</Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n\n <Drawer.Root isDismissable={false} isKeyboardDismissDisabled={true}>\n <Drawer.Trigger>Modal Drawer</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>Modal Drawer</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n <Text>Can only dismiss using the close button</Text>\n </Drawer.Body>\n <Drawer.Footer>\n <Button slot=\"close\">Close</Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n </Stack>\n)\n```\n\n**Dismissal options:**\n- `isDismissable={true}`: Allow closing by clicking backdrop (default: true)\n- `isKeyboardDismissDisabled={false}`: Allow closing with Escape key (default: false)\n- Both can be combined for fine-grained control\n\n### Intercepting close for unsaved changes\n\nUse `isDismissable={false}` with controlled mode to prevent accidental closing when forms have unsaved changes. Backdrop click is disabled, while Escape key and close buttons still fire `onOpenChange(false)`, allowing close attempts to be intercepted:\n\n```jsx live-dev\nconst App = () => {\n const [isOpen, setIsOpen] = useState(false);\n const [hasUnsavedChanges, setHasUnsavedChanges] = useState(true);\n const [showConfirmation, setShowConfirmation] = useState(false);\n\n const handleOpenChange = (open) => {\n if (open) {\n setIsOpen(true);\n return;\n }\n if (hasUnsavedChanges) {\n setShowConfirmation(true);\n return;\n }\n setIsOpen(false);\n };\n\n return (\n <Stack gap=\"400\">\n <Button onPress={() => setIsOpen(true)}>Open Protected Drawer</Button>\n\n <Drawer.Root\n isOpen={isOpen}\n onOpenChange={handleOpenChange}\n isDismissable={!hasUnsavedChanges}\n placement=\"right\"\n >\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>Edit Form</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n <Stack gap=\"400\">\n <Switch isSelected={hasUnsavedChanges} onChange={setHasUnsavedChanges}>\n Has unsaved changes\n </Switch>\n {showConfirmation && (\n <Stack gap=\"300\" p=\"400\" borderWidth=\"1px\" borderColor=\"border\" borderRadius=\"200\">\n <Text fontWeight=\"semibold\">You have unsaved changes. Discard them?</Text>\n <Stack direction=\"row\" gap=\"300\">\n <Button variant=\"outline\" size=\"xs\" onPress={() => setShowConfirmation(false)}>\n Keep Editing\n </Button>\n <Button variant=\"solid\" size=\"xs\" onPress={() => {\n setShowConfirmation(false);\n setHasUnsavedChanges(false);\n setIsOpen(false);\n }}>\n Discard Changes\n </Button>\n </Stack>\n </Stack>\n )}\n </Stack>\n </Drawer.Body>\n <Drawer.Footer>\n <Button variant=\"outline\" slot=\"close\">Cancel</Button>\n <Button variant=\"solid\" onPress={() => { setHasUnsavedChanges(false); setIsOpen(false); }}>\n Save\n </Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n </Stack>\n );\n}\n```\n\n**Key behavior:**\n- `isDismissable={false}`: Backdrop click is disabled. Escape and close buttons still fire `onOpenChange(false)` which can be intercepted to show a confirmation dialog.\n- Combine with controlled mode (`isOpen` + `onOpenChange`) to intercept close attempts\n- Toggle `isDismissable` dynamically based on form state (e.g. `isDismissable={!hasUnsavedChanges}`)\n\n### Uncontrolled mode\n\nFor simpler use cases, use uncontrolled mode with `defaultOpen` and `onOpenChange`:\n\n```jsx live-dev\nconst App = () => {\n const [lastAction, setLastAction] = useState('No action yet');\n\n return (\n <Stack direction=\"column\" gap=\"400\">\n <Drawer.Root\n defaultOpen={false}\n onOpenChange={(isOpen) => {\n setLastAction(isOpen ? 'Drawer opened' : 'Drawer closed');\n }}\n >\n <Drawer.Trigger>Open Drawer</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>Uncontrolled Drawer</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n <Text>This drawer manages its own open state.</Text>\n </Drawer.Body>\n <Drawer.Footer>\n <Button slot=\"close\">Close</Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n <Text fontSize=\"sm\">Last action: {lastAction}</Text>\n </Stack>\n );\n}\n```\n\nUse uncontrolled mode when you only need to react to state changes without managing the state yourself.\n\n### Controlled mode\n\nFor scenarios requiring programmatic control or coordination with other components, use controlled mode:\n\n```jsx live-dev\nconst App = () => {\n const [isOpen, setIsOpen] = useState(false);\n\n return (\n <Stack direction=\"column\" gap=\"400\">\n <Switch isSelected={isOpen} onChange={setIsOpen}>\n Drawer is {isOpen ? 'open' : 'closed'}\n </Switch>\n <Drawer.Root isOpen={isOpen} onOpenChange={setIsOpen}>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>Controlled Drawer</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n <Text>This drawer's state is controlled externally via the Switch.</Text>\n </Drawer.Body>\n <Drawer.Footer>\n <Button slot=\"close\">Close</Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n </Stack>\n );\n}\n```\n\nUse controlled mode when you need to:\n- Synchronize the drawer state with external state\n- Open/close the drawer programmatically\n- Coordinate the drawer with other UI elements\n\n## Component requirements\n\n## Accessibility\n\nThe Drawer component handles most accessibility requirements internally through React Aria Components. However, you must provide an accessible label for the drawer using one of these approaches:\n\n- **Using Drawer.Title** (recommended):\n```tsx\n<Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>Drawer Title</Drawer.Title>\n </Drawer.Header>\n <Drawer.Body>...</Drawer.Body>\n</Drawer.Content>\n```\n\n- **Using aria-label** (when no visual title is needed):\n```tsx\n<Drawer.Root aria-label={msg.format(drawerMessage)}>\n <Drawer.Trigger>Open</Drawer.Trigger>\n <Drawer.Content>...</Drawer.Content>\n</Drawer.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-drawer\";\n\nexport const Example = () => (\n <Drawer.Root id={PERSISTENT_ID}>\n <Drawer.Trigger>Open</Drawer.Trigger>\n <Drawer.Content>...</Drawer.Content>\n </Drawer.Root>\n);\n```\n\n#### Keyboard navigation\n\nThe component supports full keyboard interaction:\n- `Tab` / `Shift+Tab`: Navigate between focusable elements inside the drawer\n- `Escape`: Close the drawer (unless `isKeyboardDismissDisabled` is true)\n- Focus is automatically trapped within the drawer when open\n- Focus is restored to the trigger element when the drawer closes\n\n#### ARIA attributes\n\n- `role=\"dialog\"`: Applied to the drawer content\n- `aria-label` or `aria-labelledby`: Associates the drawer with its title\n- `aria-modal=\"true\"`: Indicates the drawer is modal (blocks interaction with background)\n\n## API reference\n\n<PropsTable id=\"Drawer\" />\n\n## Common patterns\n\n### Nested drawers\n\nDrawers can be nested to create multi-level workflows. Each drawer maintains proper z-index stacking:\n\n```jsx live-dev\nconst App = () => (\n <Drawer.Root>\n <Drawer.Trigger>Open First Drawer</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>First Level</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n <Stack direction=\"column\" gap=\"400\">\n <Text>This is the first level drawer.</Text>\n <Drawer.Root>\n <Drawer.Trigger asChild>\n <Button size=\"xs\">Open Second Drawer</Button>\n </Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>Second Level</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n <Text>This nested drawer appears above the first with proper z-index.</Text>\n </Drawer.Body>\n <Drawer.Footer>\n <Button slot=\"close\">Close Second</Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n </Stack>\n </Drawer.Body>\n <Drawer.Footer>\n <Button slot=\"close\">Close First</Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n)\n```\n\n### Conditional dismissal with shouldCloseOnInteractOutside\n\nControl whether the drawer should close when clicking outside based on custom logic:\n\n```jsx live-dev\nconst App = () => {\n const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);\n\n return (\n <Drawer.Root\n shouldCloseOnInteractOutside={() => {\n if (hasUnsavedChanges) {\n alert('You have unsaved changes!');\n return false;\n }\n return true;\n }}\n >\n <Drawer.Trigger>Open Editor</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>Document Editor</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>\n <Stack direction=\"column\" gap=\"400\">\n <Text>Make changes to simulate unsaved data:</Text>\n <Switch\n isSelected={hasUnsavedChanges}\n onChange={setHasUnsavedChanges}\n >\n Has unsaved changes\n </Switch>\n <Text fontSize=\"sm\" color=\"neutral.11\">\n Try clicking outside when changes are unsaved\n </Text>\n </Stack>\n </Drawer.Body>\n <Drawer.Footer>\n <Button variant=\"outline\" slot=\"close\">Cancel</Button>\n <Button\n variant=\"solid\"\n slot=\"close\"\n onClick={() => setHasUnsavedChanges(false)}\n >\n Save\n </Button>\n </Drawer.Footer>\n </Drawer.Content>\n </Drawer.Root>\n );\n}\n```\n\n## Testing your implementation\n\nThese examples demonstrate how to test your implementation when using Drawer in 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 drawer 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 { Drawer, Button, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Drawer - Basic rendering\", () => {\n it(\"renders trigger button\", () => {\n render(\n <NimbusProvider>\n <Drawer.Root>\n <Drawer.Trigger>Open Drawer</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Body>Content</Drawer.Body>\n </Drawer.Content>\n </Drawer.Root>\n </NimbusProvider>\n );\n\n expect(\n screen.getByRole(\"button\", { name: \"Open Drawer\" })\n ).toBeInTheDocument();\n });\n\n it(\"does not render dialog when closed\", () => {\n render(\n <NimbusProvider>\n <Drawer.Root>\n <Drawer.Trigger>Open</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Body>Content</Drawer.Body>\n </Drawer.Content>\n </Drawer.Root>\n </NimbusProvider>\n );\n\n expect(screen.queryByRole(\"dialog\")).not.toBeInTheDocument();\n });\n});\n```\n\n### Interaction Tests\n\nTest drawer opening and closing behavior\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, waitFor } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { useState } from \"react\";\nimport { Drawer, Button, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Drawer - Interactions\", () => {\n it(\"opens drawer when trigger is clicked\", async () => {\n const user = userEvent.setup();\n render(\n <NimbusProvider>\n <Drawer.Root>\n <Drawer.Trigger>Open Drawer</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>Test Drawer</Drawer.Title>\n </Drawer.Header>\n <Drawer.Body>Content</Drawer.Body>\n </Drawer.Content>\n </Drawer.Root>\n </NimbusProvider>\n );\n\n const trigger = screen.getByRole(\"button\", { name: \"Open Drawer\" });\n await user.click(trigger);\n\n await waitFor(() => {\n expect(screen.getByRole(\"dialog\")).toBeInTheDocument();\n expect(\n screen.getByRole(\"heading\", { name: \"Test Drawer\" })\n ).toBeInTheDocument();\n });\n });\n\n it(\"closes drawer when close button is clicked\", async () => {\n const user = userEvent.setup();\n render(\n <NimbusProvider>\n <Drawer.Root>\n <Drawer.Trigger>Open</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Header>\n <Drawer.Title>Test</Drawer.Title>\n <Drawer.CloseTrigger />\n </Drawer.Header>\n <Drawer.Body>Content</Drawer.Body>\n </Drawer.Content>\n </Drawer.Root>\n </NimbusProvider>\n );\n\n await user.click(screen.getByRole(\"button\", { name: \"Open\" }));\n await waitFor(() => {\n expect(screen.getByRole(\"dialog\")).toBeInTheDocument();\n });\n\n const closeButton = screen.getByRole(\"button\", { name: /close/i });\n await user.click(closeButton);\n\n await waitFor(() => {\n expect(screen.queryByRole(\"dialog\")).not.toBeInTheDocument();\n });\n });\n\n it(\"closes drawer when Escape key is pressed\", async () => {\n const user = userEvent.setup();\n render(\n <NimbusProvider>\n <Drawer.Root>\n <Drawer.Trigger>Open</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Body>Content</Drawer.Body>\n </Drawer.Content>\n </Drawer.Root>\n </NimbusProvider>\n );\n\n await user.click(screen.getByRole(\"button\", { name: \"Open\" }));\n await waitFor(() => {\n expect(screen.getByRole(\"dialog\")).toBeInTheDocument();\n });\n\n await user.keyboard(\"{Escape}\");\n\n await waitFor(() => {\n expect(screen.queryByRole(\"dialog\")).not.toBeInTheDocument();\n });\n });\n});\n```\n\n### Controlled State Tests\n\nTest controlled mode behavior\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, waitFor } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { useState } from \"react\";\nimport { Drawer, Button, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Drawer - Controlled state\", () => {\n it(\"opens and closes via controlled prop\", async () => {\n const user = userEvent.setup();\n\n const ControlledDrawer = () => {\n const [isOpen, setIsOpen] = useState(false);\n\n return (\n <NimbusProvider>\n <Button onPress={() => setIsOpen(true)}>External Open</Button>\n <Drawer.Root isOpen={isOpen} onOpenChange={setIsOpen}>\n <Drawer.Content aria-label=\"Controlled drawer\">\n <Drawer.Body>Content</Drawer.Body>\n </Drawer.Content>\n </Drawer.Root>\n </NimbusProvider>\n );\n };\n\n render(<ControlledDrawer />);\n\n expect(screen.queryByRole(\"dialog\")).not.toBeInTheDocument();\n\n await user.click(screen.getByRole(\"button\", { name: \"External Open\" }));\n\n await waitFor(() => {\n expect(screen.getByRole(\"dialog\")).toBeInTheDocument();\n });\n });\n\n it(\"calls onOpenChange when drawer state changes\", async () => {\n const user = userEvent.setup();\n const handleOpenChange = vi.fn();\n\n render(\n <NimbusProvider>\n <Drawer.Root onOpenChange={handleOpenChange}>\n <Drawer.Trigger>Open</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Body>Content</Drawer.Body>\n </Drawer.Content>\n </Drawer.Root>\n </NimbusProvider>\n );\n\n await user.click(screen.getByRole(\"button\", { name: \"Open\" }));\n\n await waitFor(() => {\n expect(handleOpenChange).toHaveBeenCalledWith(true);\n });\n\n await user.keyboard(\"{Escape}\");\n\n await waitFor(() => {\n expect(handleOpenChange).toHaveBeenCalledWith(false);\n });\n });\n});\n```\n\n### Portal Content Tests\n\nTest drawer content rendering in portal\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 { Drawer, Button, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Drawer - Portal content\", () => {\n it(\"renders drawer content in portal\", async () => {\n const user = userEvent.setup();\n render(\n <NimbusProvider>\n <Drawer.Root>\n <Drawer.Trigger>Open</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Body>\n <div data-testid=\"portal-content\">Portal Content</div>\n </Drawer.Body>\n </Drawer.Content>\n </Drawer.Root>\n </NimbusProvider>\n );\n\n await user.click(screen.getByRole(\"button\", { name: \"Open\" }));\n\n await waitFor(() => {\n const dialog = screen.getByRole(\"dialog\");\n expect(dialog).toBeInTheDocument();\n expect(screen.getByTestId(\"portal-content\")).toBeInTheDocument();\n });\n });\n});\n```\n\n### Dismissal Behavior Tests\n\nTest different dismissal configurations\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 { Drawer, Button, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Drawer - Dismissal\", () => {\n it(\"prevents Escape key dismissal when isKeyboardDismissDisabled\", async () => {\n const user = userEvent.setup();\n render(\n <NimbusProvider>\n <Drawer.Root isKeyboardDismissDisabled={true}>\n <Drawer.Trigger>Open</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Body>Content</Drawer.Body>\n </Drawer.Content>\n </Drawer.Root>\n </NimbusProvider>\n );\n\n await user.click(screen.getByRole(\"button\", { name: \"Open\" }));\n await waitFor(() => {\n expect(screen.getByRole(\"dialog\")).toBeInTheDocument();\n });\n\n await user.keyboard(\"{Escape}\");\n\n // Drawer should still be open\n expect(screen.getByRole(\"dialog\")).toBeInTheDocument();\n });\n\n it(\"accepts shouldCloseOnInteractOutside callback prop\", () => {\n const shouldClose = vi.fn(() => false);\n\n render(\n <NimbusProvider>\n <Drawer.Root shouldCloseOnInteractOutside={shouldClose}>\n <Drawer.Trigger>Open</Drawer.Trigger>\n <Drawer.Content>\n <Drawer.Body>Content</Drawer.Body>\n </Drawer.Content>\n </Drawer.Root>\n </NimbusProvider>\n );\n\n // Verify component renders with the callback prop without errors\n expect(screen.getByRole(\"button\", { name: \"Open\" })).toBeInTheDocument();\n });\n});\n```\n\n\n## Resources\n\n- [Storybook](https://nimbus-storybook.vercel.app/?path=/docs/components-overlay-drawer--docs)\n- [React Aria DialogTrigger](https://react-spectrum.adobe.com/react-aria/Dialog.html#dialogtrigger)\n- [React Aria Modal](https://react-spectrum.adobe.com/react-aria/Modal.html)\n- [ARIA Dialog Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/)\n",
|
|
268
|
+
"toc": [
|
|
269
|
+
{
|
|
270
|
+
"value": "Getting started",
|
|
271
|
+
"href": "#getting-started",
|
|
272
|
+
"depth": 2,
|
|
273
|
+
"numbering": [
|
|
274
|
+
1,
|
|
275
|
+
1
|
|
276
|
+
],
|
|
277
|
+
"parent": "root"
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"value": "Import",
|
|
281
|
+
"href": "#import",
|
|
282
|
+
"depth": 3,
|
|
283
|
+
"numbering": [
|
|
284
|
+
1,
|
|
285
|
+
1,
|
|
286
|
+
1
|
|
287
|
+
],
|
|
288
|
+
"parent": "root"
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
"value": "Basic usage",
|
|
292
|
+
"href": "#basic-usage",
|
|
293
|
+
"depth": 3,
|
|
294
|
+
"numbering": [
|
|
295
|
+
1,
|
|
296
|
+
1,
|
|
297
|
+
2
|
|
298
|
+
],
|
|
299
|
+
"parent": "root"
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
"value": "Usage examples",
|
|
303
|
+
"href": "#usage-examples",
|
|
304
|
+
"depth": 2,
|
|
305
|
+
"numbering": [
|
|
306
|
+
1,
|
|
307
|
+
2
|
|
308
|
+
],
|
|
309
|
+
"parent": "root"
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
"value": "Placement options",
|
|
313
|
+
"href": "#placement-options",
|
|
314
|
+
"depth": 3,
|
|
315
|
+
"numbering": [
|
|
316
|
+
1,
|
|
317
|
+
2,
|
|
318
|
+
1
|
|
319
|
+
],
|
|
320
|
+
"parent": "root"
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
"value": "Backdrop variants",
|
|
324
|
+
"href": "#backdrop-variants",
|
|
325
|
+
"depth": 3,
|
|
326
|
+
"numbering": [
|
|
327
|
+
1,
|
|
328
|
+
2,
|
|
329
|
+
2
|
|
330
|
+
],
|
|
331
|
+
"parent": "root"
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
"value": "Custom trigger with asChild",
|
|
335
|
+
"href": "#custom-trigger-with-aschild",
|
|
336
|
+
"depth": 3,
|
|
337
|
+
"numbering": [
|
|
338
|
+
1,
|
|
339
|
+
2,
|
|
340
|
+
3
|
|
341
|
+
],
|
|
342
|
+
"parent": "root"
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
"value": "Size control",
|
|
346
|
+
"href": "#size-control",
|
|
347
|
+
"depth": 3,
|
|
348
|
+
"numbering": [
|
|
349
|
+
1,
|
|
350
|
+
2,
|
|
351
|
+
4
|
|
352
|
+
],
|
|
353
|
+
"parent": "root"
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
"value": "Scrollable content",
|
|
357
|
+
"href": "#scrollable-content",
|
|
358
|
+
"depth": 3,
|
|
359
|
+
"numbering": [
|
|
360
|
+
1,
|
|
361
|
+
2,
|
|
362
|
+
5
|
|
363
|
+
],
|
|
364
|
+
"parent": "root"
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
"value": "Dismissal control",
|
|
368
|
+
"href": "#dismissal-control",
|
|
369
|
+
"depth": 3,
|
|
370
|
+
"numbering": [
|
|
371
|
+
1,
|
|
372
|
+
2,
|
|
373
|
+
6
|
|
374
|
+
],
|
|
375
|
+
"parent": "root"
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
"value": "Intercepting close for unsaved changes",
|
|
379
|
+
"href": "#intercepting-close-for-unsaved-changes",
|
|
380
|
+
"depth": 3,
|
|
381
|
+
"numbering": [
|
|
382
|
+
1,
|
|
383
|
+
2,
|
|
384
|
+
7
|
|
385
|
+
],
|
|
386
|
+
"parent": "root"
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
"value": "Uncontrolled mode",
|
|
390
|
+
"href": "#uncontrolled-mode",
|
|
391
|
+
"depth": 3,
|
|
392
|
+
"numbering": [
|
|
393
|
+
1,
|
|
394
|
+
2,
|
|
395
|
+
8
|
|
396
|
+
],
|
|
397
|
+
"parent": "root"
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
"value": "Controlled mode",
|
|
401
|
+
"href": "#controlled-mode",
|
|
402
|
+
"depth": 3,
|
|
403
|
+
"numbering": [
|
|
404
|
+
1,
|
|
405
|
+
2,
|
|
406
|
+
9
|
|
407
|
+
],
|
|
408
|
+
"parent": "root"
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
"value": "Component requirements",
|
|
412
|
+
"href": "#component-requirements",
|
|
413
|
+
"depth": 2,
|
|
414
|
+
"numbering": [
|
|
415
|
+
1,
|
|
416
|
+
3
|
|
417
|
+
],
|
|
418
|
+
"parent": "root"
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
"value": "Accessibility",
|
|
422
|
+
"href": "#accessibility",
|
|
423
|
+
"depth": 2,
|
|
424
|
+
"numbering": [
|
|
425
|
+
1,
|
|
426
|
+
4
|
|
427
|
+
],
|
|
428
|
+
"parent": "root"
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
"value": "Keyboard navigation",
|
|
432
|
+
"href": "#keyboard-navigation",
|
|
433
|
+
"depth": 4,
|
|
434
|
+
"numbering": [
|
|
435
|
+
1,
|
|
436
|
+
4,
|
|
437
|
+
1,
|
|
438
|
+
1
|
|
439
|
+
],
|
|
440
|
+
"parent": "root"
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
"value": "ARIA attributes",
|
|
444
|
+
"href": "#aria-attributes",
|
|
445
|
+
"depth": 4,
|
|
446
|
+
"numbering": [
|
|
447
|
+
1,
|
|
448
|
+
4,
|
|
449
|
+
1,
|
|
450
|
+
2
|
|
451
|
+
],
|
|
452
|
+
"parent": "root"
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
"value": "API reference",
|
|
456
|
+
"href": "#api-reference",
|
|
457
|
+
"depth": 2,
|
|
458
|
+
"numbering": [
|
|
459
|
+
1,
|
|
460
|
+
5
|
|
461
|
+
],
|
|
462
|
+
"parent": "root"
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
"value": "Common patterns",
|
|
466
|
+
"href": "#common-patterns",
|
|
467
|
+
"depth": 2,
|
|
468
|
+
"numbering": [
|
|
469
|
+
1,
|
|
470
|
+
6
|
|
471
|
+
],
|
|
472
|
+
"parent": "root"
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
"value": "Nested drawers",
|
|
476
|
+
"href": "#nested-drawers",
|
|
477
|
+
"depth": 3,
|
|
478
|
+
"numbering": [
|
|
479
|
+
1,
|
|
480
|
+
6,
|
|
481
|
+
1
|
|
482
|
+
],
|
|
483
|
+
"parent": "root"
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
"value": "Conditional dismissal with shouldCloseOnInteractOutside",
|
|
487
|
+
"href": "#conditional-dismissal-with-shouldcloseoninteractoutside",
|
|
488
|
+
"depth": 3,
|
|
489
|
+
"numbering": [
|
|
490
|
+
1,
|
|
491
|
+
6,
|
|
492
|
+
2
|
|
493
|
+
],
|
|
494
|
+
"parent": "root"
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
"value": "Testing your implementation",
|
|
498
|
+
"href": "#testing-your-implementation",
|
|
499
|
+
"depth": 2,
|
|
500
|
+
"numbering": [
|
|
501
|
+
1,
|
|
502
|
+
7
|
|
503
|
+
],
|
|
504
|
+
"parent": "root"
|
|
505
|
+
},
|
|
506
|
+
{
|
|
507
|
+
"value": "Basic Rendering Tests",
|
|
508
|
+
"href": "#basic-rendering-tests",
|
|
509
|
+
"depth": 3,
|
|
510
|
+
"numbering": [
|
|
511
|
+
1,
|
|
512
|
+
7,
|
|
513
|
+
1
|
|
514
|
+
],
|
|
515
|
+
"parent": "root"
|
|
516
|
+
},
|
|
517
|
+
{
|
|
518
|
+
"value": "Interaction Tests",
|
|
519
|
+
"href": "#interaction-tests",
|
|
520
|
+
"depth": 3,
|
|
521
|
+
"numbering": [
|
|
522
|
+
1,
|
|
523
|
+
7,
|
|
524
|
+
2
|
|
525
|
+
],
|
|
526
|
+
"parent": "root"
|
|
527
|
+
},
|
|
528
|
+
{
|
|
529
|
+
"value": "Controlled State Tests",
|
|
530
|
+
"href": "#controlled-state-tests",
|
|
531
|
+
"depth": 3,
|
|
532
|
+
"numbering": [
|
|
533
|
+
1,
|
|
534
|
+
7,
|
|
535
|
+
3
|
|
536
|
+
],
|
|
537
|
+
"parent": "root"
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
"value": "Portal Content Tests",
|
|
541
|
+
"href": "#portal-content-tests",
|
|
542
|
+
"depth": 3,
|
|
543
|
+
"numbering": [
|
|
544
|
+
1,
|
|
545
|
+
7,
|
|
546
|
+
4
|
|
547
|
+
],
|
|
548
|
+
"parent": "root"
|
|
549
|
+
},
|
|
550
|
+
{
|
|
551
|
+
"value": "Dismissal Behavior Tests",
|
|
552
|
+
"href": "#dismissal-behavior-tests",
|
|
553
|
+
"depth": 3,
|
|
554
|
+
"numbering": [
|
|
555
|
+
1,
|
|
556
|
+
7,
|
|
557
|
+
5
|
|
558
|
+
],
|
|
559
|
+
"parent": "root"
|
|
560
|
+
},
|
|
561
|
+
{
|
|
562
|
+
"value": "Resources",
|
|
563
|
+
"href": "#resources",
|
|
564
|
+
"depth": 2,
|
|
565
|
+
"numbering": [
|
|
566
|
+
1,
|
|
567
|
+
8
|
|
568
|
+
],
|
|
569
|
+
"parent": "root"
|
|
570
|
+
}
|
|
571
|
+
]
|
|
572
|
+
},
|
|
573
|
+
"guidelines": {
|
|
574
|
+
"mdx": "\n## Guidelines\n\nUse drawers strategically to enhance user workflow without disrupting the\nexperience.\n\n### Best practices\n\n- **Use drawers sparingly**: Only when you need to interrupt the user's flow for\n critical actions\n- **Keep content focused**: Drawers should have a single, clear purpose\n- **Provide clear actions**: Always include obvious ways to proceed or dismiss\n- **Make dismissal easy**: Support Escape key, close buttons, and click-outside\n behavior. For forms with unsaved changes, use `isDismissable={false}` with\n controlled mode to intercept close attempts and show a confirmation before\n discarding data\n- **Maintain focus flow**: Focus should move logically through interactive\n elements\n- **Size appropriately**: Choose sizes that fit your content without\n overwhelming the viewport. For complex full-page editing workflows, use the\n ModalPage component instead\n- **Consider mobile**: Ensure drawers work well on small screens\n\n> [!TIP]\\\n> When to use\n\n- **Confirming destructive actions**: Delete confirmations and critical warnings\n- **Collecting focused input**: Forms, settings, and data entry that requires\n attention\n- **Displaying critical alerts**: Important information that requires immediate\n user attention\n- **Showing detailed information**: Content that doesn't require navigation to a\n new page\n- **Authentication flows**: Login, signup, and security-related interactions\n\n> [!CAUTION]\\\n> When not to use\n\n- **Complex multi-step workflows**: Use pages instead for lengthy processes\n- **Non-critical information**: Use inline content for supplementary information\n- **Navigation**: Use proper routing instead of drawers for moving between\n sections\n- **Content that needs to be referenced**: Avoid for information users need\n while working elsewhere\n",
|
|
575
|
+
"toc": [
|
|
576
|
+
{
|
|
577
|
+
"value": "Guidelines",
|
|
578
|
+
"href": "#guidelines",
|
|
579
|
+
"depth": 2,
|
|
580
|
+
"numbering": [
|
|
581
|
+
1,
|
|
582
|
+
1
|
|
583
|
+
],
|
|
584
|
+
"parent": "root"
|
|
585
|
+
},
|
|
586
|
+
{
|
|
587
|
+
"value": "Best practices",
|
|
588
|
+
"href": "#best-practices",
|
|
589
|
+
"depth": 3,
|
|
590
|
+
"numbering": [
|
|
591
|
+
1,
|
|
592
|
+
1,
|
|
593
|
+
1
|
|
594
|
+
],
|
|
595
|
+
"parent": "root"
|
|
596
|
+
}
|
|
597
|
+
]
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|