@astryxdesign/core 0.1.1 → 0.1.2-canary.04e71b2
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/CHANGELOG.md +105 -0
- package/README.md +131 -13
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +11 -5
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +4 -1
- package/dist/Banner/Banner.d.ts +7 -0
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +9 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +24 -5
- package/dist/Button/Button.d.ts +12 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +53 -17
- package/dist/Calendar/Calendar.d.ts +5 -4
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +82 -43
- package/dist/Calendar/hooks/index.d.ts +0 -2
- package/dist/Calendar/hooks/index.d.ts.map +1 -1
- package/dist/Calendar/hooks/index.js +1 -2
- package/dist/Calendar/index.d.ts +3 -3
- package/dist/Calendar/index.d.ts.map +1 -1
- package/dist/Calendar/index.js +1 -1
- package/dist/Calendar/styles.d.ts +3 -9
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +3 -11
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +17 -3
- package/dist/Center/Center.d.ts +11 -1
- package/dist/Center/Center.d.ts.map +1 -1
- package/dist/Center/Center.js +9 -3
- package/dist/Chat/ChatMessageList.d.ts +14 -1
- package/dist/Chat/ChatMessageList.d.ts.map +1 -1
- package/dist/Chat/ChatMessageList.js +2 -0
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +4 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts +23 -2
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +51 -9
- package/dist/CheckboxList/CheckboxList.d.ts +13 -1
- package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxList.js +39 -9
- package/dist/CheckboxList/CheckboxListContext.d.ts +7 -0
- package/dist/CheckboxList/CheckboxListContext.d.ts.map +1 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +3 -3
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +49 -37
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +5 -5
- package/dist/ContextMenu/ContextMenu.d.ts +4 -5
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +93 -11
- package/dist/DateInput/DateInput.d.ts +23 -1
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +59 -8
- package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +42 -9
- package/dist/DateTimeInput/DateTimeInput.d.ts +35 -2
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +78 -15
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +12 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts +1 -8
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +42 -14
- package/dist/EmptyState/EmptyState.d.ts.map +1 -1
- package/dist/EmptyState/EmptyState.js +7 -1
- package/dist/Field/Field.d.ts +19 -2
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +4 -0
- package/dist/Field/FieldLabel.d.ts +21 -2
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +41 -26
- package/dist/FileInput/FileInput.d.ts +22 -1
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +56 -10
- package/dist/Grid/Grid.d.ts +11 -1
- package/dist/Grid/Grid.d.ts.map +1 -1
- package/dist/Grid/Grid.js +8 -0
- package/dist/HoverCard/HoverCard.d.ts +2 -2
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +18 -6
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +7 -3
- package/dist/InputGroup/InputGroup.d.ts +2 -2
- package/dist/InputGroup/InputGroup.d.ts.map +1 -1
- package/dist/InputGroup/InputGroup.js +14 -5
- package/dist/InputGroup/InputGroupContext.d.ts +4 -0
- package/dist/InputGroup/InputGroupContext.d.ts.map +1 -1
- package/dist/InputGroup/InputGroupContext.js +2 -2
- package/dist/InputGroup/index.d.ts +1 -0
- package/dist/InputGroup/index.d.ts.map +1 -1
- package/dist/Kbd/Kbd.d.ts.map +1 -1
- package/dist/Kbd/Kbd.js +34 -2
- package/dist/Layer/anchorName.d.ts +20 -0
- package/dist/Layer/anchorName.d.ts.map +1 -0
- package/dist/Layer/anchorName.js +36 -0
- package/dist/Layer/layerAnimations.stylex.d.ts +4 -0
- package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
- package/dist/Layer/layerAnimations.stylex.js +8 -4
- package/dist/Layer/useLayer.d.ts +29 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +55 -11
- package/dist/Layout/Layout.d.ts +4 -11
- package/dist/Layout/Layout.d.ts.map +1 -1
- package/dist/Layout/Layout.js +10 -11
- package/dist/Layout/LayoutFooter.d.ts +2 -2
- package/dist/Layout/LayoutFooter.d.ts.map +1 -1
- package/dist/Layout/LayoutHeader.d.ts +2 -2
- package/dist/Layout/LayoutHeader.d.ts.map +1 -1
- package/dist/Layout/LayoutPanel.d.ts +2 -2
- package/dist/Layout/LayoutPanel.d.ts.map +1 -1
- package/dist/Layout/padding.stylex.d.ts +51 -0
- package/dist/Layout/padding.stylex.d.ts.map +1 -1
- package/dist/Layout/padding.stylex.js +63 -0
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +4 -2
- package/dist/Link/Link.d.ts +17 -2
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +20 -9
- package/dist/Link/LinkProvider.d.ts +1 -0
- package/dist/Link/LinkProvider.d.ts.map +1 -1
- package/dist/Link/LinkProvider.js +1 -0
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +18 -3
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +13 -0
- package/dist/MoreMenu/MoreMenu.d.ts +1 -7
- package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
- package/dist/MoreMenu/MoreMenu.js +0 -2
- package/dist/MultiSelector/MultiSelector.d.ts +25 -2
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +103 -22
- package/dist/MultiSelector/hooks.d.ts +12 -1
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +14 -1
- package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
- package/dist/NavMenu/NavHeadingMenu.js +34 -3
- package/dist/NumberInput/NumberInput.d.ts +23 -2
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +62 -12
- package/dist/Pagination/Pagination.d.ts +1 -1
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +46 -28
- package/dist/Popover/usePopover.d.ts +25 -2
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +18 -6
- package/dist/PowerSearch/PowerSearch.d.ts +11 -1
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +6 -1
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +3 -5
- package/dist/RadioList/RadioList.d.ts +20 -2
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +105 -9
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +13 -2
- package/dist/SegmentedControl/SegmentedControl.d.ts +13 -2
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +78 -44
- package/dist/SegmentedControl/SegmentedControlContext.d.ts +7 -0
- package/dist/SegmentedControl/SegmentedControlContext.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +13 -2
- package/dist/Selector/Selector.d.ts +22 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +84 -23
- package/dist/Selector/hooks.d.ts +8 -1
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +14 -1
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +1 -1
- package/dist/Skeleton/Skeleton.d.ts.map +1 -1
- package/dist/Skeleton/Skeleton.js +8 -2
- package/dist/Slider/Slider.d.ts +21 -0
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +38 -11
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +1 -1
- package/dist/Stack/Stack.d.ts +38 -23
- package/dist/Stack/Stack.d.ts.map +1 -1
- package/dist/Stack/Stack.js +25 -1
- package/dist/Stack/StackItem.d.ts +12 -23
- package/dist/Stack/StackItem.d.ts.map +1 -1
- package/dist/Stack/StackItem.js +8 -1
- package/dist/Switch/Switch.d.ts +23 -2
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +41 -11
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +6 -0
- package/dist/TabList/TabList.d.ts +16 -4
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +86 -10
- package/dist/TabList/TabListContext.d.ts +5 -0
- package/dist/TabList/TabListContext.d.ts.map +1 -1
- package/dist/TabList/TabListContext.js +5 -0
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +6 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +38 -16
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +36 -7
- package/dist/Table/TableCell.d.ts +8 -1
- package/dist/Table/TableCell.d.ts.map +1 -1
- package/dist/Table/TableCell.js +10 -10
- package/dist/Table/TableHeaderCell.d.ts +8 -1
- package/dist/Table/TableHeaderCell.d.ts.map +1 -1
- package/dist/Table/TableHeaderCell.js +16 -16
- package/dist/Table/TableRow.d.ts +6 -1
- package/dist/Table/TableRow.d.ts.map +1 -1
- package/dist/Table/TableRow.js +15 -7
- package/dist/Table/index.d.ts +4 -1
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +3 -2
- package/dist/Table/plugins/pagination/paginateData.d.ts +2 -1
- package/dist/Table/plugins/pagination/paginateData.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/paginateData.js +8 -3
- package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/useTablePagination.js +6 -1
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +59 -3
- package/dist/Table/plugins/stickyColumns/index.d.ts +3 -0
- package/dist/Table/plugins/stickyColumns/index.d.ts.map +1 -0
- package/dist/Table/plugins/stickyColumns/index.js +3 -0
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts +25 -0
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -0
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +369 -0
- package/dist/Table/tableContextMenu.d.ts +33 -0
- package/dist/Table/tableContextMenu.d.ts.map +1 -0
- package/dist/Table/tableContextMenu.js +133 -0
- package/dist/Table/types.d.ts +161 -5
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +1 -1
- package/dist/Text/text.stylex.d.ts +2 -2
- package/dist/Text/text.stylex.js +2 -2
- package/dist/TextArea/TextArea.d.ts +22 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +41 -9
- package/dist/TextInput/TextInput.d.ts +23 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +55 -10
- package/dist/TimeInput/TimeInput.d.ts +23 -1
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +53 -10
- package/dist/Timestamp/Timestamp.d.ts +1 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +28 -3
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +14 -0
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +132 -3
- package/dist/ToggleButton/ToggleButton.d.ts +7 -9
- package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButton.js +34 -57
- package/dist/Tokenizer/Tokenizer.d.ts +12 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +27 -5
- package/dist/Toolbar/Toolbar.d.ts +3 -3
- package/dist/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar/Toolbar.js +51 -7
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +57 -9
- package/dist/TreeList/TreeList.d.ts +1 -1
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +72 -2
- package/dist/TreeList/TreeListItem.d.ts +11 -1
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +51 -12
- package/dist/TreeList/treeListItem.markers.stylex.d.ts +16 -0
- package/dist/TreeList/treeListItem.markers.stylex.d.ts.map +1 -0
- package/dist/TreeList/treeListItem.markers.stylex.js +22 -0
- package/dist/Typeahead/BaseTypeahead.d.ts +9 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +67 -6
- package/dist/Typeahead/Typeahead.d.ts +24 -1
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +29 -5
- package/dist/VisuallyHidden/VisuallyHidden.d.ts +61 -0
- package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -0
- package/dist/VisuallyHidden/VisuallyHidden.js +65 -0
- package/dist/VisuallyHidden/index.d.ts +11 -0
- package/dist/VisuallyHidden/index.d.ts.map +1 -0
- package/dist/VisuallyHidden/index.js +13 -0
- package/dist/astryx.css +40 -1
- package/dist/astryx.umd.js +147 -0
- package/dist/astryx.umd.js.map +7 -0
- package/dist/hooks/focusableSelector.d.ts +22 -0
- package/dist/hooks/focusableSelector.d.ts.map +1 -0
- package/dist/hooks/focusableSelector.js +24 -0
- package/dist/hooks/index.d.ts +12 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +7 -2
- package/dist/hooks/useAnnounce.d.ts +40 -0
- package/dist/hooks/useAnnounce.d.ts.map +1 -0
- package/dist/hooks/useAnnounce.js +142 -0
- package/dist/hooks/useClickableContainer.d.ts +16 -1
- package/dist/hooks/useClickableContainer.d.ts.map +1 -1
- package/dist/hooks/useClickableContainer.js +16 -4
- package/dist/hooks/useEntryAnimation.d.ts.map +1 -1
- package/dist/hooks/useEntryAnimation.js +4 -4
- package/dist/hooks/useFocusTrap.d.ts +18 -0
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +87 -3
- package/dist/hooks/useGridFocus.d.ts +88 -1
- package/dist/hooks/useGridFocus.d.ts.map +1 -1
- package/dist/hooks/useGridFocus.js +261 -62
- package/dist/hooks/useKeyboardHint.d.ts +82 -0
- package/dist/hooks/useKeyboardHint.d.ts.map +1 -0
- package/dist/hooks/useKeyboardHint.js +220 -0
- package/dist/hooks/useListFocus.d.ts +78 -7
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useListFocus.js +305 -52
- package/dist/hooks/useLongPress.d.ts +21 -0
- package/dist/hooks/useLongPress.d.ts.map +1 -0
- package/dist/hooks/useLongPress.js +89 -0
- package/dist/hooks/useTreeFocus.d.ts +157 -0
- package/dist/hooks/useTreeFocus.d.ts.map +1 -0
- package/dist/hooks/useTreeFocus.js +337 -0
- package/dist/hooks/useTypeahead.d.ts +63 -0
- package/dist/hooks/useTypeahead.d.ts.map +1 -0
- package/dist/hooks/useTypeahead.js +117 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/theme/generateThemeRules.js +1 -1
- package/dist/theme/syntax/SyntaxTheme.d.ts +1 -1
- package/dist/theme/syntax/SyntaxTheme.js +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.js +2 -2
- package/dist/theme/syntax/presets.d.ts +1 -1
- package/dist/theme/syntax/presets.d.ts.map +1 -1
- package/dist/theme/syntax/presets.js +1 -1
- package/dist/theme/syntax/tokens.d.ts +1 -1
- package/dist/theme/syntax/tokens.js +1 -1
- package/dist/theme/types.d.ts +1 -1
- package/dist/utils/dateTypes.d.ts +12 -0
- package/dist/utils/dateTypes.d.ts.map +1 -1
- package/dist/utils/dateTypes.js +41 -1
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -1
- package/dist/utils/inputAria.d.ts +29 -0
- package/dist/utils/inputAria.d.ts.map +1 -0
- package/dist/utils/inputAria.js +30 -0
- package/dist/utils/timeParser.d.ts.map +1 -1
- package/dist/utils/timeParser.js +5 -2
- package/package.json +15 -5
- package/src/Avatar/Avatar.test.tsx +37 -0
- package/src/Avatar/Avatar.tsx +10 -5
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +3 -0
- package/src/Banner/Banner.doc.mjs +8 -0
- package/src/Banner/Banner.test.tsx +16 -7
- package/src/Banner/Banner.tsx +9 -2
- package/src/Breadcrumbs/BreadcrumbItem.tsx +25 -7
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +31 -10
- package/src/Button/Button.doc.mjs +6 -0
- package/src/Button/Button.test.tsx +105 -11
- package/src/Button/Button.tsx +76 -21
- package/src/Calendar/Calendar.doc.mjs +4 -4
- package/src/Calendar/Calendar.test.tsx +168 -30
- package/src/Calendar/Calendar.tsx +121 -66
- package/src/Calendar/hooks/index.ts +0 -6
- package/src/Calendar/index.ts +1 -3
- package/src/Calendar/styles.ts +4 -9
- package/src/Carousel/Carousel.doc.mjs +7 -1
- package/src/Carousel/Carousel.test.tsx +20 -0
- package/src/Carousel/Carousel.tsx +16 -1
- package/src/Center/Center.doc.mjs +12 -2
- package/src/Center/Center.tsx +28 -3
- package/src/Chat/ChatComposer.doc.mjs +3 -0
- package/src/Chat/ChatComposerDrawer.doc.mjs +12 -0
- package/src/Chat/ChatMessageList.doc.mjs +8 -0
- package/src/Chat/ChatMessageList.test.tsx +18 -0
- package/src/Chat/ChatMessageList.tsx +16 -0
- package/src/Chat/useTriggerMenu.tsx +3 -0
- package/src/CheckboxInput/CheckboxInput.doc.mjs +18 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +172 -27
- package/src/CheckboxInput/CheckboxInput.tsx +78 -6
- package/src/CheckboxList/CheckboxList.doc.mjs +9 -0
- package/src/CheckboxList/CheckboxList.test.tsx +169 -16
- package/src/CheckboxList/CheckboxList.tsx +56 -3
- package/src/CheckboxList/CheckboxListContext.tsx +7 -0
- package/src/Citation/Citation.doc.mjs +10 -0
- package/src/Citation/Citation.test.tsx +117 -0
- package/src/Citation/Citation.tsx +9 -1
- package/src/ClickableCard/ClickableCard.doc.mjs +15 -0
- package/src/CodeBlock/CodeBlock.test.tsx +115 -0
- package/src/CodeBlock/CodeBlock.tsx +61 -33
- package/src/CommandPalette/CommandPalette.test.tsx +47 -1
- package/src/CommandPalette/CommandPalette.tsx +9 -21
- package/src/ContextMenu/ContextMenu.doc.mjs +4 -4
- package/src/ContextMenu/ContextMenu.test.tsx +155 -1
- package/src/ContextMenu/ContextMenu.tsx +113 -16
- package/src/DateInput/DateInput.doc.mjs +281 -56
- package/src/DateInput/DateInput.test.tsx +188 -2
- package/src/DateInput/DateInput.tsx +89 -10
- package/src/DateRangeInput/DateRangeInput.doc.mjs +251 -46
- package/src/DateRangeInput/DateRangeInput.test.tsx +182 -20
- package/src/DateRangeInput/DateRangeInput.tsx +63 -5
- package/src/DateTimeInput/DateTimeInput.doc.mjs +368 -67
- package/src/DateTimeInput/DateTimeInput.test.tsx +279 -11
- package/src/DateTimeInput/DateTimeInput.tsx +125 -17
- package/src/Dialog/Dialog.doc.mjs +2 -2
- package/src/Dialog/Dialog.tsx +12 -0
- package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -8
- package/src/DropdownMenu/DropdownMenu.test.tsx +56 -42
- package/src/DropdownMenu/DropdownMenu.tsx +52 -18
- package/src/EmptyState/EmptyState.test.tsx +4 -2
- package/src/EmptyState/EmptyState.tsx +6 -2
- package/src/Field/Field.test.tsx +32 -0
- package/src/Field/Field.tsx +23 -5
- package/src/Field/FieldLabel.tsx +55 -17
- package/src/FileInput/FileInput.doc.mjs +17 -0
- package/src/FileInput/FileInput.test.tsx +283 -49
- package/src/FileInput/FileInput.tsx +76 -4
- package/src/Grid/Grid.doc.mjs +14 -4
- package/src/Grid/Grid.tsx +20 -0
- package/src/HoverCard/HoverCard.doc.mjs +3 -0
- package/src/HoverCard/HoverCard.test.tsx +189 -2
- package/src/HoverCard/HoverCard.tsx +20 -16
- package/src/HoverCard/useHoverCard.tsx +13 -10
- package/src/Icon/Icon.doc.mjs +8 -0
- package/src/InputGroup/InputGroup.doc.mjs +2 -2
- package/src/InputGroup/InputGroup.test.tsx +98 -60
- package/src/InputGroup/InputGroup.tsx +21 -4
- package/src/InputGroup/InputGroupContext.ts +9 -4
- package/src/InputGroup/index.ts +1 -0
- package/src/Kbd/Kbd.test.tsx +22 -4
- package/src/Kbd/Kbd.tsx +37 -12
- package/src/Layer/anchorName.test.ts +146 -0
- package/src/Layer/anchorName.ts +46 -0
- package/src/Layer/layerAnimations.stylex.ts +20 -4
- package/src/Layer/useLayer.doc.mjs +12 -2
- package/src/Layer/useLayer.tsx +100 -15
- package/src/Layout/Layout.doc.mjs +1 -1
- package/src/Layout/Layout.tsx +8 -16
- package/src/Layout/LayoutFooter.doc.mjs +4 -4
- package/src/Layout/LayoutFooter.tsx +3 -3
- package/src/Layout/LayoutHeader.doc.mjs +4 -4
- package/src/Layout/LayoutHeader.tsx +3 -3
- package/src/Layout/LayoutPanel.tsx +3 -3
- package/src/Layout/padding.stylex.ts +52 -0
- package/src/Lightbox/Lightbox.doc.mjs +9 -2
- package/src/Lightbox/Lightbox.test.tsx +53 -5
- package/src/Lightbox/Lightbox.tsx +9 -4
- package/src/Link/Link.doc.mjs +14 -0
- package/src/Link/Link.test.tsx +52 -2
- package/src/Link/Link.tsx +42 -7
- package/src/Link/LinkProvider.tsx +1 -0
- package/src/List/List.doc.mjs +7 -0
- package/src/Markdown/Markdown.doc.mjs +2 -0
- package/src/Markdown/Markdown.test.tsx +28 -26
- package/src/Markdown/Markdown.tsx +21 -6
- package/src/MetadataList/MetadataListItem.doc.mjs +4 -0
- package/src/MobileNav/MobileNav.doc.mjs +8 -8
- package/src/MobileNav/MobileNav.tsx +13 -0
- package/src/MobileNav/MobileNavReopen.test.tsx +118 -0
- package/src/MoreMenu/MoreMenu.doc.mjs +2 -17
- package/src/MoreMenu/MoreMenu.tsx +0 -9
- package/src/MultiSelector/MultiSelector.doc.mjs +25 -0
- package/src/MultiSelector/MultiSelector.test.tsx +375 -8
- package/src/MultiSelector/MultiSelector.tsx +145 -21
- package/src/MultiSelector/hooks.ts +27 -0
- package/src/NavMenu/NavHeadingMenu.test.tsx +77 -1
- package/src/NavMenu/NavHeadingMenu.tsx +50 -3
- package/src/NumberInput/NumberInput.doc.mjs +17 -0
- package/src/NumberInput/NumberInput.test.tsx +242 -40
- package/src/NumberInput/NumberInput.tsx +89 -11
- package/src/OverflowList/OverflowList.doc.mjs +17 -0
- package/src/Pagination/Pagination.doc.mjs +3 -3
- package/src/Pagination/Pagination.test.tsx +250 -14
- package/src/Pagination/Pagination.tsx +54 -29
- package/src/Popover/usePopover.doc.mjs +7 -3
- package/src/Popover/usePopover.tsx +49 -6
- package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
- package/src/PowerSearch/PowerSearch.test.tsx +97 -1
- package/src/PowerSearch/PowerSearch.tsx +16 -3
- package/src/ProgressBar/ProgressBar.test.tsx +45 -27
- package/src/ProgressBar/ProgressBar.tsx +3 -4
- package/src/RadioList/RadioList.doc.mjs +9 -0
- package/src/RadioList/RadioList.test.tsx +252 -16
- package/src/RadioList/RadioList.tsx +166 -10
- package/src/RadioList/RadioListItem.tsx +14 -2
- package/src/Resizable/Resizable.doc.mjs +1 -1
- package/src/Section/Section.doc.mjs +11 -0
- package/src/SegmentedControl/SegmentedControl.doc.mjs +9 -0
- package/src/SegmentedControl/SegmentedControl.test.tsx +214 -42
- package/src/SegmentedControl/SegmentedControl.tsx +102 -54
- package/src/SegmentedControl/SegmentedControlContext.ts +7 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +14 -1
- package/src/SelectableCard/SelectableCard.doc.mjs +15 -0
- package/src/Selector/Selector.doc.mjs +25 -0
- package/src/Selector/Selector.test.tsx +322 -15
- package/src/Selector/Selector.tsx +126 -40
- package/src/Selector/hooks.ts +23 -0
- package/src/SideNav/SideNav.test.tsx +16 -0
- package/src/SideNav/SideNavItem.tsx +2 -4
- package/src/Skeleton/Skeleton.doc.mjs +11 -1
- package/src/Skeleton/Skeleton.test.tsx +25 -0
- package/src/Skeleton/Skeleton.tsx +11 -1
- package/src/Slider/Slider.doc.mjs +19 -0
- package/src/Slider/Slider.test.tsx +158 -18
- package/src/Slider/Slider.tsx +54 -6
- package/src/Spinner/Spinner.tsx +7 -1
- package/src/Stack/Stack.doc.mjs +77 -0
- package/src/Stack/Stack.test.tsx +55 -5
- package/src/Stack/Stack.tsx +73 -24
- package/src/Stack/StackItem.test.tsx +23 -0
- package/src/Stack/StackItem.tsx +20 -23
- package/src/Switch/Switch.doc.mjs +15 -0
- package/src/Switch/Switch.test.tsx +162 -27
- package/src/Switch/Switch.tsx +61 -21
- package/src/TabList/Tab.tsx +6 -0
- package/src/TabList/TabList.doc.mjs +12 -0
- package/src/TabList/TabList.test.tsx +208 -0
- package/src/TabList/TabList.tsx +102 -12
- package/src/TabList/TabListContext.ts +7 -3
- package/src/TabList/TabMenu.tsx +6 -3
- package/src/Table/BaseTable.tsx +72 -41
- package/src/Table/Table.doc.mjs +14 -0
- package/src/Table/Table.test.tsx +39 -30
- package/src/Table/Table.tsx +27 -1
- package/src/Table/TableCell.tsx +25 -23
- package/src/Table/TableHeaderCell.tsx +28 -29
- package/src/Table/TableRow.tsx +37 -7
- package/src/Table/index.ts +6 -2
- package/src/Table/plugins/pagination/paginateData.ts +10 -3
- package/src/Table/plugins/pagination/useTablePagination.test.tsx +16 -0
- package/src/Table/plugins/pagination/useTablePagination.tsx +8 -1
- package/src/Table/plugins/sortable/useTableSortable.test.tsx +91 -2
- package/src/Table/plugins/sortable/useTableSortable.tsx +53 -1
- package/src/Table/plugins/stickyColumns/index.ts +4 -0
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.test.tsx +163 -0
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +407 -0
- package/src/Table/tableContextMenu.test.tsx +157 -0
- package/src/Table/tableContextMenu.tsx +142 -0
- package/src/Table/types.ts +175 -4
- package/src/Table/useBaseTablePlugins.ts +1 -0
- package/src/Table/useTableColumnResize.doc.mjs +96 -0
- package/src/Table/useTableStickyColumns.doc.mjs +59 -0
- package/src/Text/Heading.doc.mjs +15 -2
- package/src/Text/Text.doc.mjs +7 -1
- package/src/Text/text.stylex.ts +2 -2
- package/src/TextArea/TextArea.doc.mjs +17 -0
- package/src/TextArea/TextArea.test.tsx +167 -35
- package/src/TextArea/TextArea.tsx +62 -15
- package/src/TextInput/TextInput.doc.mjs +17 -0
- package/src/TextInput/TextInput.test.tsx +168 -34
- package/src/TextInput/TextInput.tsx +77 -9
- package/src/TimeInput/TimeInput.doc.mjs +335 -60
- package/src/TimeInput/TimeInput.test.tsx +144 -7
- package/src/TimeInput/TimeInput.tsx +74 -5
- package/src/Timestamp/Timestamp.doc.mjs +9 -0
- package/src/Timestamp/Timestamp.test.tsx +44 -18
- package/src/Timestamp/Timestamp.tsx +30 -10
- package/src/Toast/Toast.tsx +14 -0
- package/src/Toast/ToastViewport.test.tsx +204 -0
- package/src/Toast/ToastViewport.tsx +167 -21
- package/src/ToggleButton/ToggleButton.doc.mjs +9 -3
- package/src/ToggleButton/ToggleButton.test.tsx +39 -18
- package/src/ToggleButton/ToggleButton.tsx +46 -83
- package/src/Tokenizer/Tokenizer.doc.mjs +15 -0
- package/src/Tokenizer/Tokenizer.test.tsx +105 -1
- package/src/Tokenizer/Tokenizer.tsx +41 -2
- package/src/Toolbar/Toolbar.doc.mjs +65 -5
- package/src/Toolbar/Toolbar.test.tsx +109 -6
- package/src/Toolbar/Toolbar.tsx +59 -5
- package/src/Tooltip/Tooltip.test.tsx +81 -0
- package/src/Tooltip/useTooltip.tsx +57 -11
- package/src/TreeList/TreeList.test.tsx +295 -6
- package/src/TreeList/TreeList.tsx +73 -1
- package/src/TreeList/TreeListItem.tsx +51 -5
- package/src/TreeList/treeListItem.markers.stylex.ts +20 -0
- package/src/Typeahead/BaseTypeahead.tsx +86 -9
- package/src/Typeahead/Typeahead.doc.mjs +136 -30
- package/src/Typeahead/Typeahead.test.tsx +331 -1
- package/src/Typeahead/Typeahead.tsx +52 -1
- package/src/VisuallyHidden/VisuallyHidden.doc.mjs +80 -0
- package/src/VisuallyHidden/VisuallyHidden.test.tsx +76 -0
- package/src/VisuallyHidden/VisuallyHidden.tsx +113 -0
- package/src/VisuallyHidden/index.ts +15 -0
- package/src/hooks/focusableSelector.ts +25 -0
- package/src/hooks/index.ts +28 -2
- package/src/hooks/useAnnounce.test.tsx +101 -0
- package/src/hooks/useAnnounce.ts +168 -0
- package/src/hooks/useClickableContainer.ts +16 -4
- package/src/hooks/useEntryAnimation.ts +16 -4
- package/src/hooks/useFocusTrap.test.tsx +132 -0
- package/src/hooks/useFocusTrap.ts +98 -4
- package/src/hooks/useGridFocus.doc.mjs +40 -2
- package/src/hooks/useGridFocus.test.tsx +132 -0
- package/src/hooks/useGridFocus.ts +343 -67
- package/src/hooks/useImageMode.test.ts +133 -0
- package/src/hooks/useKeyboardHint.doc.mjs +101 -0
- package/src/hooks/useKeyboardHint.test.tsx +70 -0
- package/src/hooks/useKeyboardHint.tsx +332 -0
- package/src/hooks/useListFocus.doc.mjs +50 -10
- package/src/hooks/useListFocus.test.tsx +375 -0
- package/src/hooks/useListFocus.ts +395 -57
- package/src/hooks/useLongPress.test.tsx +134 -0
- package/src/hooks/useLongPress.ts +119 -0
- package/src/hooks/useTreeFocus.doc.mjs +140 -0
- package/src/hooks/useTreeFocus.test.tsx +214 -0
- package/src/hooks/useTreeFocus.ts +559 -0
- package/src/hooks/useTypeahead.test.tsx +109 -0
- package/src/hooks/useTypeahead.ts +183 -0
- package/src/index.ts +1 -0
- package/src/theme/derivedVarRegistry.test.ts +4 -0
- package/src/theme/generateThemeRules.test.ts +7 -8
- package/src/theme/generateThemeRules.ts +1 -1
- package/src/theme/syntax/SyntaxTheme.tsx +1 -1
- package/src/theme/syntax/defineSyntaxTheme.ts +20 -11
- package/src/theme/syntax/presets.ts +5 -2
- package/src/theme/syntax/tokens.ts +1 -1
- package/src/theme/types.ts +1 -1
- package/src/utils/dateTypes.test.ts +40 -0
- package/src/utils/dateTypes.ts +40 -0
- package/src/utils/index.ts +9 -0
- package/src/utils/inputAria.test.ts +39 -0
- package/src/utils/inputAria.ts +58 -0
- package/src/utils/timeParser.test.ts +10 -0
- package/src/utils/timeParser.ts +5 -2
- package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts +0 -57
- package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts.map +0 -1
- package/dist/Calendar/hooks/useCalendarRovingTabindex.js +0 -96
- package/src/Calendar/hooks/useCalendarRovingTabindex.ts +0 -118
|
@@ -61,14 +61,7 @@ export const docs = {
|
|
|
61
61
|
type: 'boolean',
|
|
62
62
|
description: 'Whether to show a chevron icon on the trigger button. Set to false for icon-only triggers.',
|
|
63
63
|
default: 'true',
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
name: 'hasAutoFocus',
|
|
67
|
-
type: 'boolean',
|
|
68
|
-
description: 'Whether to auto-focus the first menu item when the menu opens. Set to false for inline showcases or documentation previews.',
|
|
69
|
-
default: 'true',
|
|
70
|
-
},
|
|
71
|
-
{
|
|
64
|
+
}, {
|
|
72
65
|
name: 'children',
|
|
73
66
|
type: '(item: DropdownMenuItemData) => ReactNode',
|
|
74
67
|
description: 'Custom render function for each item in the list.',
|
|
@@ -45,30 +45,43 @@ beforeEach(() => {
|
|
|
45
45
|
describe('DropdownMenu', () => {
|
|
46
46
|
it('renders trigger button with label', () => {
|
|
47
47
|
render(
|
|
48
|
-
<DropdownMenu
|
|
49
|
-
button={{label: 'Actions'}}
|
|
50
|
-
items={[{label: 'Item 1'}]}
|
|
51
|
-
/>,
|
|
48
|
+
<DropdownMenu button={{label: 'Actions'}} items={[{label: 'Item 1'}]} />,
|
|
52
49
|
);
|
|
53
50
|
expect(screen.getByRole('button', {name: /Actions/})).toBeInTheDocument();
|
|
54
51
|
});
|
|
55
52
|
|
|
56
53
|
it('renders menu with role="menu"', () => {
|
|
57
54
|
render(
|
|
58
|
-
<DropdownMenu
|
|
59
|
-
button={{label: 'Actions'}}
|
|
60
|
-
items={[{label: 'Item 1'}]}
|
|
61
|
-
/>,
|
|
55
|
+
<DropdownMenu button={{label: 'Actions'}} items={[{label: 'Item 1'}]} />,
|
|
62
56
|
);
|
|
63
57
|
expect(screen.getByRole('menu', {hidden: true})).toBeInTheDocument();
|
|
64
58
|
});
|
|
65
59
|
|
|
60
|
+
it('names the menu from the trigger label (menus-13)', () => {
|
|
61
|
+
render(
|
|
62
|
+
<DropdownMenu button={{label: 'Actions'}} items={[{label: 'Item 1'}]} />,
|
|
63
|
+
);
|
|
64
|
+
expect(
|
|
65
|
+
screen.getByRole('menu', {name: 'Actions', hidden: true}),
|
|
66
|
+
).toBeInTheDocument();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('does not wrap the menu in a role="dialog" aria-modal element', () => {
|
|
70
|
+
render(
|
|
71
|
+
<DropdownMenu button={{label: 'Actions'}} items={[{label: 'Item 1'}]} />,
|
|
72
|
+
);
|
|
73
|
+
// The popup exposes its own role="menu"; it must not be nested inside a
|
|
74
|
+
// modal dialog, which would announce an unnamed dialog around the menu
|
|
75
|
+
// while focus stays on the trigger.
|
|
76
|
+
expect(screen.queryByRole('dialog', {hidden: true})).not.toBeInTheDocument();
|
|
77
|
+
expect(
|
|
78
|
+
document.querySelector('[aria-modal="true"]'),
|
|
79
|
+
).not.toBeInTheDocument();
|
|
80
|
+
});
|
|
81
|
+
|
|
66
82
|
it('defaults menu placement below', () => {
|
|
67
83
|
render(
|
|
68
|
-
<DropdownMenu
|
|
69
|
-
button={{label: 'Actions'}}
|
|
70
|
-
items={[{label: 'Item 1'}]}
|
|
71
|
-
/>,
|
|
84
|
+
<DropdownMenu button={{label: 'Actions'}} items={[{label: 'Item 1'}]} />,
|
|
72
85
|
);
|
|
73
86
|
const popover = screen
|
|
74
87
|
.getByRole('menu', {hidden: true})
|
|
@@ -96,10 +109,7 @@ describe('DropdownMenu', () => {
|
|
|
96
109
|
|
|
97
110
|
it('has aria-haspopup and aria-expanded attributes', () => {
|
|
98
111
|
render(
|
|
99
|
-
<DropdownMenu
|
|
100
|
-
button={{label: 'Actions'}}
|
|
101
|
-
items={[{label: 'Item 1'}]}
|
|
102
|
-
/>,
|
|
112
|
+
<DropdownMenu button={{label: 'Actions'}} items={[{label: 'Item 1'}]} />,
|
|
103
113
|
);
|
|
104
114
|
const button = screen.getByRole('button', {name: /Actions/});
|
|
105
115
|
expect(button).toHaveAttribute('aria-haspopup', 'menu');
|
|
@@ -107,16 +117,43 @@ describe('DropdownMenu', () => {
|
|
|
107
117
|
});
|
|
108
118
|
|
|
109
119
|
it('opens menu when button is clicked', async () => {
|
|
120
|
+
const user = userEvent.setup();
|
|
121
|
+
render(
|
|
122
|
+
<DropdownMenu button={{label: 'Actions'}} items={[{label: 'Item 1'}]} />,
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
await user.click(screen.getByRole('button', {name: /Actions/}));
|
|
126
|
+
expect(HTMLElement.prototype.showPopover).toHaveBeenCalled();
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('closes the menu when Tab is pressed inside it (APG menu-button)', async () => {
|
|
130
|
+
const user = userEvent.setup();
|
|
131
|
+
render(
|
|
132
|
+
<DropdownMenu button={{label: 'Actions'}} items={[{label: 'Item 1'}]} />,
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
await user.click(screen.getByRole('button', {name: /Actions/}));
|
|
136
|
+
expect(HTMLElement.prototype.showPopover).toHaveBeenCalled();
|
|
137
|
+
|
|
138
|
+
const menu = screen.getByRole('menu', {hidden: true});
|
|
139
|
+
fireEvent.keyDown(menu, {key: 'Tab'});
|
|
140
|
+
expect(HTMLElement.prototype.hidePopover).toHaveBeenCalled();
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('typeahead focuses the item matching the typed character (menus-11)', async () => {
|
|
110
144
|
const user = userEvent.setup();
|
|
111
145
|
render(
|
|
112
146
|
<DropdownMenu
|
|
113
147
|
button={{label: 'Actions'}}
|
|
114
|
-
items={[{label: '
|
|
148
|
+
items={[{label: 'Cut'}, {label: 'Copy'}, {label: 'Delete'}]}
|
|
115
149
|
/>,
|
|
116
150
|
);
|
|
117
|
-
|
|
118
151
|
await user.click(screen.getByRole('button', {name: /Actions/}));
|
|
119
|
-
|
|
152
|
+
const menu = screen.getByRole('menu', {hidden: true});
|
|
153
|
+
fireEvent.keyDown(menu, {key: 'd'});
|
|
154
|
+
expect(
|
|
155
|
+
screen.getByRole('menuitem', {name: 'Delete', hidden: true}),
|
|
156
|
+
).toHaveFocus();
|
|
120
157
|
});
|
|
121
158
|
|
|
122
159
|
it('calls onClick callback when button is clicked', async () => {
|
|
@@ -212,29 +249,6 @@ describe('DropdownMenu controlled mode', () => {
|
|
|
212
249
|
});
|
|
213
250
|
});
|
|
214
251
|
|
|
215
|
-
describe('DropdownMenu hasAutoFocus', () => {
|
|
216
|
-
it('does not focus menu items when hasAutoFocus is false and isMenuOpen is true', () => {
|
|
217
|
-
const focusSpy = vi.spyOn(HTMLElement.prototype, 'focus');
|
|
218
|
-
render(
|
|
219
|
-
<DropdownMenu
|
|
220
|
-
button={{label: 'Actions'}}
|
|
221
|
-
items={[{label: 'Edit'}, {label: 'Delete'}]}
|
|
222
|
-
isMenuOpen={true}
|
|
223
|
-
hasAutoFocus={false}
|
|
224
|
-
onOpenChange={() => {}}
|
|
225
|
-
/>,
|
|
226
|
-
);
|
|
227
|
-
|
|
228
|
-
const menuItems = screen.getAllByRole('menuitem', {hidden: true});
|
|
229
|
-
const menuItemFocusCalls = focusSpy.mock.calls.filter((_, i) => {
|
|
230
|
-
const ctx = focusSpy.mock.contexts[i];
|
|
231
|
-
return menuItems.includes(ctx as HTMLElement);
|
|
232
|
-
});
|
|
233
|
-
expect(menuItemFocusCalls).toHaveLength(0);
|
|
234
|
-
focusSpy.mockRestore();
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
|
|
238
252
|
describe('DropdownMenu items', () => {
|
|
239
253
|
it('renders items with labels', () => {
|
|
240
254
|
render(
|
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
type DropdownMenuContextValue,
|
|
44
44
|
} from './DropdownMenuContext';
|
|
45
45
|
import {useListFocus} from '../hooks/useListFocus';
|
|
46
|
+
import {useTypeahead} from '../hooks/useTypeahead';
|
|
46
47
|
import {layerAnimations} from '../Layer/layerAnimations.stylex';
|
|
47
48
|
import type {LayerPlacement} from '../Layer/useLayer';
|
|
48
49
|
import {
|
|
@@ -134,13 +135,6 @@ interface DropdownMenuBaseProps extends BaseProps {
|
|
|
134
135
|
*/
|
|
135
136
|
placement?: LayerPlacement;
|
|
136
137
|
|
|
137
|
-
/**
|
|
138
|
-
* Whether to auto-focus the first menu item when the menu opens.
|
|
139
|
-
* Set to `false` for inline showcases or documentation previews
|
|
140
|
-
* where stealing focus is undesirable.
|
|
141
|
-
* @default true
|
|
142
|
-
*/
|
|
143
|
-
hasAutoFocus?: boolean;
|
|
144
138
|
'data-testid'?: string;
|
|
145
139
|
}
|
|
146
140
|
|
|
@@ -192,7 +186,6 @@ export function DropdownMenu({
|
|
|
192
186
|
onClick,
|
|
193
187
|
hasChevron = true,
|
|
194
188
|
placement = 'below',
|
|
195
|
-
hasAutoFocus = true,
|
|
196
189
|
className,
|
|
197
190
|
style,
|
|
198
191
|
xstyle,
|
|
@@ -249,6 +242,9 @@ export function DropdownMenu({
|
|
|
249
242
|
hasLightDismiss: true,
|
|
250
243
|
hasCloseButton: false,
|
|
251
244
|
hasAutoFocus: false,
|
|
245
|
+
// The popup's own role="menu" is the exposed semantics; wrapping it in a
|
|
246
|
+
// modal dialog would announce an unnamed dialog around the menu.
|
|
247
|
+
role: 'none',
|
|
252
248
|
});
|
|
253
249
|
|
|
254
250
|
const closeMenu = useCallback(() => {
|
|
@@ -260,27 +256,49 @@ export function DropdownMenu({
|
|
|
260
256
|
listRef,
|
|
261
257
|
handleKeyDown: listNavKeyDown,
|
|
262
258
|
focusFirst,
|
|
259
|
+
focusItem,
|
|
263
260
|
} = useListFocus<HTMLDivElement>({
|
|
264
261
|
itemSelector: '[role="menuitem"]:not([aria-disabled="true"])',
|
|
265
262
|
wrap: false,
|
|
266
263
|
onEscape: closeMenu,
|
|
267
264
|
});
|
|
268
265
|
|
|
266
|
+
// First-character typeahead over the (enabled) menu items — jump to the next
|
|
267
|
+
// item whose label starts with the typed text (menus-11).
|
|
268
|
+
const getMenuItems = useCallback(
|
|
269
|
+
(): HTMLElement[] =>
|
|
270
|
+
listRef.current
|
|
271
|
+
? Array.from(
|
|
272
|
+
listRef.current.querySelectorAll<HTMLElement>(
|
|
273
|
+
'[role="menuitem"]:not([aria-disabled="true"])',
|
|
274
|
+
),
|
|
275
|
+
)
|
|
276
|
+
: [],
|
|
277
|
+
[listRef],
|
|
278
|
+
);
|
|
279
|
+
const typeahead = useTypeahead({
|
|
280
|
+
getItemLabels: () => getMenuItems().map(el => el.textContent),
|
|
281
|
+
onMatch: focusItem,
|
|
282
|
+
getCurrentIndex: () =>
|
|
283
|
+
getMenuItems().findIndex(
|
|
284
|
+
el =>
|
|
285
|
+
el === document.activeElement || el.contains(document.activeElement),
|
|
286
|
+
),
|
|
287
|
+
});
|
|
288
|
+
|
|
269
289
|
// Sync controlled open state → popover, and focus first item on open
|
|
270
290
|
useEffect(() => {
|
|
271
291
|
if (isControlled) {
|
|
272
292
|
if (controlledIsOpen && !popover.isOpen) {
|
|
273
293
|
popover.show();
|
|
274
|
-
|
|
275
|
-
requestAnimationFrame(() => focusFirst());
|
|
276
|
-
}
|
|
294
|
+
requestAnimationFrame(() => focusFirst());
|
|
277
295
|
} else if (!controlledIsOpen && popover.isOpen) {
|
|
278
296
|
popover.hide();
|
|
279
297
|
}
|
|
280
298
|
}
|
|
281
|
-
}, [controlledIsOpen, isControlled, popover,
|
|
299
|
+
}, [controlledIsOpen, isControlled, popover, focusFirst]);
|
|
282
300
|
|
|
283
|
-
// Extend useListFocus with Enter/Space activation
|
|
301
|
+
// Extend useListFocus with Enter/Space activation + typeahead
|
|
284
302
|
const listKeyDown = useCallback(
|
|
285
303
|
(e: React.KeyboardEvent) => {
|
|
286
304
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
@@ -291,17 +309,29 @@ export function DropdownMenu({
|
|
|
291
309
|
}
|
|
292
310
|
return;
|
|
293
311
|
}
|
|
312
|
+
// APG menu-button pattern: Tab closes the menu. Menu items are
|
|
313
|
+
// tabIndex={-1} so the focus trap has nothing trappable and Tab would
|
|
314
|
+
// otherwise leak into the page while the menu stayed open (menus-5).
|
|
315
|
+
// Do NOT preventDefault — closing restores focus to the trigger, and the
|
|
316
|
+
// browser's default Tab then continues from there to the next element.
|
|
317
|
+
if (e.key === 'Tab') {
|
|
318
|
+
closeMenu();
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
// Type-to-focus next; if it consumed a printable key, stop here.
|
|
322
|
+
if (typeahead.onKeyDown(e)) {
|
|
323
|
+
e.preventDefault();
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
294
326
|
listNavKeyDown(e);
|
|
295
327
|
},
|
|
296
|
-
[listNavKeyDown],
|
|
328
|
+
[listNavKeyDown, closeMenu, typeahead],
|
|
297
329
|
);
|
|
298
330
|
|
|
299
331
|
const openAndFocus = useCallback(() => {
|
|
300
332
|
popover.show();
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}
|
|
304
|
-
}, [popover, hasAutoFocus, focusFirst]);
|
|
333
|
+
requestAnimationFrame(() => focusFirst());
|
|
334
|
+
}, [popover, focusFirst]);
|
|
305
335
|
|
|
306
336
|
const handleButtonClick = useCallback(() => {
|
|
307
337
|
// If the menu was just closed by light dismiss (e.g. iOS Safari fires
|
|
@@ -399,6 +429,10 @@ export function DropdownMenu({
|
|
|
399
429
|
ref={listRef}
|
|
400
430
|
id={menuId}
|
|
401
431
|
role="menu"
|
|
432
|
+
// Give the menu an accessible name from its trigger's label, so
|
|
433
|
+
// screen readers announce e.g. "Actions menu" rather than an unnamed
|
|
434
|
+
// menu (menus-13).
|
|
435
|
+
aria-label={button.label}
|
|
402
436
|
onKeyDown={listKeyDown}
|
|
403
437
|
{...mergeProps(
|
|
404
438
|
themeProps('dropdown-menu'),
|
|
@@ -45,11 +45,13 @@ describe('EmptyState', () => {
|
|
|
45
45
|
/>,
|
|
46
46
|
);
|
|
47
47
|
expect(screen.getByText('Try adjusting your search.')).toBeInTheDocument();
|
|
48
|
+
// Description renders as <div> (never <p>) so block content composes safely.
|
|
49
|
+
expect(screen.getByText('Try adjusting your search.').tagName).toBe('DIV');
|
|
48
50
|
});
|
|
49
51
|
|
|
50
52
|
it('does not render description when not provided', () => {
|
|
51
|
-
|
|
52
|
-
expect(
|
|
53
|
+
render(<EmptyState title="No results" />);
|
|
54
|
+
expect(screen.queryByText('Try adjusting your search.')).toBeNull();
|
|
53
55
|
});
|
|
54
56
|
|
|
55
57
|
it('renders with icon', () => {
|
|
@@ -174,13 +174,17 @@ export function EmptyState({
|
|
|
174
174
|
title,
|
|
175
175
|
)}
|
|
176
176
|
{description != null && (
|
|
177
|
-
<p
|
|
177
|
+
// Rendered as <div> (not <p>): description accepts ReactNode and a
|
|
178
|
+
// <p> cannot legally contain block children, which causes hydration
|
|
179
|
+
// mismatches. The StyleX style sets margin: 0, so appearance is
|
|
180
|
+
// unchanged.
|
|
181
|
+
<div
|
|
178
182
|
{...stylex.props(
|
|
179
183
|
styles.description,
|
|
180
184
|
isCompact && styles.descriptionCompact,
|
|
181
185
|
)}>
|
|
182
186
|
{description}
|
|
183
|
-
</
|
|
187
|
+
</div>
|
|
184
188
|
)}
|
|
185
189
|
</div>
|
|
186
190
|
{actions != null && (
|
package/src/Field/Field.test.tsx
CHANGED
|
@@ -93,6 +93,38 @@ describe('Field', () => {
|
|
|
93
93
|
expect(label).toBeVisible();
|
|
94
94
|
});
|
|
95
95
|
|
|
96
|
+
it('renders a single-control label as a <label> with htmlFor', () => {
|
|
97
|
+
render(
|
|
98
|
+
<Field label="Email" inputID="email-input">
|
|
99
|
+
<input id="email-input" />
|
|
100
|
+
</Field>,
|
|
101
|
+
);
|
|
102
|
+
const labelEl = screen.getByText('Email');
|
|
103
|
+
expect(labelEl.tagName).toBe('LABEL');
|
|
104
|
+
expect(labelEl).toHaveAttribute('for', 'email-input');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('renders a group label as a <span> (not <label>) with no htmlFor', () => {
|
|
108
|
+
render(
|
|
109
|
+
<Field
|
|
110
|
+
label="Plan"
|
|
111
|
+
inputID="plan-group"
|
|
112
|
+
labelID="plan-label"
|
|
113
|
+
isGroupLabel>
|
|
114
|
+
<div role="radiogroup" aria-labelledby="plan-label" />
|
|
115
|
+
</Field>,
|
|
116
|
+
);
|
|
117
|
+
const labelEl = screen.getByText('Plan');
|
|
118
|
+
// A group's accessible-name element must not be a literal <label>.
|
|
119
|
+
expect(labelEl.tagName).toBe('SPAN');
|
|
120
|
+
expect(labelEl.closest('label')).toBeNull();
|
|
121
|
+
expect(labelEl).not.toHaveAttribute('for');
|
|
122
|
+
// labelID is applied to the label element and referenced by the group.
|
|
123
|
+
expect(labelEl).toHaveAttribute('id', 'plan-label');
|
|
124
|
+
const group = screen.getByRole('radiogroup', {name: 'Plan'});
|
|
125
|
+
expect(group.getAttribute('aria-labelledby')).toBe(labelEl.id);
|
|
126
|
+
});
|
|
127
|
+
|
|
96
128
|
it('forwards ref correctly', () => {
|
|
97
129
|
const ref = vi.fn();
|
|
98
130
|
render(
|
package/src/Field/Field.tsx
CHANGED
|
@@ -99,9 +99,26 @@ export interface FieldProps extends Omit<
|
|
|
99
99
|
*/
|
|
100
100
|
description?: string;
|
|
101
101
|
/**
|
|
102
|
-
* ID
|
|
102
|
+
* ID of the input element this label points AT (used as the label's
|
|
103
|
+
* `htmlFor`). This is the id of the *control*, not of the label element —
|
|
104
|
+
* see `labelID` for the latter.
|
|
103
105
|
*/
|
|
104
106
|
inputID: string;
|
|
107
|
+
/**
|
|
108
|
+
* The `id` applied TO the label element itself (distinct from `inputID`,
|
|
109
|
+
* which is the control the label points at). A grouping control
|
|
110
|
+
* (radiogroup, checkbox group) references this via `aria-labelledby` to take
|
|
111
|
+
* the label as its accessible name. Pair with `isGroupLabel`.
|
|
112
|
+
*/
|
|
113
|
+
labelID?: string;
|
|
114
|
+
/**
|
|
115
|
+
* When the field wraps a group of controls rather than a single input, set
|
|
116
|
+
* this so the label renders as a non-`<label>` element (a `<span>`): a
|
|
117
|
+
* `<label>` semantically names one control and can't be associated with a
|
|
118
|
+
* group. Pair with `labelID` + `aria-labelledby` on the group.
|
|
119
|
+
* @default false
|
|
120
|
+
*/
|
|
121
|
+
isGroupLabel?: boolean;
|
|
105
122
|
/**
|
|
106
123
|
* ID for the description element (use for aria-describedby on the input).
|
|
107
124
|
*/
|
|
@@ -172,6 +189,8 @@ export function Field({
|
|
|
172
189
|
isLabelHidden = false,
|
|
173
190
|
description,
|
|
174
191
|
inputID,
|
|
192
|
+
labelID,
|
|
193
|
+
isGroupLabel = false,
|
|
175
194
|
descriptionID,
|
|
176
195
|
isOptional = false,
|
|
177
196
|
isRequired = false,
|
|
@@ -206,6 +225,8 @@ export function Field({
|
|
|
206
225
|
<FieldLabel
|
|
207
226
|
label={label}
|
|
208
227
|
inputID={inputID}
|
|
228
|
+
labelID={labelID}
|
|
229
|
+
isGroupLabel={isGroupLabel}
|
|
209
230
|
isLabelHidden={isLabelHidden}
|
|
210
231
|
isDisabled={isDisabled}
|
|
211
232
|
isOptional={isOptional}
|
|
@@ -245,10 +266,7 @@ export function Field({
|
|
|
245
266
|
<div {...stylex.props(styles.horizontalLabelAlign)}>{labelNode}</div>
|
|
246
267
|
<div {...stylex.props(styles.inputStatusWrapper)}>
|
|
247
268
|
{description && (
|
|
248
|
-
<Text
|
|
249
|
-
type="supporting"
|
|
250
|
-
display="block"
|
|
251
|
-
id={resolvedDescriptionID}>
|
|
269
|
+
<Text type="supporting" display="block" id={resolvedDescriptionID}>
|
|
252
270
|
{description}
|
|
253
271
|
</Text>
|
|
254
272
|
)}
|
package/src/Field/FieldLabel.tsx
CHANGED
|
@@ -35,6 +35,7 @@ const styles = stylex.create({
|
|
|
35
35
|
gap: spacingVars['--spacing-1'],
|
|
36
36
|
fontFamily: typographyVars['--font-family-body'],
|
|
37
37
|
fontSize: typeScaleVars['--text-label-size'],
|
|
38
|
+
lineHeight: typeScaleVars['--text-label-leading'],
|
|
38
39
|
fontWeight: fontWeightVars['--font-weight-medium'],
|
|
39
40
|
color: colorVars['--color-text-secondary'],
|
|
40
41
|
cursor: 'pointer',
|
|
@@ -61,6 +62,7 @@ const styles = stylex.create({
|
|
|
61
62
|
optionalRequired: {
|
|
62
63
|
fontWeight: fontWeightVars['--font-weight-normal'],
|
|
63
64
|
fontSize: typeScaleVars['--text-supporting-size'],
|
|
65
|
+
lineHeight: typeScaleVars['--text-supporting-leading'],
|
|
64
66
|
color: colorVars['--color-text-secondary'],
|
|
65
67
|
},
|
|
66
68
|
description: {
|
|
@@ -80,9 +82,28 @@ export interface FieldLabelProps extends BaseProps<HTMLLabelElement> {
|
|
|
80
82
|
*/
|
|
81
83
|
label: string;
|
|
82
84
|
/**
|
|
83
|
-
* ID of the input element this label
|
|
85
|
+
* ID of the input element this label points AT (rendered as `htmlFor` on the
|
|
86
|
+
* label). This is *not* the id of the label element itself — see
|
|
87
|
+
* `labelID` for that.
|
|
84
88
|
*/
|
|
85
89
|
inputID: string;
|
|
90
|
+
/**
|
|
91
|
+
* The `id` applied TO the label element itself (not the element it points
|
|
92
|
+
* at — that's `inputID`). A grouping control (e.g. `role="radiogroup"`) can
|
|
93
|
+
* reference this via `aria-labelledby` to take the label as its accessible
|
|
94
|
+
* name.
|
|
95
|
+
*/
|
|
96
|
+
labelID?: string;
|
|
97
|
+
/**
|
|
98
|
+
* When true, the field wraps a *group* of controls (e.g. a radiogroup)
|
|
99
|
+
* rather than a single input. In that case the label is rendered as a
|
|
100
|
+
* `<span>` instead of a `<label>` — a `<label>` semantically names one form
|
|
101
|
+
* control and can't be associated with a group, so it must not be a literal
|
|
102
|
+
* label element. The group takes the label as its name via
|
|
103
|
+
* `labelID` + `aria-labelledby`.
|
|
104
|
+
* @default false
|
|
105
|
+
*/
|
|
106
|
+
isGroupLabel?: boolean;
|
|
86
107
|
/**
|
|
87
108
|
* Whether to visually hide the label and description (still accessible
|
|
88
109
|
* to screen readers). When hidden, the entire label group is rendered
|
|
@@ -140,6 +161,8 @@ export interface FieldLabelProps extends BaseProps<HTMLLabelElement> {
|
|
|
140
161
|
export function FieldLabel({
|
|
141
162
|
label,
|
|
142
163
|
inputID,
|
|
164
|
+
labelID,
|
|
165
|
+
isGroupLabel = false,
|
|
143
166
|
isLabelHidden = false,
|
|
144
167
|
isDisabled = false,
|
|
145
168
|
isOptional = false,
|
|
@@ -152,11 +175,38 @@ export function FieldLabel({
|
|
|
152
175
|
}: FieldLabelProps) {
|
|
153
176
|
const statusText = isOptional ? 'Optional' : isRequired ? 'Required' : null;
|
|
154
177
|
|
|
178
|
+
// A group label (e.g. for a radiogroup) must not be a literal `<label>`
|
|
179
|
+
// element: a `<label>` semantically names a single form control and can't be
|
|
180
|
+
// associated with a group. Render it as a `<span>` instead, keeping all the
|
|
181
|
+
// label styling and slots. The group references it via `aria-labelledby`.
|
|
182
|
+
const LabelElement = isGroupLabel ? 'span' : 'label';
|
|
183
|
+
|
|
184
|
+
const labelContent = (
|
|
185
|
+
<>
|
|
186
|
+
{labelIcon && renderIconSlot(labelIcon, {size: 'sm', color: 'inherit'})}
|
|
187
|
+
{label}
|
|
188
|
+
{statusText && (
|
|
189
|
+
<span {...stylex.props(styles.optionalRequired)}>
|
|
190
|
+
<span aria-hidden="true"> ∙ </span>
|
|
191
|
+
{statusText}
|
|
192
|
+
</span>
|
|
193
|
+
)}
|
|
194
|
+
{labelTooltip && (
|
|
195
|
+
<Tooltip content={labelTooltip} placement="above">
|
|
196
|
+
<Icon icon="info" size="sm" color="inherit" />
|
|
197
|
+
</Tooltip>
|
|
198
|
+
)}
|
|
199
|
+
</>
|
|
200
|
+
);
|
|
201
|
+
|
|
155
202
|
return (
|
|
156
203
|
<>
|
|
157
|
-
<
|
|
204
|
+
<LabelElement
|
|
158
205
|
ref={ref}
|
|
159
|
-
|
|
206
|
+
id={labelID}
|
|
207
|
+
// `htmlFor` only applies to a real `<label>` associating with a single
|
|
208
|
+
// control; a group label (span) has no `htmlFor`.
|
|
209
|
+
htmlFor={isGroupLabel ? undefined : inputID}
|
|
160
210
|
{...mergeProps(
|
|
161
211
|
themeProps('field-label'),
|
|
162
212
|
stylex.props(
|
|
@@ -165,20 +215,8 @@ export function FieldLabel({
|
|
|
165
215
|
isLabelHidden && styles.srOnly,
|
|
166
216
|
),
|
|
167
217
|
)}>
|
|
168
|
-
{
|
|
169
|
-
|
|
170
|
-
{statusText && (
|
|
171
|
-
<span {...stylex.props(styles.optionalRequired)}>
|
|
172
|
-
<span aria-hidden="true"> ∙ </span>
|
|
173
|
-
{statusText}
|
|
174
|
-
</span>
|
|
175
|
-
)}
|
|
176
|
-
{labelTooltip && (
|
|
177
|
-
<Tooltip content={labelTooltip} placement="above">
|
|
178
|
-
<Icon icon="info" size="sm" color="inherit" />
|
|
179
|
-
</Tooltip>
|
|
180
|
-
)}
|
|
181
|
-
</label>
|
|
218
|
+
{labelContent}
|
|
219
|
+
</LabelElement>
|
|
182
220
|
{description && (
|
|
183
221
|
<span
|
|
184
222
|
id={descriptionID}
|
|
@@ -88,6 +88,12 @@ export const docs = {
|
|
|
88
88
|
'Disables the input, preventing interaction and dimming the element.',
|
|
89
89
|
default: 'false',
|
|
90
90
|
},
|
|
91
|
+
{
|
|
92
|
+
name: 'disabledMessage',
|
|
93
|
+
type: 'string',
|
|
94
|
+
description:
|
|
95
|
+
'Explains why the input is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the trigger focusable via aria-disabled (opening the file picker stays blocked). Use this instead of wrapping a disabled FileInput in Tooltip — disabled controls swallow the hover events an external Tooltip needs.',
|
|
96
|
+
},
|
|
91
97
|
{
|
|
92
98
|
name: 'isLoading',
|
|
93
99
|
type: 'boolean',
|
|
@@ -135,6 +141,7 @@ export const docs = {
|
|
|
135
141
|
{guidance: true, description: 'Use changeAction for immediate upload workflows that benefit from optimistic UI.'},
|
|
136
142
|
{guidance: false, description: "Don't use FileInput for directory or folder uploads; that is not supported in v1."},
|
|
137
143
|
{guidance: false, description: "Don't avoid dropzone mode unless space is constrained; drag-and-drop is the expected interaction for file uploads."},
|
|
144
|
+
{guidance: false, description: "Don't wrap a disabled FileInput in Tooltip to explain why it's disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead."},
|
|
138
145
|
],
|
|
139
146
|
anatomy: [
|
|
140
147
|
{name: 'Label', required: true, description: 'Text that identifies the field. Always rendered for accessibility even when visually hidden.'},
|
|
@@ -211,6 +218,12 @@ export const docsZh = {
|
|
|
211
218
|
description: '禁用输入框,阻止交互并使元素变暗。',
|
|
212
219
|
default: 'false',
|
|
213
220
|
},
|
|
221
|
+
{
|
|
222
|
+
name: 'disabledMessage',
|
|
223
|
+
type: 'string',
|
|
224
|
+
description:
|
|
225
|
+
'说明输入框被禁用的原因。与 isDisabled 一起使用时,在悬停/键盘聚焦时显示工具提示,并通过 aria-disabled 保持触发器可聚焦(打开文件选择器仍被阻止)。请使用此属性,而不是用 Tooltip 包裹已禁用的 FileInput。',
|
|
226
|
+
},
|
|
214
227
|
{
|
|
215
228
|
name: 'isLoading',
|
|
216
229
|
type: 'boolean',
|
|
@@ -248,6 +261,7 @@ export const docsZh = {
|
|
|
248
261
|
{guidance: true, description: 'Add a description to communicate constraints.'},
|
|
249
262
|
{guidance: false, description: "Don't use FileInput for directory uploads."},
|
|
250
263
|
{guidance: false, description: "Don't use mode='input' unless space is constrained; dropzone mode provides a better experience."},
|
|
264
|
+
{guidance: false, description: "Don't wrap a disabled FileInput in Tooltip to explain the disabled state; use the disabledMessage prop instead."},
|
|
251
265
|
],
|
|
252
266
|
anatomy: [
|
|
253
267
|
{name: 'Label', required: true, description: 'Text identifying the field.'},
|
|
@@ -272,6 +286,7 @@ export const docsDense = {
|
|
|
272
286
|
{guidance: true, description: 'Use changeAction for immediate upload workflows that benefit from optimistic UI.'},
|
|
273
287
|
{guidance: false, description: "Don't use FileInput for directory uploads."},
|
|
274
288
|
{guidance: false, description: "Don't use mode='input' unless space is constrained; dropzone mode provides a better experience."},
|
|
289
|
+
{guidance: false, description: "Don't wrap a disabled FileInput in Tooltip to explain the disabled state; use the disabledMessage prop instead."},
|
|
275
290
|
],
|
|
276
291
|
anatomy: [
|
|
277
292
|
{name: 'Label', required: true, description: 'Text identifying the field.'},
|
|
@@ -295,6 +310,8 @@ export const docsDense = {
|
|
|
295
310
|
isOptional: 'Shows "Optional" indicator.',
|
|
296
311
|
isRequired: 'Shows "Required" indicator+sets aria-required.',
|
|
297
312
|
isDisabled: 'Disables input, prevents interaction.',
|
|
313
|
+
disabledMessage:
|
|
314
|
+
'Explains why input is disabled. With isDisabled, shows tooltip on hover/focus + keeps trigger focusable via aria-disabled (opening picker stays blocked). Use instead of wrapping a disabled FileInput in Tooltip.',
|
|
298
315
|
isLoading: 'Loading state w/ spinner+aria-busy.',
|
|
299
316
|
placeholder: 'Placeholder when no files selected.',
|
|
300
317
|
mode: "Visual mode: 'input' (compact) or 'dropzone' (drag-and-drop).",
|