@usefragments/ui 1.6.0 → 1.7.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 +4 -4
- package/dist/assets/fragments-wordmark.cjs +2 -2
- package/dist/assets/fragments-wordmark.d.ts.map +1 -1
- package/dist/assets/fragments-wordmark.js +2 -2
- package/dist/assets/ui.css +4720 -4159
- package/dist/chart.cjs +24 -6
- package/dist/chart.js +24 -6
- package/dist/codeblock.cjs +55 -29
- package/dist/codeblock.js +55 -29
- package/dist/colorpicker.cjs +3 -1
- package/dist/colorpicker.js +3 -1
- package/dist/components/Accordion/Accordion.module.scss.cjs +8 -8
- package/dist/components/Accordion/Accordion.module.scss.js +8 -8
- package/dist/components/Alert/Alert.module.scss.cjs +15 -12
- package/dist/components/Alert/Alert.module.scss.js +15 -12
- package/dist/components/Alert/index.cjs +7 -1
- package/dist/components/Alert/index.d.ts +12 -6
- package/dist/components/Alert/index.d.ts.map +1 -1
- package/dist/components/Alert/index.js +7 -1
- package/dist/components/AppShell/AppShell.module.scss.cjs +14 -14
- package/dist/components/AppShell/AppShell.module.scss.js +14 -14
- package/dist/components/Avatar/Avatar.module.scss.cjs +14 -14
- package/dist/components/Avatar/Avatar.module.scss.js +14 -14
- package/dist/components/Badge/Badge.module.scss.cjs +19 -19
- package/dist/components/Badge/Badge.module.scss.js +19 -19
- package/dist/components/BentoGrid/BentoGrid.module.scss.cjs +14 -14
- package/dist/components/BentoGrid/BentoGrid.module.scss.js +14 -14
- package/dist/components/Box/Box.module.scss.cjs +152 -152
- package/dist/components/Box/Box.module.scss.js +152 -152
- package/dist/components/Box/index.cjs +64 -75
- package/dist/components/Box/index.d.ts +16 -16
- package/dist/components/Box/index.d.ts.map +1 -1
- package/dist/components/Box/index.js +64 -75
- package/dist/components/Breadcrumbs/Breadcrumbs.module.scss.cjs +8 -8
- package/dist/components/Breadcrumbs/Breadcrumbs.module.scss.js +8 -8
- package/dist/components/Button/Button.module.scss.cjs +14 -14
- package/dist/components/Button/Button.module.scss.js +14 -14
- package/dist/components/Card/Card.module.scss.cjs +29 -17
- package/dist/components/Card/Card.module.scss.js +30 -18
- package/dist/components/Card/index.cjs +8 -0
- package/dist/components/Card/index.d.ts +12 -2
- package/dist/components/Card/index.d.ts.map +1 -1
- package/dist/components/Card/index.js +8 -0
- package/dist/components/Chart/Chart.module.scss.cjs +15 -15
- package/dist/components/Chart/Chart.module.scss.js +15 -15
- package/dist/components/Chart/index.d.ts.map +1 -1
- package/dist/components/Checkbox/Checkbox.module.scss.cjs +9 -9
- package/dist/components/Checkbox/Checkbox.module.scss.js +9 -9
- package/dist/components/Checkbox/index.cjs +2 -2
- package/dist/components/Checkbox/index.d.ts.map +1 -1
- package/dist/components/Checkbox/index.js +2 -2
- package/dist/components/Chip/Chip.module.scss.cjs +15 -15
- package/dist/components/Chip/Chip.module.scss.js +15 -15
- package/dist/components/Chip/index.cjs +2 -1
- package/dist/components/Chip/index.d.ts.map +1 -1
- package/dist/components/Chip/index.js +2 -1
- package/dist/components/CodeBlock/CodeBlock.module.scss.cjs +26 -23
- package/dist/components/CodeBlock/CodeBlock.module.scss.js +26 -23
- package/dist/components/CodeBlock/css-variables-theme.cjs +98 -0
- package/dist/components/CodeBlock/css-variables-theme.d.ts +27 -0
- package/dist/components/CodeBlock/css-variables-theme.d.ts.map +1 -0
- package/dist/components/CodeBlock/css-variables-theme.js +98 -0
- package/dist/components/CodeBlock/index.d.ts +17 -3
- package/dist/components/CodeBlock/index.d.ts.map +1 -1
- package/dist/components/Collapsible/Collapsible.module.scss.cjs +9 -9
- package/dist/components/Collapsible/Collapsible.module.scss.js +9 -9
- package/dist/components/ColorPicker/ColorPicker.module.scss.cjs +14 -14
- package/dist/components/ColorPicker/ColorPicker.module.scss.js +14 -14
- package/dist/components/ColorPicker/index.d.ts.map +1 -1
- package/dist/components/Combobox/Combobox.module.scss.cjs +21 -21
- package/dist/components/Combobox/Combobox.module.scss.js +21 -21
- package/dist/components/Combobox/index.cjs +17 -1
- package/dist/components/Combobox/index.d.ts.map +1 -1
- package/dist/components/Combobox/index.js +17 -1
- package/dist/components/Command/Command.module.scss.cjs +11 -11
- package/dist/components/Command/Command.module.scss.js +11 -11
- package/dist/components/Command/index.cjs +26 -15
- package/dist/components/Command/index.d.ts +2 -2
- package/dist/components/Command/index.d.ts.map +1 -1
- package/dist/components/Command/index.js +26 -15
- package/dist/components/ConversationList/ConversationList.module.scss.cjs +10 -10
- package/dist/components/ConversationList/ConversationList.module.scss.js +10 -10
- package/dist/components/DataTable/DataTable.icons.cjs +6 -33
- package/dist/components/DataTable/DataTable.icons.d.ts.map +1 -1
- package/dist/components/DataTable/DataTable.icons.js +6 -33
- package/dist/components/DataTable/DataTable.module.scss.cjs +27 -27
- package/dist/components/DataTable/DataTable.module.scss.js +27 -27
- package/dist/components/DataTable/index.d.ts.map +1 -1
- package/dist/components/DatePicker/DatePicker.module.scss.cjs +33 -33
- package/dist/components/DatePicker/DatePicker.module.scss.js +33 -33
- package/dist/components/DatePicker/index.d.ts.map +1 -1
- package/dist/components/Dialog/Dialog.module.scss.cjs +14 -14
- package/dist/components/Dialog/Dialog.module.scss.js +14 -14
- package/dist/components/Dialog/index.cjs +11 -14
- package/dist/components/Dialog/index.d.ts +7 -7
- package/dist/components/Dialog/index.d.ts.map +1 -1
- package/dist/components/Dialog/index.js +11 -14
- package/dist/components/Drawer/Drawer.module.scss.cjs +29 -29
- package/dist/components/Drawer/Drawer.module.scss.js +29 -29
- package/dist/components/Editor/Editor.module.scss.cjs +17 -17
- package/dist/components/Editor/Editor.module.scss.js +17 -17
- package/dist/components/Editor/index.d.ts +10 -10
- package/dist/components/Editor/index.d.ts.map +1 -1
- package/dist/components/EmptyState/EmptyState.module.scss.cjs +11 -8
- package/dist/components/EmptyState/EmptyState.module.scss.js +11 -8
- package/dist/components/EmptyState/index.cjs +8 -6
- package/dist/components/EmptyState/index.d.ts +9 -4
- package/dist/components/EmptyState/index.d.ts.map +1 -1
- package/dist/components/EmptyState/index.js +8 -6
- package/dist/components/Field/Field.module.scss.cjs +5 -5
- package/dist/components/Field/Field.module.scss.js +5 -5
- package/dist/components/Field/index.cjs +9 -1
- package/dist/components/Field/index.d.ts.map +1 -1
- package/dist/components/Field/index.js +9 -1
- package/dist/components/Fieldset/Fieldset.module.scss.cjs +3 -3
- package/dist/components/Fieldset/Fieldset.module.scss.js +3 -3
- package/dist/components/Grid/index.cjs +1 -1
- package/dist/components/Grid/index.js +1 -1
- package/dist/components/Header/Header.module.scss.cjs +33 -33
- package/dist/components/Header/Header.module.scss.js +33 -33
- package/dist/components/Header/index.cjs +17 -38
- package/dist/components/Header/index.d.ts +15 -11
- package/dist/components/Header/index.d.ts.map +1 -1
- package/dist/components/Header/index.js +17 -38
- package/dist/components/Icon/Icon.module.scss.cjs +15 -15
- package/dist/components/Icon/Icon.module.scss.js +15 -15
- package/dist/components/IconButton/IconButton.module.scss.cjs +8 -8
- package/dist/components/IconButton/IconButton.module.scss.js +8 -8
- package/dist/components/IconButton/index.cjs +2 -1
- package/dist/components/IconButton/index.d.ts.map +1 -1
- package/dist/components/IconButton/index.js +2 -1
- package/dist/components/Image/Image.module.scss.cjs +27 -27
- package/dist/components/Image/Image.module.scss.js +27 -27
- package/dist/components/Input/Input.module.scss.cjs +17 -17
- package/dist/components/Input/Input.module.scss.js +17 -17
- package/dist/components/Link/Link.module.scss.cjs +14 -10
- package/dist/components/Link/Link.module.scss.js +14 -10
- package/dist/components/Link/index.d.ts +1 -1
- package/dist/components/Link/index.d.ts.map +1 -1
- package/dist/components/List/List.module.scss.cjs +19 -19
- package/dist/components/List/List.module.scss.js +19 -19
- package/dist/components/Listbox/Listbox.module.scss.cjs +8 -8
- package/dist/components/Listbox/Listbox.module.scss.js +8 -8
- package/dist/components/Loading/Loading.module.scss.cjs +34 -34
- package/dist/components/Loading/Loading.module.scss.js +34 -34
- package/dist/components/Loading/index.cjs +1 -1
- package/dist/components/Loading/index.js +1 -1
- package/dist/components/Markdown/Markdown.module.scss.cjs +1 -1
- package/dist/components/Markdown/Markdown.module.scss.js +1 -1
- package/dist/components/Markdown/index.d.ts +2 -2
- package/dist/components/Markdown/index.d.ts.map +1 -1
- package/dist/components/Menu/Menu.module.scss.cjs +14 -14
- package/dist/components/Menu/Menu.module.scss.js +14 -14
- package/dist/components/Message/Message.module.scss.cjs +18 -18
- package/dist/components/Message/Message.module.scss.js +18 -18
- package/dist/components/NavigationMenu/NavigationMenu.module.scss.cjs +34 -31
- package/dist/components/NavigationMenu/NavigationMenu.module.scss.js +34 -31
- package/dist/components/NavigationMenu/index.cjs +32 -15
- package/dist/components/NavigationMenu/index.d.ts +12 -6
- package/dist/components/NavigationMenu/index.d.ts.map +1 -1
- package/dist/components/NavigationMenu/index.js +32 -15
- package/dist/components/Pagination/Pagination.module.scss.cjs +10 -10
- package/dist/components/Pagination/Pagination.module.scss.js +10 -10
- package/dist/components/Popover/Popover.module.scss.cjs +10 -10
- package/dist/components/Popover/Popover.module.scss.js +10 -10
- package/dist/components/Progress/Progress.module.scss.cjs +25 -25
- package/dist/components/Progress/Progress.module.scss.js +25 -25
- package/dist/components/Prompt/Prompt.module.scss.cjs +28 -28
- package/dist/components/Prompt/Prompt.module.scss.js +28 -28
- package/dist/components/RadioGroup/RadioGroup.module.scss.cjs +15 -15
- package/dist/components/RadioGroup/RadioGroup.module.scss.js +15 -15
- package/dist/components/ScrollArea/ScrollArea.module.scss.cjs +5 -5
- package/dist/components/ScrollArea/ScrollArea.module.scss.js +5 -5
- package/dist/components/ScrollArea/index.d.ts +4 -4
- package/dist/components/ScrollArea/index.d.ts.map +1 -1
- package/dist/components/ScrollArea/scroll-state.d.ts +5 -5
- package/dist/components/Select/Select.module.scss.cjs +21 -21
- package/dist/components/Select/Select.module.scss.js +21 -21
- package/dist/components/Separator/Separator.module.scss.cjs +11 -11
- package/dist/components/Separator/Separator.module.scss.js +11 -11
- package/dist/components/Sidebar/Sidebar.module.scss.cjs +43 -43
- package/dist/components/Sidebar/Sidebar.module.scss.js +43 -43
- package/dist/components/Sidebar/index.cjs +12 -35
- package/dist/components/Sidebar/index.d.ts +19 -19
- package/dist/components/Sidebar/index.d.ts.map +1 -1
- package/dist/components/Sidebar/index.js +12 -35
- package/dist/components/Skeleton/Skeleton.module.scss.cjs +50 -46
- package/dist/components/Skeleton/Skeleton.module.scss.js +50 -46
- package/dist/components/Slider/Slider.module.scss.cjs +12 -12
- package/dist/components/Slider/Slider.module.scss.js +12 -12
- package/dist/components/Stack/Stack.module.scss.cjs +25 -25
- package/dist/components/Stack/Stack.module.scss.js +25 -25
- package/dist/components/Stack/index.cjs +1 -1
- package/dist/components/Stack/index.js +1 -1
- package/dist/components/Switch/Switch.module.scss.cjs +9 -9
- package/dist/components/Switch/Switch.module.scss.js +9 -9
- package/dist/components/Table/Table.module.scss.cjs +19 -19
- package/dist/components/Table/Table.module.scss.js +19 -19
- package/dist/components/TableOfContents/TableOfContents.module.scss.cjs +15 -15
- package/dist/components/TableOfContents/TableOfContents.module.scss.js +15 -15
- package/dist/components/TableOfContents/index.cjs +13 -9
- package/dist/components/TableOfContents/index.d.ts +5 -3
- package/dist/components/TableOfContents/index.d.ts.map +1 -1
- package/dist/components/TableOfContents/index.js +13 -9
- package/dist/components/Tabs/Tabs.module.scss.cjs +12 -12
- package/dist/components/Tabs/Tabs.module.scss.js +12 -12
- package/dist/components/Tabs/index.cjs +26 -6
- package/dist/components/Tabs/index.d.ts.map +1 -1
- package/dist/components/Tabs/index.js +26 -6
- package/dist/components/Text/Text.module.scss.cjs +87 -75
- package/dist/components/Text/Text.module.scss.js +87 -75
- package/dist/components/Text/index.cjs +49 -41
- package/dist/components/Text/index.d.ts +12 -11
- package/dist/components/Text/index.d.ts.map +1 -1
- package/dist/components/Text/index.js +49 -41
- package/dist/components/Textarea/Textarea.module.scss.cjs +24 -24
- package/dist/components/Textarea/Textarea.module.scss.js +24 -24
- package/dist/components/Theme/index.cjs +2 -1
- package/dist/components/Theme/index.d.ts.map +1 -1
- package/dist/components/Theme/index.js +2 -1
- package/dist/components/ThemeToggle/ThemeToggle.module.scss.cjs +9 -6
- package/dist/components/ThemeToggle/ThemeToggle.module.scss.js +9 -6
- package/dist/components/ThemeToggle/index.cjs +31 -6
- package/dist/components/ThemeToggle/index.d.ts +7 -2
- package/dist/components/ThemeToggle/index.d.ts.map +1 -1
- package/dist/components/ThemeToggle/index.js +32 -7
- package/dist/components/ThinkingIndicator/ThinkingIndicator.module.scss.cjs +13 -13
- package/dist/components/ThinkingIndicator/ThinkingIndicator.module.scss.js +13 -13
- package/dist/components/Toast/Toast.module.scss.cjs +20 -20
- package/dist/components/Toast/Toast.module.scss.js +20 -20
- package/dist/components/ToggleGroup/ToggleGroup.module.scss.cjs +17 -17
- package/dist/components/ToggleGroup/ToggleGroup.module.scss.js +17 -17
- package/dist/components/Tooltip/Tooltip.module.scss.cjs +3 -3
- package/dist/components/Tooltip/Tooltip.module.scss.js +3 -3
- package/dist/components/Tooltip/index.cjs +24 -40
- package/dist/components/Tooltip/index.d.ts +4 -4
- package/dist/components/Tooltip/index.d.ts.map +1 -1
- package/dist/components/Tooltip/index.js +24 -40
- package/dist/components/VisuallyHidden/index.d.ts +2 -2
- package/dist/data-table.cjs +2 -1
- package/dist/data-table.js +2 -1
- package/dist/datepicker.cjs +3 -2
- package/dist/datepicker.js +3 -2
- package/dist/editor.cjs +68 -28
- package/dist/editor.js +68 -28
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/markdown.cjs +21 -29
- package/dist/markdown.js +21 -29
- package/dist/measurements/generated.cjs +9 -1
- package/dist/measurements/generated.d.ts +7 -0
- package/dist/measurements/generated.d.ts.map +1 -1
- package/dist/measurements/generated.js +9 -1
- package/dist/utils/a11y.cjs +5 -2
- package/dist/utils/a11y.d.ts +5 -5
- package/dist/utils/a11y.d.ts.map +1 -1
- package/dist/utils/a11y.js +5 -2
- package/dist/utils/canonical-stamp.cjs +2 -8
- package/dist/utils/canonical-stamp.d.ts.map +1 -1
- package/dist/utils/canonical-stamp.js +1 -7
- package/dist/utils/css-warning.cjs +1 -1
- package/dist/utils/css-warning.js +1 -1
- package/dist/utils/env.cjs +17 -0
- package/dist/utils/env.d.ts +3 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/env.js +17 -0
- package/dist/utils/keyboard-shortcuts.cjs +3 -10
- package/dist/utils/keyboard-shortcuts.d.ts +4 -4
- package/dist/utils/keyboard-shortcuts.d.ts.map +1 -1
- package/dist/utils/keyboard-shortcuts.js +3 -10
- package/dist/utils/seed-derivation.cjs +10 -6
- package/dist/utils/seed-derivation.d.ts.map +1 -1
- package/dist/utils/seed-derivation.js +10 -6
- package/fragments.json +1 -1
- package/package.json +6 -4
- package/src/assets/fragments-logo.tsx +2 -2
- package/src/assets/fragments-wordmark.tsx +4 -2
- package/src/components/Accordion/Accordion.contract.json +24 -48
- package/src/components/Alert/Alert.contract.json +37 -53
- package/src/components/Alert/Alert.module.scss +24 -0
- package/src/components/Alert/index.tsx +55 -29
- package/src/components/AppShell/AppShell.contract.json +34 -51
- package/src/components/AppShell/AppShell.module.scss +53 -40
- package/src/components/Avatar/Avatar.contract.json +31 -48
- package/src/components/Avatar/Avatar.module.scss +4 -1
- package/src/components/Badge/Badge.contract.json +37 -42
- package/src/components/Badge/Badge.module.scss +9 -2
- package/src/components/BentoGrid/BentoGrid.contract.json +21 -45
- package/src/components/Box/Box.contract.json +40 -148
- package/src/components/Box/index.tsx +92 -99
- package/src/components/Breadcrumbs/Breadcrumbs.contract.json +21 -34
- package/src/components/Breadcrumbs/Breadcrumbs.module.scss +12 -7
- package/src/components/Button/Button.module.scss +8 -7
- package/src/components/ButtonGroup/ButtonGroup.contract.json +32 -47
- package/src/components/Card/Card.module.scss +82 -1
- package/src/components/Card/index.tsx +21 -2
- package/src/components/Chart/Chart.contract.json +21 -29
- package/src/components/Chart/index.tsx +36 -6
- package/src/components/Checkbox/Checkbox.contract.json +24 -24
- package/src/components/Checkbox/Checkbox.module.scss +32 -23
- package/src/components/Checkbox/index.tsx +4 -2
- package/src/components/Chip/Chip.contract.json +33 -40
- package/src/components/Chip/Chip.module.scss +2 -2
- package/src/components/Chip/index.tsx +2 -1
- package/src/components/CodeBlock/CodeBlock.contract.json +46 -76
- package/src/components/CodeBlock/CodeBlock.module.scss +40 -15
- package/src/components/CodeBlock/css-variables-theme.ts +102 -0
- package/src/components/CodeBlock/index.tsx +91 -35
- package/src/components/Collapsible/Collapsible.contract.json +21 -36
- package/src/components/ColorPicker/ColorPicker.contract.json +29 -48
- package/src/components/ColorPicker/ColorPicker.module.scss +15 -12
- package/src/components/ColorPicker/index.tsx +5 -1
- package/src/components/Combobox/Combobox.contract.json +36 -37
- package/src/components/Combobox/Combobox.module.scss +1 -1
- package/src/components/Combobox/index.tsx +31 -5
- package/src/components/Command/Command.contract.json +21 -43
- package/src/components/Command/index.tsx +58 -47
- package/src/components/ConversationList/ConversationList.contract.json +27 -32
- package/src/components/DataTable/DataTable.icons.tsx +4 -21
- package/src/components/DataTable/DataTable.module.scss +12 -8
- package/src/components/DataTable/index.tsx +8 -7
- package/src/components/DatePicker/DatePicker.contract.json +27 -28
- package/src/components/DatePicker/DatePicker.module.scss +12 -5
- package/src/components/DatePicker/index.tsx +5 -2
- package/src/components/Dialog/Dialog.module.scss +3 -3
- package/src/components/Dialog/index.tsx +47 -37
- package/src/components/Drawer/Drawer.contract.json +22 -36
- package/src/components/Editor/Editor.contract.json +31 -48
- package/src/components/Editor/Editor.module.scss +36 -14
- package/src/components/Editor/index.tsx +240 -179
- package/src/components/EmptyState/EmptyState.contract.json +31 -43
- package/src/components/EmptyState/EmptyState.module.scss +8 -0
- package/src/components/EmptyState/index.tsx +48 -23
- package/src/components/Field/Field.contract.json +28 -46
- package/src/components/Field/index.tsx +5 -1
- package/src/components/Fieldset/Fieldset.contract.json +21 -38
- package/src/components/Fieldset/Fieldset.module.scss +10 -3
- package/src/components/Form/Form.contract.json +20 -20
- package/src/components/Grid/Grid.contract.json +28 -64
- package/src/components/Grid/index.tsx +10 -10
- package/src/components/Header/Header.contract.json +31 -67
- package/src/components/Header/Header.module.scss +36 -21
- package/src/components/Header/index.tsx +134 -122
- package/src/components/Icon/Icon.contract.json +22 -62
- package/src/components/IconButton/IconButton.contract.json +34 -18
- package/src/components/IconButton/IconButton.module.scss +6 -7
- package/src/components/IconButton/index.tsx +2 -1
- package/src/components/Image/Image.contract.json +23 -56
- package/src/components/Input/Input.contract.json +26 -32
- package/src/components/Input/Input.module.scss +3 -2
- package/src/components/Link/Link.contract.json +32 -52
- package/src/components/Link/Link.module.scss +23 -6
- package/src/components/Link/index.tsx +1 -1
- package/src/components/List/List.contract.json +23 -52
- package/src/components/List/List.module.scss +1 -1
- package/src/components/Listbox/Listbox.contract.json +21 -37
- package/src/components/Loading/Loading.contract.json +37 -61
- package/src/components/Loading/Loading.module.scss +10 -7
- package/src/components/Loading/index.tsx +2 -2
- package/src/components/Main/Main.contract.json +17 -9
- package/src/components/Markdown/Markdown.contract.json +22 -43
- package/src/components/Markdown/Markdown.module.scss +43 -5
- package/src/components/Markdown/index.tsx +48 -49
- package/src/components/Menu/Menu.contract.json +25 -41
- package/src/components/Menu/Menu.module.scss +23 -8
- package/src/components/Message/Message.contract.json +29 -52
- package/src/components/Message/Message.module.scss +12 -5
- package/src/components/NavigationMenu/NavigationMenu.contract.json +36 -45
- package/src/components/NavigationMenu/NavigationMenu.module.scss +64 -19
- package/src/components/NavigationMenu/index.tsx +105 -81
- package/src/components/Pagination/Pagination.contract.json +22 -40
- package/src/components/Pagination/Pagination.module.scss +2 -2
- package/src/components/Popover/Popover.contract.json +24 -46
- package/src/components/Popover/Popover.module.scss +6 -5
- package/src/components/Progress/Progress.contract.json +32 -28
- package/src/components/Progress/Progress.module.scss +3 -2
- package/src/components/Prompt/Prompt.contract.json +31 -47
- package/src/components/Prompt/Prompt.module.scss +13 -5
- package/src/components/RadioGroup/RadioGroup.contract.json +23 -24
- package/src/components/RadioGroup/RadioGroup.module.scss +13 -14
- package/src/components/ScrollArea/ScrollArea.contract.json +18 -19
- package/src/components/ScrollArea/ScrollArea.module.scss +15 -15
- package/src/components/ScrollArea/index.tsx +16 -16
- package/src/components/ScrollArea/scroll-state.ts +24 -24
- package/src/components/Select/Select.module.scss +2 -2
- package/src/components/Separator/Separator.contract.json +24 -48
- package/src/components/Sidebar/Sidebar.contract.json +35 -67
- package/src/components/Sidebar/Sidebar.module.scss +22 -13
- package/src/components/Sidebar/index.tsx +164 -164
- package/src/components/Skeleton/Skeleton.contract.json +28 -54
- package/src/components/Skeleton/Skeleton.module.scss +27 -10
- package/src/components/Slider/Slider.contract.json +27 -39
- package/src/components/Slider/Slider.module.scss +3 -3
- package/src/components/Stack/Stack.contract.json +29 -56
- package/src/components/Stack/Stack.module.scss +13 -12
- package/src/components/Stack/index.tsx +3 -3
- package/src/components/Switch/Switch.contract.json +33 -46
- package/src/components/Switch/Switch.module.scss +64 -26
- package/src/components/Table/Table.contract.json +28 -46
- package/src/components/Table/Table.module.scss +15 -3
- package/src/components/TableOfContents/TableOfContents.contract.json +34 -21
- package/src/components/TableOfContents/TableOfContents.module.scss +15 -5
- package/src/components/TableOfContents/index.tsx +26 -9
- package/src/components/Tabs/Tabs.contract.json +24 -45
- package/src/components/Tabs/Tabs.module.scss +1 -1
- package/src/components/Tabs/index.tsx +15 -3
- package/src/components/Text/Text.contract.json +30 -72
- package/src/components/Text/Text.module.scss +21 -4
- package/src/components/Text/index.tsx +113 -75
- package/src/components/Textarea/Textarea.contract.json +25 -43
- package/src/components/Textarea/Textarea.module.scss +2 -4
- package/src/components/Theme/Theme.contract.json +32 -51
- package/src/components/Theme/index.tsx +2 -1
- package/src/components/ThemeToggle/ThemeToggle.module.scss +23 -7
- package/src/components/ThemeToggle/index.tsx +43 -7
- package/src/components/ThinkingIndicator/ThinkingIndicator.contract.json +23 -40
- package/src/components/Toast/Toast.contract.json +30 -40
- package/src/components/Toast/Toast.module.scss +1 -1
- package/src/components/ToggleGroup/ToggleGroup.contract.json +29 -30
- package/src/components/ToggleGroup/ToggleGroup.module.scss +38 -5
- package/src/components/Tooltip/Tooltip.contract.json +31 -52
- package/src/components/Tooltip/index.tsx +19 -24
- package/src/components/VisuallyHidden/VisuallyHidden.contract.json +22 -44
- package/src/components/VisuallyHidden/index.tsx +5 -5
- package/src/index.ts +2 -2
- package/src/measurements/generated.ts +9 -2
- package/src/measurements/measurements.json +7 -0
- package/src/recipes/_boolean-range.scss +3 -11
- package/src/recipes/_field.scss +5 -1
- package/src/recipes/_layout.scss +14 -7
- package/src/recipes/_popup.scss +12 -2
- package/src/recipes/_prose.scss +13 -5
- package/src/recipes/_table-chrome.scss +16 -2
- package/src/scss.d.ts +1 -1
- package/src/styles/globals.scss +20 -19
- package/src/tokens/_computed.scss +5 -16
- package/src/tokens/_derive.scss +112 -210
- package/src/tokens/_measurements.catalog.generated.css +6 -1
- package/src/tokens/_measurements.generated.scss +14 -1
- package/src/tokens/_mixins.scss +7 -8
- package/src/tokens/_palettes.scss +39 -167
- package/src/tokens/_seeds.scss +20 -20
- package/src/tokens/_variables.scss +183 -38
- package/src/utils/a11y.tsx +69 -69
- package/src/utils/aria.ts +3 -3
- package/src/utils/canonical-stamp.ts +2 -12
- package/src/utils/css-warning.ts +7 -7
- package/src/utils/env.ts +25 -0
- package/src/utils/keyboard-shortcuts.ts +131 -126
- package/src/utils/seed-derivation.ts +10 -6
- package/src/components/Button/Button.contract.json +0 -218
- package/src/components/Card/Card.contract.json +0 -175
- package/src/components/DataTable/DataTable.contract.json +0 -302
- package/src/components/Dialog/Dialog.contract.json +0 -159
- package/src/components/Select/Select.contract.json +0 -259
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://usefragments.com/schemas/contract.v1.json",
|
|
3
3
|
"name": "Combobox",
|
|
4
|
-
"description": "
|
|
5
|
-
"category": "
|
|
4
|
+
"description": "Filters a list of options as the user types.",
|
|
5
|
+
"category": "inputs",
|
|
6
6
|
"tags": ["combobox", "autocomplete", "search", "select", "typeahead", "form", "multiselect"],
|
|
7
7
|
"status": "stable",
|
|
8
8
|
"sourcePath": "src/components/Combobox/index.tsx",
|
|
@@ -133,86 +133,85 @@
|
|
|
133
133
|
},
|
|
134
134
|
"usage": {
|
|
135
135
|
"when": [
|
|
136
|
-
"
|
|
137
|
-
"
|
|
138
|
-
"
|
|
139
|
-
"
|
|
140
|
-
"Multiple selections from a searchable list"
|
|
136
|
+
"Lists too long to scan by eye",
|
|
137
|
+
"The user roughly knows the value they want",
|
|
138
|
+
"Autocomplete or typeahead",
|
|
139
|
+
"Multi-select from a searchable list"
|
|
141
140
|
],
|
|
142
141
|
"whenNot": [
|
|
143
|
-
"
|
|
144
|
-
"Free-form text with no
|
|
145
|
-
"
|
|
146
|
-
"Actions
|
|
142
|
+
"Under five options (use Select or RadioGroup)",
|
|
143
|
+
"Free-form text with no known options (use Input)",
|
|
144
|
+
"Short list nobody needs to search (use Select)",
|
|
145
|
+
"Actions rather than values (use Menu)"
|
|
147
146
|
],
|
|
148
147
|
"guidelines": [
|
|
149
|
-
"
|
|
150
|
-
"
|
|
151
|
-
"
|
|
152
|
-
"
|
|
153
|
-
"Group related options with Combobox.Group
|
|
154
|
-
"
|
|
155
|
-
"Keep option text
|
|
156
|
-
"
|
|
148
|
+
"Placeholder names what is searchable",
|
|
149
|
+
"Set label so the field is announced",
|
|
150
|
+
"helperText for guidance, error for the failure reason",
|
|
151
|
+
"Override the built-in \"No results found\" with Combobox.Empty when you have better wording",
|
|
152
|
+
"Group related options with Combobox.Group in long lists",
|
|
153
|
+
"Filtering keeps wrapper composition, so groups and fragments survive",
|
|
154
|
+
"Keep option text short and searchable",
|
|
155
|
+
"multiple turns selections into removable chips"
|
|
157
156
|
],
|
|
158
157
|
"accessibility": [
|
|
159
|
-
"
|
|
160
|
-
"
|
|
161
|
-
"
|
|
162
|
-
"
|
|
163
|
-
"
|
|
158
|
+
"Arrow keys, Enter, and Escape all work",
|
|
159
|
+
"Typing filters the list in place",
|
|
160
|
+
"Correct ARIA combobox roles and attributes",
|
|
161
|
+
"Filtered result counts are announced",
|
|
162
|
+
"Chips can be removed from the keyboard"
|
|
164
163
|
]
|
|
165
164
|
},
|
|
166
165
|
"examples": [
|
|
167
166
|
{
|
|
168
167
|
"name": "Default",
|
|
169
|
-
"description": "
|
|
168
|
+
"description": "Type to narrow the list; unmatched queries show a no-results row.",
|
|
170
169
|
"code": "<StatefulCombobox placeholder=\"Select a fruit\">\n <Combobox.Input />\n <Combobox.Content>\n <Combobox.Item value=\"apple\">Apple</Combobox.Item>\n <Combobox.Item value=\"banana\">Banana</Combobox.Item>\n <Combobox.Item value=\"orange\">Orange</Combobox.Item>\n <Combobox.Item value=\"grape\">Grape</Combobox.Item>\n </Combobox.Content>\n</StatefulCombobox>"
|
|
171
170
|
},
|
|
172
171
|
{
|
|
173
172
|
"name": "Multiple Selection",
|
|
174
|
-
"description": "
|
|
173
|
+
"description": "Each pick becomes a removable chip in the field.",
|
|
175
174
|
"code": "<StatefulCombobox multiple placeholder=\"Select fruits...\">\n <Combobox.Input />\n <Combobox.Content>\n <Combobox.Item value=\"apple\">Apple</Combobox.Item>\n <Combobox.Item value=\"banana\">Banana</Combobox.Item>\n <Combobox.Item value=\"orange\">Orange</Combobox.Item>\n <Combobox.Item value=\"grape\">Grape</Combobox.Item>\n <Combobox.Item value=\"mango\">Mango</Combobox.Item>\n <Combobox.Item value=\"kiwi\">Kiwi</Combobox.Item>\n </Combobox.Content>\n</StatefulCombobox>"
|
|
176
175
|
},
|
|
177
176
|
{
|
|
178
177
|
"name": "With Label and Helper Text",
|
|
179
|
-
"description": "
|
|
178
|
+
"description": "Helper text tells the user the field is searchable.",
|
|
180
179
|
"code": "<StatefulCombobox\n label=\"Assignee\"\n placeholder=\"Search assignees...\"\n helperText=\"Type to filter the list of available assignees.\"\n>\n <Combobox.Input />\n <Combobox.Content>\n <Combobox.Empty>No matches</Combobox.Empty>\n <Combobox.Item value=\"alice\">Alice Johnson</Combobox.Item>\n <Combobox.Item value=\"bob\">Bob Chen</Combobox.Item>\n <Combobox.Item value=\"carol\">Carol Smith</Combobox.Item>\n </Combobox.Content>\n</StatefulCombobox>"
|
|
181
180
|
},
|
|
182
181
|
{
|
|
183
182
|
"name": "Error State",
|
|
184
|
-
"description": "
|
|
185
|
-
"code": "<Combobox\n label=\"Reviewer\"\n placeholder=\"Search reviewers...\"\n error=\"Please select a reviewer\"\n
|
|
183
|
+
"description": "Red border, and the message replaces helper text.",
|
|
184
|
+
"code": "<Combobox\n label=\"Reviewer\"\n placeholder=\"Search reviewers...\"\n error=\"Please select a reviewer\"\n>\n <Combobox.Input />\n <Combobox.Content>\n <Combobox.Item value=\"alice\">Alice</Combobox.Item>\n </Combobox.Content>\n</Combobox>"
|
|
186
185
|
},
|
|
187
186
|
{
|
|
188
187
|
"name": "With Groups",
|
|
189
|
-
"description": "
|
|
188
|
+
"description": "Headed sections stay intact while filtering.",
|
|
190
189
|
"code": "<StatefulCombobox placeholder=\"Search countries...\">\n <Combobox.Input />\n <Combobox.Content>\n <>\n <Combobox.Group>\n <Combobox.GroupLabel>North America</Combobox.GroupLabel>\n <Combobox.Item value=\"us\">United States</Combobox.Item>\n <Combobox.Item value=\"ca\">Canada</Combobox.Item>\n <Combobox.Item value=\"mx\">Mexico</Combobox.Item>\n </Combobox.Group>\n <Combobox.Group>\n <Combobox.GroupLabel>Europe</Combobox.GroupLabel>\n <Combobox.Item value=\"uk\">United Kingdom</Combobox.Item>\n <Combobox.Item value=\"de\">Germany</Combobox.Item>\n <Combobox.Item value=\"fr\">France</Combobox.Item>\n </Combobox.Group>\n <Combobox.Empty>No matching country</Combobox.Empty>\n </>\n </Combobox.Content>\n</StatefulCombobox>"
|
|
191
190
|
},
|
|
192
191
|
{
|
|
193
192
|
"name": "With Empty State",
|
|
194
|
-
"description": "
|
|
195
|
-
"code": "<StatefulCombobox placeholder=\"
|
|
193
|
+
"description": "Combobox.Empty replaces the default no-results wording.",
|
|
194
|
+
"code": "<StatefulCombobox placeholder=\"Filter languages...\">\n <Combobox.Input />\n <Combobox.Content>\n <Combobox.Empty>No language matches that search</Combobox.Empty>\n <Combobox.Item value=\"js\">JavaScript</Combobox.Item>\n <Combobox.Item value=\"ts\">TypeScript</Combobox.Item>\n <Combobox.Item value=\"py\">Python</Combobox.Item>\n <Combobox.Item value=\"rs\">Rust</Combobox.Item>\n <Combobox.Item value=\"go\">Go</Combobox.Item>\n </Combobox.Content>\n</StatefulCombobox>"
|
|
196
195
|
},
|
|
197
196
|
{
|
|
198
197
|
"name": "Scrollable List",
|
|
199
|
-
"description": "
|
|
198
|
+
"description": "Caps at four rows and half-shows the fifth as a scroll hint.",
|
|
200
199
|
"code": "<StatefulCombobox placeholder=\"Search languages...\">\n <Combobox.Input />\n <Combobox.Content>\n <Combobox.Empty>No results found</Combobox.Empty>\n <Combobox.Item value=\"js\">JavaScript</Combobox.Item>\n <Combobox.Item value=\"ts\">TypeScript</Combobox.Item>\n <Combobox.Item value=\"py\">Python</Combobox.Item>\n <Combobox.Item value=\"rs\">Rust</Combobox.Item>\n <Combobox.Item value=\"go\">Go</Combobox.Item>\n <Combobox.Item value=\"rb\">Ruby</Combobox.Item>\n <Combobox.Item value=\"java\">Java</Combobox.Item>\n <Combobox.Item value=\"swift\">Swift</Combobox.Item>\n <Combobox.Item value=\"kt\">Kotlin</Combobox.Item>\n <Combobox.Item value=\"cpp\">C++</Combobox.Item>\n </Combobox.Content>\n</StatefulCombobox>"
|
|
201
200
|
},
|
|
202
201
|
{
|
|
203
202
|
"name": "Custom Max Visible Items",
|
|
204
|
-
"description": "
|
|
203
|
+
"description": "maxVisibleItems raises the cap to six rows.",
|
|
205
204
|
"code": "<StatefulCombobox placeholder=\"Search cities...\">\n <Combobox.Input />\n <Combobox.Content maxVisibleItems={6}>\n <Combobox.Empty>No results found</Combobox.Empty>\n <Combobox.Item value=\"nyc\">New York</Combobox.Item>\n <Combobox.Item value=\"lon\">London</Combobox.Item>\n <Combobox.Item value=\"tok\">Tokyo</Combobox.Item>\n <Combobox.Item value=\"par\">Paris</Combobox.Item>\n <Combobox.Item value=\"syd\">Sydney</Combobox.Item>\n <Combobox.Item value=\"ber\">Berlin</Combobox.Item>\n <Combobox.Item value=\"tor\">Toronto</Combobox.Item>\n <Combobox.Item value=\"sin\">Singapore</Combobox.Item>\n <Combobox.Item value=\"dub\">Dubai</Combobox.Item>\n <Combobox.Item value=\"sao\">São Paulo</Combobox.Item>\n </Combobox.Content>\n</StatefulCombobox>"
|
|
206
205
|
},
|
|
207
206
|
{
|
|
208
207
|
"name": "Disabled",
|
|
209
|
-
"description": "
|
|
208
|
+
"description": "Dimmed and unfocusable.",
|
|
210
209
|
"code": "<Combobox disabled placeholder=\"Search...\">\n <Combobox.Input />\n <Combobox.Content>\n <Combobox.Item value=\"1\">Option 1</Combobox.Item>\n </Combobox.Content>\n</Combobox>"
|
|
211
210
|
},
|
|
212
211
|
{
|
|
213
212
|
"name": "Explicit Trigger",
|
|
214
|
-
"description": "
|
|
215
|
-
"code": "<StatefulCombobox placeholder=\"Search assignees...\">\n <Combobox.Input showTrigger={false} />\n
|
|
213
|
+
"description": "showTrigger={false} hands the open control to your own Combobox.Trigger.",
|
|
214
|
+
"code": "<StatefulCombobox placeholder=\"Search assignees...\">\n <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>\n <Combobox.Input showTrigger={false} />\n <Combobox.Trigger aria-label=\"Open assignee list\" />\n </div>\n <Combobox.Content>\n <Combobox.Item value=\"alice\">Alice</Combobox.Item>\n <Combobox.Item value=\"bob\">Bob</Combobox.Item>\n <Combobox.Item value=\"carol\">Carol</Combobox.Item>\n </Combobox.Content>\n</StatefulCombobox>"
|
|
216
215
|
}
|
|
217
216
|
],
|
|
218
217
|
"relations": [
|
|
@@ -4,10 +4,7 @@ import * as React from "react";
|
|
|
4
4
|
import { Combobox as BaseCombobox } from "@base-ui/react/combobox";
|
|
5
5
|
import { useResolvedControlSize } from "../ComponentDefaults";
|
|
6
6
|
import { mergeAriaIds, useFormFieldIds, type FormFieldProps } from "../../utils/aria";
|
|
7
|
-
import {
|
|
8
|
-
POPUP_OFFSET_PX,
|
|
9
|
-
resolvePopupViewportRows,
|
|
10
|
-
} from "../../recipes/popup";
|
|
7
|
+
import { POPUP_OFFSET_PX, resolvePopupViewportRows } from "../../recipes/popup";
|
|
11
8
|
import styles from "./Combobox.module.scss";
|
|
12
9
|
|
|
13
10
|
// ============================================
|
|
@@ -293,6 +290,27 @@ function filterStaticChildren(
|
|
|
293
290
|
};
|
|
294
291
|
}
|
|
295
292
|
|
|
293
|
+
/**
|
|
294
|
+
* True when the consumer already supplied a `Combobox.Empty` slot anywhere in
|
|
295
|
+
* the content. Used to decide whether the built-in "no results" fallback is
|
|
296
|
+
* needed — without it an unmatched query renders an empty, collapsed popup.
|
|
297
|
+
*/
|
|
298
|
+
function containsEmptySlot(node: React.ReactNode): boolean {
|
|
299
|
+
let found = false;
|
|
300
|
+
React.Children.forEach(node, (child) => {
|
|
301
|
+
if (found || !React.isValidElement(child)) return;
|
|
302
|
+
if (child.type === ComboboxEmpty) {
|
|
303
|
+
found = true;
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
const props = child.props as { children?: React.ReactNode };
|
|
307
|
+
if (props.children !== undefined && containsEmptySlot(props.children)) {
|
|
308
|
+
found = true;
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
return found;
|
|
312
|
+
}
|
|
313
|
+
|
|
296
314
|
// ============================================
|
|
297
315
|
// Components
|
|
298
316
|
// ============================================
|
|
@@ -631,6 +649,14 @@ function ComboboxContent({
|
|
|
631
649
|
() => filterStaticChildren(children, visibleValues),
|
|
632
650
|
[children, visibleValues]
|
|
633
651
|
);
|
|
652
|
+
// No matches and no author-supplied empty slot would leave a bare, collapsed
|
|
653
|
+
// popup, so fall back to a readable "no results" row.
|
|
654
|
+
const popupChildren =
|
|
655
|
+
filteredContent.visibleItemCount === 0 && !containsEmptySlot(children) ? (
|
|
656
|
+
<ComboboxEmpty>No results found</ComboboxEmpty>
|
|
657
|
+
) : (
|
|
658
|
+
filteredContent.children
|
|
659
|
+
);
|
|
634
660
|
|
|
635
661
|
const popupStyle =
|
|
636
662
|
maxVisibleItems != null
|
|
@@ -650,7 +676,7 @@ function ComboboxContent({
|
|
|
650
676
|
>
|
|
651
677
|
<BaseCombobox.Popup {...htmlProps} className={popupClasses} style={popupStyle}>
|
|
652
678
|
<ComboboxFilteredItemIndexContext.Provider value={filteredItemIndices}>
|
|
653
|
-
{
|
|
679
|
+
{popupChildren}
|
|
654
680
|
</ComboboxFilteredItemIndexContext.Provider>
|
|
655
681
|
</BaseCombobox.Popup>
|
|
656
682
|
</BaseCombobox.Positioner>
|
|
@@ -1,16 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://usefragments.com/schemas/contract.v1.json",
|
|
3
3
|
"name": "Command",
|
|
4
|
-
"description": "
|
|
4
|
+
"description": "Filters a list of actions as the user types.",
|
|
5
5
|
"category": "navigation",
|
|
6
|
-
"tags": [
|
|
7
|
-
"command",
|
|
8
|
-
"palette",
|
|
9
|
-
"search",
|
|
10
|
-
"spotlight",
|
|
11
|
-
"quick-actions",
|
|
12
|
-
"cmdk"
|
|
13
|
-
],
|
|
6
|
+
"tags": ["command", "palette", "search", "spotlight", "quick-actions", "cmdk"],
|
|
14
7
|
"status": "stable",
|
|
15
8
|
"sourcePath": "src/components/Command/index.tsx",
|
|
16
9
|
"exportName": "Command",
|
|
@@ -58,23 +51,22 @@
|
|
|
58
51
|
},
|
|
59
52
|
"usage": {
|
|
60
53
|
"when": [
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"Inline
|
|
64
|
-
"
|
|
54
|
+
"A keyboard shortcut that jumps anywhere",
|
|
55
|
+
"Action lists too long to scan",
|
|
56
|
+
"Inline lists that need filtering",
|
|
57
|
+
"Search across everything the app can do"
|
|
65
58
|
],
|
|
66
59
|
"whenNot": [
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"Search with complex result types (build custom)"
|
|
60
|
+
"A handful of actions (use Menu)",
|
|
61
|
+
"Picking a value for a form (use Select or Combobox)",
|
|
62
|
+
"Fixed navigation (use Sidebar or Tabs)"
|
|
71
63
|
],
|
|
72
64
|
"guidelines": [
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
65
|
+
"Wrap in Dialog for the summon-anywhere palette",
|
|
66
|
+
"Group by category once the list gets long",
|
|
67
|
+
"Always supply Command.Empty",
|
|
68
|
+
"Add keywords so aliases and synonyms match",
|
|
69
|
+
"Label rows with a verb"
|
|
78
70
|
],
|
|
79
71
|
"accessibility": [
|
|
80
72
|
"Uses combobox + listbox ARIA pattern",
|
|
@@ -86,22 +78,22 @@
|
|
|
86
78
|
"examples": [
|
|
87
79
|
{
|
|
88
80
|
"name": "Default",
|
|
89
|
-
"description": "
|
|
81
|
+
"description": "Search field over a flat list.",
|
|
90
82
|
"code": "<div style={{ maxWidth: '400px', width: '100%' }}>\n <Command>\n <Command.Input placeholder=\"Type a command...\" />\n <Command.List>\n <Command.Item onItemSelect={() => {}}>Open File</Command.Item>\n <Command.Item onItemSelect={() => {}}>Save Document</Command.Item>\n <Command.Item onItemSelect={() => {}}>Print</Command.Item>\n <Command.Empty>No results found.</Command.Empty>\n </Command.List>\n </Command>\n</div>"
|
|
91
83
|
},
|
|
92
84
|
{
|
|
93
85
|
"name": "Dialog Command Palette",
|
|
94
|
-
"description": "
|
|
86
|
+
"description": "The same list summoned over the page.",
|
|
95
87
|
"code": "<Dialog>\n <Dialog.Trigger asChild>\n <Button variant=\"secondary\">Open Command Palette</Button>\n </Dialog.Trigger>\n <Dialog.Content size=\"sm\">\n <Command>\n <Command.Input placeholder=\"Search commands...\" />\n <Command.List>\n <Command.Group heading=\"Actions\">\n <Command.Item onItemSelect={() => {}}>New File</Command.Item>\n <Command.Item onItemSelect={() => {}}>Open Recent</Command.Item>\n </Command.Group>\n <Command.Separator />\n <Command.Group heading=\"Settings\">\n <Command.Item onItemSelect={() => {}}>Preferences</Command.Item>\n <Command.Item onItemSelect={() => {}}>Keyboard Shortcuts</Command.Item>\n </Command.Group>\n <Command.Empty>No results found.</Command.Empty>\n </Command.List>\n </Command>\n </Dialog.Content>\n</Dialog>"
|
|
96
88
|
},
|
|
97
89
|
{
|
|
98
90
|
"name": "With Groups",
|
|
99
|
-
"description": "
|
|
91
|
+
"description": "Category labels survive filtering.",
|
|
100
92
|
"code": "<div style={{ maxWidth: '400px', width: '100%' }}>\n <Command>\n <Command.Input placeholder=\"Search...\" />\n <Command.List>\n <Command.Group heading=\"Suggestions\">\n <Command.Item onItemSelect={() => {}}>Calendar</Command.Item>\n <Command.Item onItemSelect={() => {}}>Calculator</Command.Item>\n </Command.Group>\n <Command.Separator />\n <Command.Group heading=\"Settings\">\n <Command.Item onItemSelect={() => {}}>Profile</Command.Item>\n <Command.Item onItemSelect={() => {}}>Billing</Command.Item>\n <Command.Item disabled onItemSelect={() => {}}>\n Team (coming soon)\n </Command.Item>\n </Command.Group>\n <Command.Empty>No results found.</Command.Empty>\n </Command.List>\n </Command>\n</div>"
|
|
101
93
|
},
|
|
102
94
|
{
|
|
103
95
|
"name": "With Icons",
|
|
104
|
-
"description": "
|
|
96
|
+
"description": "Leading glyphs speed up scanning.",
|
|
105
97
|
"code": "<div style={{ maxWidth: '400px', width: '100%' }}>\n <Command>\n <Command.Input placeholder=\"What do you need?\" />\n <Command.List>\n <Command.Item onItemSelect={() => {}}>\n <span style={{ marginRight: '0.5rem', fontSize: '1rem' }}>+</span> New Document\n </Command.Item>\n <Command.Item onItemSelect={() => {}}>\n <span style={{ marginRight: '0.5rem', fontSize: '1rem' }}>{'>'}</span> Open Folder\n </Command.Item>\n <Command.Item onItemSelect={() => {}}>\n <span style={{ marginRight: '0.5rem', fontSize: '1rem' }}>?</span> Search\n </Command.Item>\n <Command.Empty>No results found.</Command.Empty>\n </Command.List>\n </Command>\n</div>"
|
|
106
98
|
}
|
|
107
99
|
],
|
|
@@ -132,26 +124,12 @@
|
|
|
132
124
|
"Command.Item keywords: string[] - extra filter terms",
|
|
133
125
|
"Command.Item onItemSelect: (value, event) => void - selection handler"
|
|
134
126
|
],
|
|
135
|
-
"a11yRules": [
|
|
136
|
-
"A11Y_COMBOBOX_ROLE",
|
|
137
|
-
"A11Y_LISTBOX_ROLE",
|
|
138
|
-
"A11Y_ACTIVE_DESCENDANT"
|
|
139
|
-
]
|
|
127
|
+
"a11yRules": ["A11Y_COMBOBOX_ROLE", "A11Y_LISTBOX_ROLE", "A11Y_ACTIVE_DESCENDANT"]
|
|
140
128
|
},
|
|
141
129
|
"ai": {
|
|
142
130
|
"compositionPattern": "compound",
|
|
143
|
-
"subComponents": [
|
|
144
|
-
|
|
145
|
-
"List",
|
|
146
|
-
"Item",
|
|
147
|
-
"Group",
|
|
148
|
-
"Empty",
|
|
149
|
-
"Separator"
|
|
150
|
-
],
|
|
151
|
-
"requiredChildren": [
|
|
152
|
-
"Input",
|
|
153
|
-
"List"
|
|
154
|
-
],
|
|
131
|
+
"subComponents": ["Input", "List", "Item", "Group", "Empty", "Separator"],
|
|
132
|
+
"requiredChildren": ["Input", "List"],
|
|
155
133
|
"commonPatterns": [
|
|
156
134
|
"<Dialog><Dialog.Trigger><Button>Open Palette</Button></Dialog.Trigger><Dialog.Content size=\"sm\"><Command><Command.Input placeholder=\"Search...\" /><Command.List><Command.Group heading=\"Actions\"><Command.Item onItemSelect={() => {}}>Action 1</Command.Item></Command.Group><Command.Empty>No results.</Command.Empty></Command.List></Command></Dialog.Content></Dialog>"
|
|
157
135
|
]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
2
|
|
|
3
|
-
import * as React from
|
|
4
|
-
import styles from
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import styles from "./Command.module.scss";
|
|
5
5
|
|
|
6
6
|
// ============================================
|
|
7
7
|
// Types
|
|
@@ -30,7 +30,7 @@ export interface CommandListProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
30
30
|
children: React.ReactNode;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
export interface CommandItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>,
|
|
33
|
+
export interface CommandItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onSelect"> {
|
|
34
34
|
children: React.ReactNode;
|
|
35
35
|
/** Value used for filtering (falls back to text content) */
|
|
36
36
|
value?: string;
|
|
@@ -78,13 +78,13 @@ function defaultFilter(value: string, search: string, keywords?: string[]): numb
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
function getTextContent(node: React.ReactNode): string {
|
|
81
|
-
if (typeof node ===
|
|
82
|
-
if (Array.isArray(node)) return node.map(getTextContent).join(
|
|
81
|
+
if (typeof node === "string" || typeof node === "number") return String(node);
|
|
82
|
+
if (Array.isArray(node)) return node.map(getTextContent).join(" ");
|
|
83
83
|
if (React.isValidElement(node)) {
|
|
84
84
|
const childProps = node.props as { children?: React.ReactNode };
|
|
85
85
|
return getTextContent(childProps.children);
|
|
86
86
|
}
|
|
87
|
-
return
|
|
87
|
+
return "";
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
// ============================================
|
|
@@ -115,7 +115,7 @@ const CommandContext = React.createContext<CommandContextValue | null>(null);
|
|
|
115
115
|
|
|
116
116
|
function useCommandContext() {
|
|
117
117
|
const ctx = React.useContext(CommandContext);
|
|
118
|
-
if (!ctx) throw new Error(
|
|
118
|
+
if (!ctx) throw new Error("Command sub-components must be used within <Command>");
|
|
119
119
|
return ctx;
|
|
120
120
|
}
|
|
121
121
|
|
|
@@ -150,7 +150,7 @@ function SearchIcon() {
|
|
|
150
150
|
function CommandRoot({
|
|
151
151
|
children,
|
|
152
152
|
search: controlledSearch,
|
|
153
|
-
defaultSearch =
|
|
153
|
+
defaultSearch = "",
|
|
154
154
|
onSearchChange,
|
|
155
155
|
filter = defaultFilter,
|
|
156
156
|
loop = true,
|
|
@@ -231,14 +231,25 @@ function CommandRoot({
|
|
|
231
231
|
visibleCount,
|
|
232
232
|
listId,
|
|
233
233
|
}),
|
|
234
|
-
[
|
|
234
|
+
[
|
|
235
|
+
search,
|
|
236
|
+
setSearch,
|
|
237
|
+
filter,
|
|
238
|
+
scores,
|
|
239
|
+
registerItem,
|
|
240
|
+
unregisterItem,
|
|
241
|
+
activeId,
|
|
242
|
+
loop,
|
|
243
|
+
visibleCount,
|
|
244
|
+
listId,
|
|
245
|
+
]
|
|
235
246
|
);
|
|
236
247
|
|
|
237
248
|
return (
|
|
238
249
|
<CommandContext.Provider value={contextValue}>
|
|
239
250
|
<div
|
|
240
251
|
{...htmlProps}
|
|
241
|
-
className={[styles.command, className].filter(Boolean).join(
|
|
252
|
+
className={[styles.command, className].filter(Boolean).join(" ")}
|
|
242
253
|
role="search"
|
|
243
254
|
>
|
|
244
255
|
{children}
|
|
@@ -247,12 +258,7 @@ function CommandRoot({
|
|
|
247
258
|
);
|
|
248
259
|
}
|
|
249
260
|
|
|
250
|
-
function CommandInput({
|
|
251
|
-
className,
|
|
252
|
-
onChange,
|
|
253
|
-
onKeyDown,
|
|
254
|
-
...htmlProps
|
|
255
|
-
}: CommandInputProps) {
|
|
261
|
+
function CommandInput({ className, onChange, onKeyDown, ...htmlProps }: CommandInputProps) {
|
|
256
262
|
const { search, setSearch, listRef, setActiveId, activeId, loop, listId } = useCommandContext();
|
|
257
263
|
const inputRef = React.useRef<HTMLInputElement>(null);
|
|
258
264
|
|
|
@@ -261,7 +267,7 @@ function CommandInput({
|
|
|
261
267
|
if (!list) return [];
|
|
262
268
|
return Array.from(
|
|
263
269
|
list.querySelectorAll<HTMLElement>('[data-command-item]:not([data-disabled="true"])')
|
|
264
|
-
).filter((el) => el.style.display !==
|
|
270
|
+
).filter((el) => el.style.display !== "none");
|
|
265
271
|
}, [listRef]);
|
|
266
272
|
|
|
267
273
|
const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
|
@@ -270,45 +276,48 @@ function CommandInput({
|
|
|
270
276
|
|
|
271
277
|
const items = getEnabledItems();
|
|
272
278
|
if (items.length === 0) return;
|
|
279
|
+
const firstItem = items[0];
|
|
280
|
+
const lastItem = items.at(-1);
|
|
281
|
+
if (!firstItem || !lastItem) return;
|
|
273
282
|
|
|
274
|
-
const currentIndex = activeId
|
|
275
|
-
? items.findIndex((item) => item.id === activeId)
|
|
276
|
-
: -1;
|
|
283
|
+
const currentIndex = activeId ? items.findIndex((item) => item.id === activeId) : -1;
|
|
277
284
|
|
|
278
285
|
switch (event.key) {
|
|
279
|
-
case
|
|
286
|
+
case "ArrowDown": {
|
|
280
287
|
event.preventDefault();
|
|
281
288
|
if (currentIndex < 0) {
|
|
282
|
-
setActiveId(
|
|
289
|
+
setActiveId(firstItem.id);
|
|
283
290
|
} else if (currentIndex < items.length - 1) {
|
|
284
|
-
|
|
291
|
+
const nextItem = items[currentIndex + 1];
|
|
292
|
+
if (nextItem) setActiveId(nextItem.id);
|
|
285
293
|
} else if (loop) {
|
|
286
|
-
setActiveId(
|
|
294
|
+
setActiveId(firstItem.id);
|
|
287
295
|
}
|
|
288
296
|
break;
|
|
289
297
|
}
|
|
290
|
-
case
|
|
298
|
+
case "ArrowUp": {
|
|
291
299
|
event.preventDefault();
|
|
292
300
|
if (currentIndex < 0) {
|
|
293
|
-
setActiveId(
|
|
301
|
+
setActiveId(lastItem.id);
|
|
294
302
|
} else if (currentIndex > 0) {
|
|
295
|
-
|
|
303
|
+
const previousItem = items[currentIndex - 1];
|
|
304
|
+
if (previousItem) setActiveId(previousItem.id);
|
|
296
305
|
} else if (loop) {
|
|
297
|
-
setActiveId(
|
|
306
|
+
setActiveId(lastItem.id);
|
|
298
307
|
}
|
|
299
308
|
break;
|
|
300
309
|
}
|
|
301
|
-
case
|
|
310
|
+
case "Home": {
|
|
302
311
|
event.preventDefault();
|
|
303
|
-
setActiveId(
|
|
312
|
+
setActiveId(firstItem.id);
|
|
304
313
|
break;
|
|
305
314
|
}
|
|
306
|
-
case
|
|
315
|
+
case "End": {
|
|
307
316
|
event.preventDefault();
|
|
308
|
-
setActiveId(
|
|
317
|
+
setActiveId(lastItem.id);
|
|
309
318
|
break;
|
|
310
319
|
}
|
|
311
|
-
case
|
|
320
|
+
case "Enter": {
|
|
312
321
|
event.preventDefault();
|
|
313
322
|
if (activeId) {
|
|
314
323
|
const activeItem = items.find((item) => item.id === activeId);
|
|
@@ -343,7 +352,7 @@ function CommandInput({
|
|
|
343
352
|
setSearch(e.target.value);
|
|
344
353
|
}}
|
|
345
354
|
onKeyDown={handleKeyDown}
|
|
346
|
-
className={[styles.input, className].filter(Boolean).join(
|
|
355
|
+
className={[styles.input, className].filter(Boolean).join(" ")}
|
|
347
356
|
/>
|
|
348
357
|
</div>
|
|
349
358
|
);
|
|
@@ -358,7 +367,7 @@ function CommandList({ children, className, ...htmlProps }: CommandListProps) {
|
|
|
358
367
|
{...htmlProps}
|
|
359
368
|
id={listId}
|
|
360
369
|
role="listbox"
|
|
361
|
-
className={[styles.list, className].filter(Boolean).join(
|
|
370
|
+
className={[styles.list, className].filter(Boolean).join(" ")}
|
|
362
371
|
>
|
|
363
372
|
{children}
|
|
364
373
|
</div>
|
|
@@ -402,11 +411,13 @@ function CommandItem({
|
|
|
402
411
|
// Scroll active item into view
|
|
403
412
|
React.useEffect(() => {
|
|
404
413
|
if (isActive && itemRef.current) {
|
|
405
|
-
itemRef.current.scrollIntoView({ block:
|
|
414
|
+
itemRef.current.scrollIntoView({ block: "nearest" });
|
|
406
415
|
}
|
|
407
416
|
}, [isActive]);
|
|
408
417
|
|
|
409
|
-
const activateItem = (
|
|
418
|
+
const activateItem = (
|
|
419
|
+
event: React.MouseEvent<HTMLDivElement> | React.KeyboardEvent<HTMLDivElement>
|
|
420
|
+
) => {
|
|
410
421
|
if (disabled) return;
|
|
411
422
|
onItemSelect?.(textValue, event);
|
|
412
423
|
};
|
|
@@ -440,7 +451,7 @@ function CommandItem({
|
|
|
440
451
|
onKeyDown={(e) => {
|
|
441
452
|
onKeyDown?.(e);
|
|
442
453
|
if (e.defaultPrevented) return;
|
|
443
|
-
if (e.key ===
|
|
454
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
444
455
|
e.preventDefault();
|
|
445
456
|
activateItem(e);
|
|
446
457
|
}
|
|
@@ -453,8 +464,8 @@ function CommandItem({
|
|
|
453
464
|
className,
|
|
454
465
|
]
|
|
455
466
|
.filter(Boolean)
|
|
456
|
-
.join(
|
|
457
|
-
style={{ ...style, display: isVisible ? undefined :
|
|
467
|
+
.join(" ")}
|
|
468
|
+
style={{ ...style, display: isVisible ? undefined : "none" }}
|
|
458
469
|
>
|
|
459
470
|
{children}
|
|
460
471
|
</div>
|
|
@@ -470,8 +481,8 @@ function CommandGroup({ children, heading, className, ...htmlProps }: CommandGro
|
|
|
470
481
|
// Check if any children are visible after each score update
|
|
471
482
|
React.useEffect(() => {
|
|
472
483
|
if (!groupRef.current) return;
|
|
473
|
-
const items = groupRef.current.querySelectorAll<HTMLElement>(
|
|
474
|
-
const anyVisible = Array.from(items).some((item) => item.style.display !==
|
|
484
|
+
const items = groupRef.current.querySelectorAll<HTMLElement>("[data-command-item]");
|
|
485
|
+
const anyVisible = Array.from(items).some((item) => item.style.display !== "none");
|
|
475
486
|
setHasVisibleChildren(anyVisible);
|
|
476
487
|
}, [scores]);
|
|
477
488
|
|
|
@@ -483,8 +494,8 @@ function CommandGroup({ children, heading, className, ...htmlProps }: CommandGro
|
|
|
483
494
|
{...restHtmlProps}
|
|
484
495
|
role="group"
|
|
485
496
|
aria-labelledby={heading ? labelId : undefined}
|
|
486
|
-
className={[styles.group, className].filter(Boolean).join(
|
|
487
|
-
style={{ ...style, display: hasVisibleChildren ? undefined :
|
|
497
|
+
className={[styles.group, className].filter(Boolean).join(" ")}
|
|
498
|
+
style={{ ...style, display: hasVisibleChildren ? undefined : "none" }}
|
|
488
499
|
>
|
|
489
500
|
{heading && (
|
|
490
501
|
<div id={labelId} className={styles.groupHeading}>
|
|
@@ -507,7 +518,7 @@ function CommandEmpty({ children, className, ...htmlProps }: CommandEmptyProps)
|
|
|
507
518
|
role="option"
|
|
508
519
|
aria-disabled="true"
|
|
509
520
|
aria-selected="false"
|
|
510
|
-
className={[styles.empty, className].filter(Boolean).join(
|
|
521
|
+
className={[styles.empty, className].filter(Boolean).join(" ")}
|
|
511
522
|
>
|
|
512
523
|
{children}
|
|
513
524
|
</div>
|
|
@@ -519,7 +530,7 @@ function CommandSeparator({ className, ...htmlProps }: CommandSeparatorProps) {
|
|
|
519
530
|
<div
|
|
520
531
|
{...htmlProps}
|
|
521
532
|
role="separator"
|
|
522
|
-
className={[styles.separator, className].filter(Boolean).join(
|
|
533
|
+
className={[styles.separator, className].filter(Boolean).join(" ")}
|
|
523
534
|
/>
|
|
524
535
|
);
|
|
525
536
|
}
|