@usefragments/ui 1.0.2 → 1.2.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 +16 -16
- package/dist/assets/fragments-wordmark.cjs +30 -0
- package/dist/assets/fragments-wordmark.d.ts +13 -0
- package/dist/assets/fragments-wordmark.d.ts.map +1 -0
- package/dist/assets/fragments-wordmark.js +30 -0
- package/dist/assets/ui.css +3234 -3116
- package/dist/components/Accordion/Accordion.module.scss.cjs +8 -8
- package/dist/components/Accordion/Accordion.module.scss.js +8 -8
- package/dist/components/Accordion/index.cjs +22 -10
- package/dist/components/Accordion/index.d.ts.map +1 -1
- package/dist/components/Accordion/index.js +22 -10
- package/dist/components/Alert/Alert.module.scss.cjs +13 -13
- package/dist/components/Alert/Alert.module.scss.js +13 -13
- package/dist/components/AppShell/AppShell.module.scss.cjs +22 -10
- package/dist/components/AppShell/AppShell.module.scss.js +22 -10
- package/dist/components/AppShell/index.cjs +1 -1
- package/dist/components/AppShell/index.js +1 -1
- package/dist/components/Avatar/Avatar.module.scss.cjs +13 -13
- package/dist/components/Avatar/Avatar.module.scss.js +13 -13
- package/dist/components/Badge/Badge.module.scss.cjs +16 -16
- package/dist/components/Badge/Badge.module.scss.js +16 -16
- 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/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 +13 -13
- package/dist/components/Button/Button.module.scss.js +13 -13
- package/dist/components/Card/Card.module.scss.cjs +17 -17
- package/dist/components/Card/Card.module.scss.js +17 -17
- package/dist/components/Card/index.d.ts +3 -3
- package/dist/components/Card/index.d.ts.map +1 -1
- package/dist/components/Chart/Chart.module.scss.cjs +15 -15
- package/dist/components/Chart/Chart.module.scss.js +15 -15
- package/dist/components/Checkbox/Checkbox.module.scss.cjs +11 -11
- package/dist/components/Checkbox/Checkbox.module.scss.js +11 -11
- package/dist/components/Chip/Chip.module.scss.cjs +15 -15
- package/dist/components/Chip/Chip.module.scss.js +15 -15
- package/dist/components/CodeBlock/CodeBlock.module.scss.cjs +21 -21
- package/dist/components/CodeBlock/CodeBlock.module.scss.js +21 -21
- package/dist/components/Collapsible/Collapsible.module.scss.cjs +10 -10
- package/dist/components/Collapsible/Collapsible.module.scss.js +10 -10
- package/dist/components/ColorPicker/ColorPicker.module.scss.cjs +14 -14
- package/dist/components/ColorPicker/ColorPicker.module.scss.js +14 -14
- package/dist/components/Combobox/Combobox.module.scss.cjs +23 -23
- package/dist/components/Combobox/Combobox.module.scss.js +23 -23
- package/dist/components/Combobox/index.cjs +106 -9
- package/dist/components/Combobox/index.d.ts.map +1 -1
- package/dist/components/Combobox/index.js +106 -9
- package/dist/components/Command/Command.module.scss.cjs +11 -11
- package/dist/components/Command/Command.module.scss.js +11 -11
- 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.module.scss.cjs +37 -34
- package/dist/components/DataTable/DataTable.module.scss.js +37 -34
- package/dist/components/DataTable/index.d.ts +3 -1
- 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 +1 -1
- 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/Drawer/Drawer.module.scss.cjs +28 -28
- package/dist/components/Drawer/Drawer.module.scss.js +28 -28
- package/dist/components/Drawer/index.cjs +20 -3
- package/dist/components/Drawer/index.d.ts.map +1 -1
- package/dist/components/Drawer/index.js +20 -3
- package/dist/components/Editor/Editor.module.scss.cjs +17 -17
- package/dist/components/Editor/Editor.module.scss.js +17 -17
- package/dist/components/EmptyState/EmptyState.module.scss.cjs +8 -8
- package/dist/components/EmptyState/EmptyState.module.scss.js +8 -8
- package/dist/components/Field/Field.module.scss.cjs +4 -4
- package/dist/components/Field/Field.module.scss.js +4 -4
- package/dist/components/Field/index.cjs +10 -9
- package/dist/components/Field/index.d.ts +7 -7
- package/dist/components/Field/index.d.ts.map +1 -1
- package/dist/components/Field/index.js +10 -9
- package/dist/components/Fieldset/Fieldset.module.scss.cjs +3 -3
- package/dist/components/Fieldset/Fieldset.module.scss.js +3 -3
- package/dist/components/Header/Header.module.scss.cjs +44 -29
- package/dist/components/Header/Header.module.scss.js +44 -29
- package/dist/components/Header/index.cjs +56 -3
- package/dist/components/Header/index.d.ts +25 -3
- package/dist/components/Header/index.d.ts.map +1 -1
- package/dist/components/Header/index.js +56 -3
- package/dist/components/Icon/Icon.module.scss.cjs +8 -8
- package/dist/components/Icon/Icon.module.scss.js +8 -8
- package/dist/components/IconButton/IconButton.module.scss.cjs +8 -8
- package/dist/components/IconButton/IconButton.module.scss.js +8 -8
- 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 +19 -19
- package/dist/components/Input/Input.module.scss.js +19 -19
- package/dist/components/Link/Link.module.scss.cjs +10 -10
- package/dist/components/Link/Link.module.scss.js +10 -10
- 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 +30 -30
- package/dist/components/Loading/Loading.module.scss.js +30 -30
- package/dist/components/Main/Main.module.scss.cjs +26 -0
- package/dist/components/Main/Main.module.scss.js +26 -0
- package/dist/components/Main/index.cjs +128 -0
- package/dist/components/Main/index.d.ts +22 -0
- package/dist/components/Main/index.d.ts.map +1 -0
- package/dist/components/Main/index.js +111 -0
- package/dist/components/Markdown/Markdown.module.scss.cjs +1 -1
- package/dist/components/Markdown/Markdown.module.scss.js +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 +28 -28
- package/dist/components/NavigationMenu/NavigationMenu.module.scss.js +28 -28
- package/dist/components/Pagination/Pagination.module.scss.cjs +7 -7
- package/dist/components/Pagination/Pagination.module.scss.js +7 -7
- package/dist/components/Popover/Popover.module.scss.cjs +10 -10
- package/dist/components/Popover/Popover.module.scss.js +10 -10
- package/dist/components/Popover/index.cjs +27 -2
- package/dist/components/Popover/index.d.ts.map +1 -1
- package/dist/components/Popover/index.js +27 -2
- 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 +18 -18
- package/dist/components/Prompt/Prompt.module.scss.js +18 -18
- package/dist/components/RadioGroup/RadioGroup.module.scss.cjs +17 -17
- package/dist/components/RadioGroup/RadioGroup.module.scss.js +17 -17
- package/dist/components/RadioGroup/index.cjs +2 -0
- package/dist/components/RadioGroup/index.d.ts +2 -0
- package/dist/components/RadioGroup/index.d.ts.map +1 -1
- package/dist/components/RadioGroup/index.js +2 -0
- package/dist/components/ScrollArea/ScrollArea.module.scss.cjs +10 -10
- package/dist/components/ScrollArea/ScrollArea.module.scss.js +10 -10
- package/dist/components/Select/Select.module.scss.cjs +17 -17
- package/dist/components/Select/Select.module.scss.js +17 -17
- package/dist/components/Separator/Separator.module.scss.cjs +10 -10
- package/dist/components/Separator/Separator.module.scss.js +10 -10
- package/dist/components/Sidebar/Sidebar.module.scss.cjs +42 -42
- package/dist/components/Sidebar/Sidebar.module.scss.js +42 -42
- package/dist/components/Skeleton/Skeleton.module.scss.cjs +38 -38
- package/dist/components/Skeleton/Skeleton.module.scss.js +38 -38
- package/dist/components/Slider/Slider.module.scss.cjs +12 -12
- package/dist/components/Slider/Slider.module.scss.js +12 -12
- 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 +22 -42
- package/dist/components/TableOfContents/index.d.ts +3 -3
- package/dist/components/TableOfContents/index.d.ts.map +1 -1
- package/dist/components/TableOfContents/index.js +22 -42
- package/dist/components/Tabs/Tabs.module.scss.cjs +12 -12
- package/dist/components/Tabs/Tabs.module.scss.js +12 -12
- package/dist/components/Text/Text.module.scss.cjs +51 -51
- package/dist/components/Text/Text.module.scss.js +51 -51
- package/dist/components/Textarea/Textarea.module.scss.cjs +23 -23
- package/dist/components/Textarea/Textarea.module.scss.js +23 -23
- package/dist/components/Theme/ThemeToggle.module.scss.cjs +6 -6
- package/dist/components/Theme/ThemeToggle.module.scss.js +6 -6
- 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 +21 -21
- package/dist/components/Toast/Toast.module.scss.js +21 -21
- package/dist/components/Toggle/Toggle.module.scss.cjs +13 -13
- package/dist/components/Toggle/Toggle.module.scss.js +13 -13
- 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/data-table.cjs +58 -41
- package/dist/data-table.js +59 -41
- package/dist/datepicker.cjs +32 -72
- package/dist/datepicker.js +32 -72
- package/dist/index.cjs +89 -85
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/fragments.json +1 -1
- package/package.json +9 -8
- package/src/assets/fragments-wordmark.tsx +47 -0
- package/src/components/Accordion/index.tsx +13 -3
- package/src/components/Alert/Alert.module.scss +15 -2
- package/src/components/AppShell/AppShell.module.scss +73 -15
- package/src/components/AppShell/index.tsx +1 -1
- package/src/components/Button/Button.module.scss +19 -20
- package/src/components/Card/Card.module.scss +3 -3
- package/src/components/Card/index.tsx +3 -3
- package/src/components/Checkbox/Checkbox.contract.json +5 -24
- package/src/components/Checkbox/Checkbox.module.scss +4 -2
- package/src/components/Chip/Chip.contract.json +11 -28
- package/src/components/Chip/Chip.module.scss +21 -45
- package/src/components/CodeBlock/CodeBlock.module.scss +2 -7
- package/src/components/Combobox/Combobox.contract.json +6 -24
- package/src/components/Combobox/Combobox.module.scss +3 -2
- package/src/components/Combobox/index.tsx +132 -6
- package/src/components/DataTable/DataTable.contract.json +16 -23
- package/src/components/DataTable/DataTable.module.scss +31 -8
- package/src/components/DataTable/index.tsx +25 -4
- package/src/components/DatePicker/index.tsx +32 -84
- package/src/components/Drawer/index.tsx +38 -12
- package/src/components/Field/index.tsx +35 -35
- package/src/components/Header/Header.contract.json +41 -1
- package/src/components/Header/Header.module.scss +40 -0
- package/src/components/Header/index.tsx +88 -2
- package/src/components/IconButton/IconButton.contract.json +120 -0
- package/src/components/Listbox/Listbox.module.scss +5 -4
- package/src/components/Main/Main.contract.json +79 -0
- package/src/components/Main/Main.module.scss +31 -0
- package/src/components/Main/index.tsx +124 -0
- package/src/components/Menu/Menu.module.scss +8 -10
- package/src/components/Popover/index.tsx +34 -2
- package/src/components/RadioGroup/RadioGroup.contract.json +13 -27
- package/src/components/RadioGroup/index.tsx +4 -0
- package/src/components/Select/Select.module.scss +13 -12
- package/src/components/Table/Table.module.scss +22 -5
- package/src/components/TableOfContents/TableOfContents.contract.json +6 -16
- package/src/components/TableOfContents/TableOfContents.module.scss +20 -14
- package/src/components/TableOfContents/index.tsx +27 -38
- package/src/components/Toast/Toast.module.scss +15 -2
- package/src/components/ToggleGroup/ToggleGroup.module.scss +4 -1
- package/src/index.ts +4 -0
- package/src/styles/globals.scss +13 -10
- package/src/tokens/_component-properties.scss +26 -0
- package/src/tokens/_computed.scss +22 -4
- package/src/tokens/_derive.scss +55 -6
- package/src/tokens/_palettes.scss +24 -0
- package/src/tokens/_seeds.scss +20 -12
- package/src/tokens/_variables.scss +110 -63
- package/dist/components/Cloud/DashboardLayoutPrototypes.shared.d.ts +0 -33
- package/dist/components/Cloud/DashboardLayoutPrototypes.shared.d.ts.map +0 -1
- package/dist/components/Cloud/DashboardLayoutPrototypes.shell.d.ts +0 -11
- package/dist/components/Cloud/DashboardLayoutPrototypes.shell.d.ts.map +0 -1
- package/dist/components/Cloud/PullRequestsPrototypes.content.d.ts +0 -5
- package/dist/components/Cloud/PullRequestsPrototypes.content.d.ts.map +0 -1
- package/dist/components/Cloud/PullRequestsPrototypes.detail-panels.d.ts +0 -4
- package/dist/components/Cloud/PullRequestsPrototypes.detail-panels.d.ts.map +0 -1
- package/dist/components/Cloud/PullRequestsPrototypes.detail.d.ts +0 -3
- package/dist/components/Cloud/PullRequestsPrototypes.detail.d.ts.map +0 -1
- package/dist/components/Cloud/PullRequestsPrototypes.id-data.d.ts +0 -86
- package/dist/components/Cloud/PullRequestsPrototypes.id-data.d.ts.map +0 -1
- package/dist/components/Cloud/PullRequestsPrototypes.id-page.d.ts +0 -2
- package/dist/components/Cloud/PullRequestsPrototypes.id-page.d.ts.map +0 -1
- package/src/components/Accordion/Accordion.stories.tsx +0 -106
- package/src/components/Alert/Alert.stories.tsx +0 -119
- package/src/components/AppShell/AppShell.stories.tsx +0 -156
- package/src/components/Avatar/Avatar.stories.tsx +0 -74
- package/src/components/Badge/Badge.stories.tsx +0 -92
- package/src/components/BentoGrid/BentoGrid.stories.tsx +0 -98
- package/src/components/Box/Box.stories.tsx +0 -150
- package/src/components/Breadcrumbs/Breadcrumbs.stories.tsx +0 -87
- package/src/components/Button/Button.stories.tsx +0 -103
- package/src/components/ButtonGroup/ButtonGroup.stories.tsx +0 -97
- package/src/components/Card/Card.stories.tsx +0 -144
- package/src/components/Chart/Chart.stories.tsx +0 -119
- package/src/components/Checkbox/Checkbox.stories.tsx +0 -68
- package/src/components/Chip/Chip.stories.tsx +0 -70
- package/src/components/Cloud/CloudGovernanceShell.module.scss +0 -88
- package/src/components/Cloud/CloudGovernanceShell.stories.tsx +0 -446
- package/src/components/Cloud/ControlSizing.module.scss +0 -49
- package/src/components/Cloud/ControlSizing.stories.tsx +0 -238
- package/src/components/Cloud/DashboardLayoutPrototypes.module.scss +0 -462
- package/src/components/Cloud/DashboardLayoutPrototypes.shared.tsx +0 -375
- package/src/components/Cloud/DashboardLayoutPrototypes.shell.tsx +0 -147
- package/src/components/Cloud/DashboardLayoutPrototypes.stories.tsx +0 -328
- package/src/components/Cloud/PullRequestsPrototypes.content.tsx +0 -283
- package/src/components/Cloud/PullRequestsPrototypes.detail-panels.tsx +0 -381
- package/src/components/Cloud/PullRequestsPrototypes.detail.tsx +0 -204
- package/src/components/Cloud/PullRequestsPrototypes.id-data.ts +0 -395
- package/src/components/Cloud/PullRequestsPrototypes.id-page.tsx +0 -349
- package/src/components/Cloud/PullRequestsPrototypes.stories.tsx +0 -81
- package/src/components/CodeBlock/CodeBlock.stories.tsx +0 -147
- package/src/components/Collapsible/Collapsible.stories.tsx +0 -94
- package/src/components/ColorPicker/ColorPicker.stories.tsx +0 -74
- package/src/components/Combobox/Combobox.stories.tsx +0 -133
- package/src/components/Command/Command.stories.tsx +0 -102
- package/src/components/ConversationList/ConversationList.stories.tsx +0 -93
- package/src/components/DataTable/DataTable.stories.tsx +0 -129
- package/src/components/DatePicker/DatePicker.stories.tsx +0 -129
- package/src/components/Dialog/Dialog.stories.tsx +0 -154
- package/src/components/Drawer/Drawer.stories.tsx +0 -144
- package/src/components/Editor/Editor.stories.tsx +0 -99
- package/src/components/EmptyState/EmptyState.stories.tsx +0 -97
- package/src/components/Field/Field.stories.tsx +0 -109
- package/src/components/Fieldset/Fieldset.stories.tsx +0 -116
- package/src/components/Form/Form.stories.tsx +0 -142
- package/src/components/Grid/Grid.stories.tsx +0 -125
- package/src/components/Header/Header.stories.tsx +0 -133
- package/src/components/Icon/Icon.stories.tsx +0 -80
- package/src/components/IconButton/IconButton.stories.tsx +0 -78
- package/src/components/Image/Image.stories.tsx +0 -109
- package/src/components/Input/Input.stories.tsx +0 -104
- package/src/components/Link/Link.stories.tsx +0 -67
- package/src/components/List/List.stories.tsx +0 -95
- package/src/components/Listbox/Listbox.stories.tsx +0 -81
- package/src/components/Loading/Loading.stories.tsx +0 -69
- package/src/components/Markdown/Markdown.stories.tsx +0 -75
- package/src/components/Menu/Menu.stories.tsx +0 -113
- package/src/components/Message/Message.stories.tsx +0 -85
- package/src/components/NavigationMenu/NavigationMenu.stories.tsx +0 -161
- package/src/components/Pagination/Pagination.stories.tsx +0 -81
- package/src/components/Popover/Popover.stories.tsx +0 -152
- package/src/components/Progress/Progress.stories.tsx +0 -64
- package/src/components/Prompt/Prompt.stories.tsx +0 -93
- package/src/components/RadioGroup/RadioGroup.stories.tsx +0 -107
- package/src/components/ScrollArea/ScrollArea.stories.tsx +0 -97
- package/src/components/Select/Select.stories.tsx +0 -127
- package/src/components/Separator/Separator.stories.tsx +0 -84
- package/src/components/Sidebar/Sidebar.stories.tsx +0 -122
- package/src/components/Skeleton/Skeleton.stories.tsx +0 -80
- package/src/components/Slider/Slider.stories.tsx +0 -73
- package/src/components/Stack/Stack.stories.tsx +0 -73
- package/src/components/Switch/Switch.stories.tsx +0 -59
- package/src/components/Table/Table.stories.tsx +0 -219
- package/src/components/TableOfContents/TableOfContents.stories.tsx +0 -120
- package/src/components/Tabs/Tabs.stories.tsx +0 -136
- package/src/components/Text/Text.stories.tsx +0 -133
- package/src/components/Textarea/Textarea.stories.tsx +0 -107
- package/src/components/Theme/Theme.stories.tsx +0 -95
- package/src/components/ThinkingIndicator/ThinkingIndicator.stories.tsx +0 -85
- package/src/components/Toast/Toast.stories.tsx +0 -91
- package/src/components/ToggleGroup/ToggleGroup.stories.tsx +0 -114
- package/src/components/Tooltip/Tooltip.stories.tsx +0 -95
- package/src/components/VisuallyHidden/VisuallyHidden.stories.tsx +0 -78
|
@@ -82,6 +82,8 @@ export interface DataTableProps<T> extends Omit<React.HTMLAttributes<HTMLTableEl
|
|
|
82
82
|
onRowSelectionChange?: OnChangeFn<RowSelectionState>;
|
|
83
83
|
/** Row click handler */
|
|
84
84
|
onRowClick?: (row: T, event: DataTableRowClickEvent) => void;
|
|
85
|
+
/** Props applied to each rendered data row. Use this for row-level ARIA labels, roles, and data attributes. */
|
|
86
|
+
getRowProps?: (row: T) => React.HTMLAttributes<HTMLTableRowElement>;
|
|
85
87
|
/** Extract sub-rows from a row for expandable tree tables */
|
|
86
88
|
getSubRows?: (row: T) => T[] | undefined;
|
|
87
89
|
/** Controlled expanded state */
|
|
@@ -143,7 +145,11 @@ function isInteractiveTarget(target: EventTarget | null, currentTarget: HTMLTabl
|
|
|
143
145
|
'button, a, input, select, textarea, [role="button"], [role="link"], [role="checkbox"], [role="switch"]'
|
|
144
146
|
);
|
|
145
147
|
|
|
146
|
-
return Boolean(
|
|
148
|
+
return Boolean(
|
|
149
|
+
interactiveElement &&
|
|
150
|
+
interactiveElement !== currentTarget &&
|
|
151
|
+
currentTarget.contains(interactiveElement)
|
|
152
|
+
);
|
|
147
153
|
}
|
|
148
154
|
|
|
149
155
|
function DataTableRoot<T>({
|
|
@@ -158,6 +164,7 @@ function DataTableRoot<T>({
|
|
|
158
164
|
rowSelection: controlledRowSelection,
|
|
159
165
|
onRowSelectionChange,
|
|
160
166
|
onRowClick,
|
|
167
|
+
getRowProps,
|
|
161
168
|
getSubRows,
|
|
162
169
|
expanded: controlledExpanded,
|
|
163
170
|
onExpandedChange,
|
|
@@ -411,13 +418,25 @@ function DataTableRoot<T>({
|
|
|
411
418
|
const isSelected = selectable ? row.getIsSelected() : false;
|
|
412
419
|
const depth: number = row.depth ?? 0;
|
|
413
420
|
const canExpand = hasSubRows && row.getCanExpand();
|
|
421
|
+
const resolvedRowProps = getRowProps?.(row.original) ?? {};
|
|
422
|
+
const {
|
|
423
|
+
className: rowClassName,
|
|
424
|
+
onClick: rowOnClick,
|
|
425
|
+
onKeyDown: rowOnKeyDown,
|
|
426
|
+
tabIndex: rowTabIndex,
|
|
427
|
+
...rowHtmlProps
|
|
428
|
+
} = resolvedRowProps;
|
|
414
429
|
const handleRowClick = (event: React.MouseEvent<HTMLTableRowElement>) => {
|
|
430
|
+
rowOnClick?.(event);
|
|
431
|
+
if (event.defaultPrevented) return;
|
|
415
432
|
if (!onRowClick) return;
|
|
416
433
|
if (isInteractiveTarget(event.target, event.currentTarget)) return;
|
|
417
434
|
onRowClick(row.original, event);
|
|
418
435
|
};
|
|
419
436
|
|
|
420
437
|
const handleRowKeyDown = (event: React.KeyboardEvent<HTMLTableRowElement>) => {
|
|
438
|
+
rowOnKeyDown?.(event);
|
|
439
|
+
if (event.defaultPrevented) return;
|
|
421
440
|
if (!onRowClick) return;
|
|
422
441
|
if (isInteractiveTarget(event.target, event.currentTarget)) return;
|
|
423
442
|
if (event.key === "Enter" || event.key === " ") {
|
|
@@ -428,18 +447,20 @@ function DataTableRoot<T>({
|
|
|
428
447
|
|
|
429
448
|
return (
|
|
430
449
|
<tr
|
|
450
|
+
{...rowHtmlProps}
|
|
431
451
|
key={row.id}
|
|
432
452
|
className={[
|
|
433
453
|
styles.row,
|
|
434
454
|
isClickable && styles.clickable,
|
|
435
455
|
isSelected && styles.selected,
|
|
436
456
|
depth > 0 && styles.subRow,
|
|
457
|
+
rowClassName,
|
|
437
458
|
]
|
|
438
459
|
.filter(Boolean)
|
|
439
460
|
.join(" ")}
|
|
440
|
-
onClick={isClickable ? handleRowClick : undefined}
|
|
441
|
-
onKeyDown={isClickable ? handleRowKeyDown : undefined}
|
|
442
|
-
tabIndex={isClickable ? 0 : undefined}
|
|
461
|
+
onClick={isClickable || rowOnClick ? handleRowClick : undefined}
|
|
462
|
+
onKeyDown={isClickable || rowOnKeyDown ? handleRowKeyDown : undefined}
|
|
463
|
+
tabIndex={rowTabIndex ?? (isClickable ? 0 : undefined)}
|
|
443
464
|
data-selected={isSelected || undefined}
|
|
444
465
|
data-depth={depth > 0 ? depth : undefined}
|
|
445
466
|
>
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { Popover as BasePopover } from "@base-ui/react/popover";
|
|
5
|
+
import { DayFlag, DayPicker, SelectionState, UI } from "react-day-picker";
|
|
6
|
+
import { format as formatDateWithPattern } from "date-fns";
|
|
5
7
|
import { useFormFieldIds, type FormFieldProps } from "../../utils/aria";
|
|
6
8
|
import { useResolvedControlSize } from "../ComponentDefaults";
|
|
7
9
|
import styles from "./DatePicker.module.scss";
|
|
@@ -82,39 +84,6 @@ export interface DatePickerPresetProps extends React.ButtonHTMLAttributes<HTMLBu
|
|
|
82
84
|
range?: DateRange;
|
|
83
85
|
}
|
|
84
86
|
|
|
85
|
-
// ============================================
|
|
86
|
-
// Lazy-loaded dependencies (react-day-picker + date-fns)
|
|
87
|
-
// ============================================
|
|
88
|
-
|
|
89
|
-
let _DayPicker: any = null;
|
|
90
|
-
let _dpUI: any = null;
|
|
91
|
-
let _SelectionState: any = null;
|
|
92
|
-
let _DayFlag: any = null;
|
|
93
|
-
let _formatDate: ((date: Date, fmt: string) => string) | null = null;
|
|
94
|
-
let _dpLoaded = false;
|
|
95
|
-
let _dpFailed = false;
|
|
96
|
-
|
|
97
|
-
function loadDatePickerDeps() {
|
|
98
|
-
if (_dpLoaded) return;
|
|
99
|
-
_dpLoaded = true;
|
|
100
|
-
try {
|
|
101
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
102
|
-
const rdp = require("react-day-picker");
|
|
103
|
-
_DayPicker = rdp.DayPicker;
|
|
104
|
-
_dpUI = rdp.UI;
|
|
105
|
-
_SelectionState = rdp.SelectionState;
|
|
106
|
-
_DayFlag = rdp.DayFlag;
|
|
107
|
-
} catch {
|
|
108
|
-
_dpFailed = true;
|
|
109
|
-
}
|
|
110
|
-
try {
|
|
111
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
112
|
-
_formatDate = require("date-fns").format;
|
|
113
|
-
} catch {
|
|
114
|
-
_dpFailed = true;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
87
|
// ============================================
|
|
119
88
|
// Icons
|
|
120
89
|
// ============================================
|
|
@@ -219,18 +188,13 @@ function useDatePickerContext() {
|
|
|
219
188
|
// ============================================
|
|
220
189
|
|
|
221
190
|
function defaultFormatDate(date: Date): string {
|
|
222
|
-
|
|
223
|
-
return date.toLocaleDateString();
|
|
191
|
+
return formatDateWithPattern(date, "PPP");
|
|
224
192
|
}
|
|
225
193
|
|
|
226
194
|
function defaultFormatRange(range: DateRange): string {
|
|
227
195
|
if (!range.from) return "";
|
|
228
|
-
if (
|
|
229
|
-
|
|
230
|
-
return `${_formatDate(range.from, "LLL dd, y")} - ${_formatDate(range.to, "LLL dd, y")}`;
|
|
231
|
-
}
|
|
232
|
-
if (!range.to) return range.from.toLocaleDateString();
|
|
233
|
-
return `${range.from.toLocaleDateString()} - ${range.to.toLocaleDateString()}`;
|
|
196
|
+
if (!range.to) return formatDateWithPattern(range.from, "LLL dd, y");
|
|
197
|
+
return `${formatDateWithPattern(range.from, "LLL dd, y")} - ${formatDateWithPattern(range.to, "LLL dd, y")}`;
|
|
234
198
|
}
|
|
235
199
|
|
|
236
200
|
function formatDateForHiddenInput(date?: Date): string {
|
|
@@ -246,32 +210,31 @@ function formatDateForHiddenInput(date?: Date): string {
|
|
|
246
210
|
// ============================================
|
|
247
211
|
|
|
248
212
|
function getCalendarClassNames() {
|
|
249
|
-
if (!_dpUI || !_SelectionState || !_DayFlag) return {};
|
|
250
213
|
return {
|
|
251
|
-
[
|
|
252
|
-
[
|
|
253
|
-
[
|
|
254
|
-
[
|
|
255
|
-
[
|
|
256
|
-
[
|
|
257
|
-
[
|
|
258
|
-
[
|
|
259
|
-
[
|
|
260
|
-
[
|
|
261
|
-
[
|
|
262
|
-
[
|
|
263
|
-
[
|
|
264
|
-
[
|
|
265
|
-
[
|
|
266
|
-
[
|
|
267
|
-
[
|
|
268
|
-
[
|
|
269
|
-
[
|
|
270
|
-
[
|
|
271
|
-
[
|
|
272
|
-
[
|
|
273
|
-
[
|
|
274
|
-
[
|
|
214
|
+
[UI.Root]: styles.calendar,
|
|
215
|
+
[UI.Months]: styles.months,
|
|
216
|
+
[UI.Month]: styles.month,
|
|
217
|
+
[UI.MonthCaption]: styles.monthCaption,
|
|
218
|
+
[UI.CaptionLabel]: styles.captionLabel,
|
|
219
|
+
[UI.Nav]: styles.nav,
|
|
220
|
+
[UI.PreviousMonthButton]: styles.navButton,
|
|
221
|
+
[UI.NextMonthButton]: styles.navButton,
|
|
222
|
+
[UI.MonthGrid]: styles.monthGrid,
|
|
223
|
+
[UI.Weekdays]: styles.weekdays,
|
|
224
|
+
[UI.Weekday]: styles.weekday,
|
|
225
|
+
[UI.Weeks]: styles.weeks,
|
|
226
|
+
[UI.Week]: styles.week,
|
|
227
|
+
[UI.Day]: styles.day,
|
|
228
|
+
[UI.DayButton]: styles.dayButton,
|
|
229
|
+
[UI.Chevron]: styles.chevron,
|
|
230
|
+
[SelectionState.selected]: styles.selected,
|
|
231
|
+
[SelectionState.range_start]: styles.rangeStart,
|
|
232
|
+
[SelectionState.range_middle]: styles.rangeMiddle,
|
|
233
|
+
[SelectionState.range_end]: styles.rangeEnd,
|
|
234
|
+
[DayFlag.today]: styles.today,
|
|
235
|
+
[DayFlag.outside]: styles.outside,
|
|
236
|
+
[DayFlag.disabled]: styles.disabled,
|
|
237
|
+
[DayFlag.focused]: styles.focused,
|
|
275
238
|
};
|
|
276
239
|
}
|
|
277
240
|
|
|
@@ -309,7 +272,6 @@ const DatePickerRoot = React.forwardRef<HTMLDivElement, DatePickerProps>(functio
|
|
|
309
272
|
) {
|
|
310
273
|
const size = useResolvedControlSize(sizeProp);
|
|
311
274
|
// Load deps eagerly so date formatters are available in the trigger
|
|
312
|
-
loadDatePickerDeps();
|
|
313
275
|
const [internalSelected, setInternalSelected] = React.useState<Date | null>(selectedProp ?? null);
|
|
314
276
|
const [internalRange, setInternalRange] = React.useState<DateRange | null>(
|
|
315
277
|
selectedRangeProp ?? null
|
|
@@ -544,8 +506,6 @@ function DatePickerCalendar({
|
|
|
544
506
|
numberOfMonths: numberOfMonthsProp,
|
|
545
507
|
className,
|
|
546
508
|
}: DatePickerCalendarProps) {
|
|
547
|
-
loadDatePickerDeps();
|
|
548
|
-
|
|
549
509
|
const ctx = useDatePickerContext();
|
|
550
510
|
const monthCount = numberOfMonthsProp ?? ctx.numberOfMonths;
|
|
551
511
|
|
|
@@ -557,31 +517,19 @@ function DatePickerCalendar({
|
|
|
557
517
|
[]
|
|
558
518
|
);
|
|
559
519
|
|
|
560
|
-
if (_dpFailed || !_DayPicker) {
|
|
561
|
-
if (_dpFailed && process.env.NODE_ENV === "development") {
|
|
562
|
-
console.warn(
|
|
563
|
-
"[@usefragments/ui] DatePicker: react-day-picker and date-fns are not installed. " +
|
|
564
|
-
"Install them with: npm install react-day-picker date-fns"
|
|
565
|
-
);
|
|
566
|
-
}
|
|
567
|
-
return null;
|
|
568
|
-
}
|
|
569
|
-
|
|
570
520
|
const calendarClassNames = getCalendarClassNames();
|
|
571
521
|
|
|
572
522
|
const calendarClasses = className
|
|
573
|
-
? { ...calendarClassNames, [
|
|
523
|
+
? { ...calendarClassNames, [UI.Root]: [styles.calendar, className].join(" ") }
|
|
574
524
|
: calendarClassNames;
|
|
575
525
|
|
|
576
|
-
const DayPickerComponent = _DayPicker;
|
|
577
|
-
|
|
578
526
|
if (ctx.mode === "range") {
|
|
579
527
|
const rangeSelected = ctx.selectedRange
|
|
580
528
|
? { from: ctx.selectedRange.from ?? undefined, to: ctx.selectedRange.to ?? undefined }
|
|
581
529
|
: undefined;
|
|
582
530
|
|
|
583
531
|
return (
|
|
584
|
-
<
|
|
532
|
+
<DayPicker
|
|
585
533
|
mode="range"
|
|
586
534
|
selected={rangeSelected}
|
|
587
535
|
onSelect={(range: any) => {
|
|
@@ -601,7 +549,7 @@ function DatePickerCalendar({
|
|
|
601
549
|
}
|
|
602
550
|
|
|
603
551
|
return (
|
|
604
|
-
<
|
|
552
|
+
<DayPicker
|
|
605
553
|
mode="single"
|
|
606
554
|
selected={ctx.selected ?? undefined}
|
|
607
555
|
onSelect={(date: any) => {
|
|
@@ -92,6 +92,18 @@ export interface DrawerSwipeAreaProps extends React.HTMLAttributes<HTMLDivElemen
|
|
|
92
92
|
disabled?: boolean;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
type DrawerSide = NonNullable<DrawerContentProps["side"]>;
|
|
96
|
+
type DrawerSwipeDirection = NonNullable<DrawerProps["swipeDirection"]>;
|
|
97
|
+
|
|
98
|
+
const SWIPE_DIRECTION_BY_SIDE: Record<DrawerSide, DrawerSwipeDirection> = {
|
|
99
|
+
left: "left",
|
|
100
|
+
right: "right",
|
|
101
|
+
top: "up",
|
|
102
|
+
bottom: "down",
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const DrawerContentSideContext = React.createContext<(side: DrawerSide) => void>(() => {});
|
|
106
|
+
|
|
95
107
|
function getAsChildElement(children: React.ReactNode, componentName: string): React.ReactElement {
|
|
96
108
|
if (!React.isValidElement(children)) {
|
|
97
109
|
throw new Error(`${componentName} with asChild requires a single valid React element child.`);
|
|
@@ -138,19 +150,24 @@ function DrawerRoot({
|
|
|
138
150
|
snapPoints,
|
|
139
151
|
disablePointerDismissal,
|
|
140
152
|
}: DrawerProps) {
|
|
153
|
+
const [contentSide, setContentSide] = React.useState<DrawerSide>("right");
|
|
154
|
+
const resolvedSwipeDirection = swipeDirection ?? SWIPE_DIRECTION_BY_SIDE[contentSide];
|
|
155
|
+
|
|
141
156
|
return (
|
|
142
|
-
<
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
157
|
+
<DrawerContentSideContext.Provider value={setContentSide}>
|
|
158
|
+
<BaseDrawer.Root
|
|
159
|
+
open={open}
|
|
160
|
+
defaultOpen={defaultOpen}
|
|
161
|
+
onOpenChange={onOpenChange}
|
|
162
|
+
onOpenChangeComplete={onOpenChangeComplete}
|
|
163
|
+
modal={modal}
|
|
164
|
+
swipeDirection={resolvedSwipeDirection}
|
|
165
|
+
snapPoints={snapPoints}
|
|
166
|
+
disablePointerDismissal={disablePointerDismissal}
|
|
167
|
+
>
|
|
168
|
+
{children}
|
|
169
|
+
</BaseDrawer.Root>
|
|
170
|
+
</DrawerContentSideContext.Provider>
|
|
154
171
|
);
|
|
155
172
|
}
|
|
156
173
|
|
|
@@ -181,11 +198,20 @@ function DrawerContent({
|
|
|
181
198
|
className,
|
|
182
199
|
...htmlProps
|
|
183
200
|
}: DrawerContentProps) {
|
|
201
|
+
const registerContentSide = React.useContext(DrawerContentSideContext);
|
|
184
202
|
const { className: viewportClassName, ...viewportHtmlProps } = viewportProps ?? {};
|
|
185
203
|
const popupClasses = [styles.popup, styles[`side-${side}`], styles[`size-${size}`], className]
|
|
186
204
|
.filter(Boolean)
|
|
187
205
|
.join(" ");
|
|
188
206
|
|
|
207
|
+
React.useEffect(() => {
|
|
208
|
+
registerContentSide(side);
|
|
209
|
+
|
|
210
|
+
return () => {
|
|
211
|
+
registerContentSide("right");
|
|
212
|
+
};
|
|
213
|
+
}, [registerContentSide, side]);
|
|
214
|
+
|
|
189
215
|
return (
|
|
190
216
|
<BaseDrawer.Portal>
|
|
191
217
|
{backdrop && <BaseDrawer.Backdrop className={styles.backdrop} />}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
2
|
|
|
3
|
-
import * as React from
|
|
4
|
-
import {
|
|
5
|
-
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import {
|
|
5
|
+
Field as BaseField,
|
|
6
|
+
type FieldControlProps as BaseFieldControlProps,
|
|
7
|
+
type FieldValidityState,
|
|
8
|
+
} from "@base-ui/react/field";
|
|
9
|
+
import styles from "./Field.module.scss";
|
|
6
10
|
|
|
7
11
|
// ============================================
|
|
8
12
|
// Types
|
|
@@ -14,7 +18,7 @@ export interface FieldProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
14
18
|
disabled?: boolean;
|
|
15
19
|
invalid?: boolean;
|
|
16
20
|
validate?: (value: unknown) => string | string[] | null | Promise<string | string[] | null>;
|
|
17
|
-
validationMode?:
|
|
21
|
+
validationMode?: "onSubmit" | "onBlur" | "onChange";
|
|
18
22
|
validationDebounceTime?: number;
|
|
19
23
|
}
|
|
20
24
|
|
|
@@ -23,7 +27,10 @@ export interface FieldLabelProps {
|
|
|
23
27
|
className?: string;
|
|
24
28
|
}
|
|
25
29
|
|
|
26
|
-
export interface FieldControlProps
|
|
30
|
+
export interface FieldControlProps extends Omit<
|
|
31
|
+
BaseFieldControlProps,
|
|
32
|
+
"children" | "className" | "ref" | "render"
|
|
33
|
+
> {
|
|
27
34
|
children: React.ReactElement;
|
|
28
35
|
className?: string;
|
|
29
36
|
}
|
|
@@ -35,7 +42,14 @@ export interface FieldDescriptionProps {
|
|
|
35
42
|
|
|
36
43
|
export interface FieldErrorProps {
|
|
37
44
|
children?: React.ReactNode;
|
|
38
|
-
match?:
|
|
45
|
+
match?:
|
|
46
|
+
| "valueMissing"
|
|
47
|
+
| "typeMismatch"
|
|
48
|
+
| "tooShort"
|
|
49
|
+
| "tooLong"
|
|
50
|
+
| "patternMismatch"
|
|
51
|
+
| "customError"
|
|
52
|
+
| boolean;
|
|
39
53
|
className?: string;
|
|
40
54
|
}
|
|
41
55
|
|
|
@@ -60,7 +74,7 @@ function FieldRoot({
|
|
|
60
74
|
className,
|
|
61
75
|
...htmlProps
|
|
62
76
|
}: FieldProps) {
|
|
63
|
-
const classes = [styles.root, className].filter(Boolean).join(
|
|
77
|
+
const classes = [styles.root, className].filter(Boolean).join(" ");
|
|
64
78
|
|
|
65
79
|
return (
|
|
66
80
|
<BaseField.Root
|
|
@@ -79,7 +93,7 @@ function FieldRoot({
|
|
|
79
93
|
}
|
|
80
94
|
|
|
81
95
|
function FieldLabel({ children, className }: FieldLabelProps) {
|
|
82
|
-
const classes = [styles.label, className].filter(Boolean).join(
|
|
96
|
+
const classes = [styles.label, className].filter(Boolean).join(" ");
|
|
83
97
|
return <BaseField.Label className={classes}>{children}</BaseField.Label>;
|
|
84
98
|
}
|
|
85
99
|
|
|
@@ -90,31 +104,24 @@ function FieldLabel({ children, className }: FieldLabelProps) {
|
|
|
90
104
|
*
|
|
91
105
|
* Works with Input, Textarea, Checkbox, Switch, Select, or any element.
|
|
92
106
|
*/
|
|
93
|
-
function FieldControl({ children, className }: FieldControlProps) {
|
|
94
|
-
const classes = [styles.control, className].filter(Boolean).join(
|
|
95
|
-
return
|
|
96
|
-
<BaseField.Control
|
|
97
|
-
className={classes}
|
|
98
|
-
render={children}
|
|
99
|
-
/>
|
|
100
|
-
);
|
|
107
|
+
function FieldControl({ children, className, ...controlProps }: FieldControlProps) {
|
|
108
|
+
const classes = [styles.control, className].filter(Boolean).join(" ");
|
|
109
|
+
return <BaseField.Control {...controlProps} className={classes} render={children} />;
|
|
101
110
|
}
|
|
102
111
|
|
|
103
112
|
function FieldDescription({ children, className }: FieldDescriptionProps) {
|
|
104
|
-
const classes = [styles.description, className].filter(Boolean).join(
|
|
105
|
-
return
|
|
106
|
-
<BaseField.Description className={classes}>
|
|
107
|
-
{children}
|
|
108
|
-
</BaseField.Description>
|
|
109
|
-
);
|
|
113
|
+
const classes = [styles.description, className].filter(Boolean).join(" ");
|
|
114
|
+
return <BaseField.Description className={classes}>{children}</BaseField.Description>;
|
|
110
115
|
}
|
|
111
116
|
|
|
112
117
|
function FieldError({ children, match, className }: FieldErrorProps) {
|
|
113
|
-
const classes = [styles.error, className].filter(Boolean).join(
|
|
118
|
+
const classes = [styles.error, className].filter(Boolean).join(" ");
|
|
114
119
|
return (
|
|
115
|
-
<BaseField.Error
|
|
116
|
-
{
|
|
117
|
-
|
|
120
|
+
<BaseField.Error
|
|
121
|
+
match={match}
|
|
122
|
+
className={classes}
|
|
123
|
+
{...(children === undefined ? {} : { children })}
|
|
124
|
+
/>
|
|
118
125
|
);
|
|
119
126
|
}
|
|
120
127
|
|
|
@@ -134,11 +141,4 @@ export const Field = Object.assign(FieldRoot, {
|
|
|
134
141
|
Validity: FieldValidity,
|
|
135
142
|
});
|
|
136
143
|
|
|
137
|
-
export {
|
|
138
|
-
FieldRoot,
|
|
139
|
-
FieldLabel,
|
|
140
|
-
FieldControl,
|
|
141
|
-
FieldDescription,
|
|
142
|
-
FieldError,
|
|
143
|
-
FieldValidity,
|
|
144
|
-
};
|
|
144
|
+
export { FieldRoot, FieldLabel, FieldControl, FieldDescription, FieldError, FieldValidity };
|
|
@@ -18,6 +18,9 @@
|
|
|
18
18
|
"children: node (required)",
|
|
19
19
|
"height: string (default: 56px)",
|
|
20
20
|
"position: static|fixed|sticky (default: static)",
|
|
21
|
+
"elevatedOnScroll: boolean|{ threshold?: number }",
|
|
22
|
+
"navAlign: start|center (default: start)",
|
|
23
|
+
"container: full|page (default: full)",
|
|
21
24
|
"icons: object",
|
|
22
25
|
"style: object"
|
|
23
26
|
],
|
|
@@ -44,6 +47,26 @@
|
|
|
44
47
|
"sticky"
|
|
45
48
|
]
|
|
46
49
|
},
|
|
50
|
+
"elevatedOnScroll": {
|
|
51
|
+
"type": "boolean|object",
|
|
52
|
+
"description": "Apply the elevated header border after scrolling. Object form accepts { threshold?: number }.",
|
|
53
|
+
"default": false,
|
|
54
|
+
"required": false
|
|
55
|
+
},
|
|
56
|
+
"navAlign": {
|
|
57
|
+
"type": "enum",
|
|
58
|
+
"description": "Navigation alignment inside the header",
|
|
59
|
+
"default": "start",
|
|
60
|
+
"required": false,
|
|
61
|
+
"values": ["start", "center"]
|
|
62
|
+
},
|
|
63
|
+
"container": {
|
|
64
|
+
"type": "enum",
|
|
65
|
+
"description": "Header content width",
|
|
66
|
+
"default": "full",
|
|
67
|
+
"required": false,
|
|
68
|
+
"values": ["full", "page"]
|
|
69
|
+
},
|
|
47
70
|
"icons": {
|
|
48
71
|
"type": "object",
|
|
49
72
|
"description": "Optional icon overrides for Header.Trigger (menu/close) and Header.NavMenu chevron",
|
|
@@ -79,7 +102,12 @@
|
|
|
79
102
|
"Use Header.NavMenu to group related nav items under a dropdown",
|
|
80
103
|
"Use Header.NavMenuItem inside Header.NavMenu for dropdown items",
|
|
81
104
|
"Header sub-components forward DOM props (id, aria-*, data-*, handlers) to their rendered elements",
|
|
105
|
+
"Header.Brand asChild composes custom link components while preserving canonical brand styling",
|
|
82
106
|
"Header.NavItem asChild composes click handlers instead of overwriting the child handler",
|
|
107
|
+
"Use elevatedOnScroll on sticky marketing headers that need a boundary after scrolling",
|
|
108
|
+
"Use navAlign=\"center\" when navigation must stay centered independently of brand and actions",
|
|
109
|
+
"Use container=\"page\" when the header should share a bounded page gutter",
|
|
110
|
+
"Use Header.MobileNavActions for the primary action row inside Header.MobileNav",
|
|
83
111
|
"Use the Header icons prop to replace internal mobile trigger and dropdown chevron icons with any icon package",
|
|
84
112
|
"For rich dropdown content (titles, descriptions, icons), use NavigationMenu instead of Header.Nav",
|
|
85
113
|
"NavigationMenu also provides an automatic mobile drawer, replacing Header.Trigger + Sidebar for mobile nav"
|
|
@@ -98,6 +126,11 @@
|
|
|
98
126
|
"description": "Header with brand, nav, and actions. Use with AppShell layout=\"default\".",
|
|
99
127
|
"code": "<ThemeProvider defaultMode=\"light\">\n <Header>\n <Header.SkipLink />\n <Header.Trigger />\n <Header.Brand href=\"/\">MyApp</Header.Brand>\n <Header.Nav>\n <Header.NavItem href=\"/dashboard\" active>Dashboard</Header.NavItem>\n <Header.NavItem href=\"/projects\">Projects</Header.NavItem>\n <Header.NavItem href=\"/settings\">Settings</Header.NavItem>\n </Header.Nav>\n <Header.Spacer />\n <Header.Actions>\n <ThemeToggle size=\"md\" />\n <Button variant=\"secondary\" size=\"sm\">Sign In</Button>\n </Header.Actions>\n </Header>\n</ThemeProvider>"
|
|
100
128
|
},
|
|
129
|
+
{
|
|
130
|
+
"name": "Marketing Header",
|
|
131
|
+
"description": "Sticky, page-width marketing header with centered navigation, scroll elevation, custom link composition, and mobile actions.",
|
|
132
|
+
"code": "<Header position=\"sticky\" elevatedOnScroll navAlign=\"center\" container=\"page\">\n <Header.SkipLink href=\"#main-content\" />\n <Header.Brand asChild>\n <a href=\"/\" aria-label=\"Home\">Logo</a>\n </Header.Brand>\n <Header.Nav aria-label=\"Main navigation\">\n <Header.NavItem href=\"/docs\">Docs</Header.NavItem>\n </Header.Nav>\n <Header.Actions>\n <Button size=\"sm\">Start free</Button>\n </Header.Actions>\n <Header.Trigger />\n <Header.MobileNav>\n <Header.MobileNavLink href=\"/docs\">Docs</Header.MobileNavLink>\n <Header.MobileNavActions>\n <Button size=\"sm\">Start free</Button>\n </Header.MobileNavActions>\n </Header.MobileNav>\n</Header>"
|
|
133
|
+
},
|
|
101
134
|
{
|
|
102
135
|
"name": "With Dropdown Nav",
|
|
103
136
|
"description": "Header with a dropdown menu grouping related navigation links.",
|
|
@@ -155,9 +188,14 @@
|
|
|
155
188
|
"propsSummary": [
|
|
156
189
|
"height: string - header height (default: 56px)",
|
|
157
190
|
"position: static|fixed|sticky - positioning behavior",
|
|
191
|
+
"elevatedOnScroll: boolean|{ threshold?: number } - scroll-elevated boundary",
|
|
192
|
+
"navAlign: start|center - nav placement inside the header",
|
|
193
|
+
"container: full|page - content width and gutter",
|
|
158
194
|
"icons: { menu?, close?, navMenuChevron? } - custom internal control icons (ReactNode or render function)",
|
|
195
|
+
"Header.Brand asChild composes custom link components",
|
|
159
196
|
"Header.Trigger composes click handler with Sidebar toggle behavior",
|
|
160
|
-
"Header.NavMenu provides dropdown groups via Base UI Menu"
|
|
197
|
+
"Header.NavMenu provides dropdown groups via Base UI Menu",
|
|
198
|
+
"Header.MobileNavActions provides an action row inside the mobile drawer"
|
|
161
199
|
],
|
|
162
200
|
"a11yRules": [
|
|
163
201
|
"A11Y_HEADER_LANDMARK",
|
|
@@ -176,6 +214,7 @@
|
|
|
176
214
|
"NavItem",
|
|
177
215
|
"MobileNav",
|
|
178
216
|
"MobileNavLink",
|
|
217
|
+
"MobileNavActions",
|
|
179
218
|
"NavMenu",
|
|
180
219
|
"NavMenuItem",
|
|
181
220
|
"Search",
|
|
@@ -184,6 +223,7 @@
|
|
|
184
223
|
],
|
|
185
224
|
"commonPatterns": [
|
|
186
225
|
"<Header><Header.Brand href=\"/\">{appName}</Header.Brand><Header.Nav><Header.NavItem href=\"/home\" active>Home</Header.NavItem></Header.Nav><Header.Spacer /><Header.Actions>{actions}</Header.Actions></Header>",
|
|
226
|
+
"<Header position=\"sticky\" elevatedOnScroll navAlign=\"center\" container=\"page\"><Header.Brand asChild>{link}</Header.Brand><Header.Nav>{links}</Header.Nav><Header.Actions>{actions}</Header.Actions><Header.Trigger /><Header.MobileNav>{mobileLinks}<Header.MobileNavActions>{mobileActions}</Header.MobileNavActions></Header.MobileNav></Header>",
|
|
187
227
|
"<Header><Header.Nav><Header.NavItem href=\"/home\">Home</Header.NavItem><Header.NavMenu label=\"Docs\" active><Header.NavMenuItem href=\"/cli\">CLI</Header.NavMenuItem><Header.NavMenuItem href=\"/mcp\">MCP</Header.NavMenuItem></Header.NavMenu></Header.Nav></Header>"
|
|
188
228
|
]
|
|
189
229
|
},
|
|
@@ -30,6 +30,24 @@
|
|
|
30
30
|
top: 0;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
.elevatedOnScroll {
|
|
34
|
+
border-bottom: var(--fui-space-px, $fui-space-px) solid transparent;
|
|
35
|
+
transition: border-color var(--fui-transition-fast, $fui-transition-fast);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.scrolled {
|
|
39
|
+
border-bottom-color: var(--fui-border, $fui-border);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.containerPage {
|
|
43
|
+
padding-inline: clamp(var(--fui-space-4, $fui-space-4), 4vw, var(--fui-space-12, $fui-space-12));
|
|
44
|
+
|
|
45
|
+
.container {
|
|
46
|
+
max-width: calc(var(--fui-space-12, $fui-space-12) * 31);
|
|
47
|
+
margin-inline: auto;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
33
51
|
.container {
|
|
34
52
|
display: flex;
|
|
35
53
|
align-items: center;
|
|
@@ -43,6 +61,21 @@
|
|
|
43
61
|
}
|
|
44
62
|
}
|
|
45
63
|
|
|
64
|
+
.navCentered {
|
|
65
|
+
.container {
|
|
66
|
+
position: relative;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.nav {
|
|
70
|
+
@include container-min($fui-breakpoint-md, fui-header) {
|
|
71
|
+
position: absolute;
|
|
72
|
+
inset-block: 0;
|
|
73
|
+
left: 50%;
|
|
74
|
+
transform: translateX(-50%);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
46
79
|
// ============================================
|
|
47
80
|
// Brand
|
|
48
81
|
// ============================================
|
|
@@ -381,6 +414,13 @@
|
|
|
381
414
|
background-color: var(--fui-bg-secondary, $fui-bg-secondary);
|
|
382
415
|
}
|
|
383
416
|
|
|
417
|
+
.mobileNavActions {
|
|
418
|
+
display: flex;
|
|
419
|
+
align-items: center;
|
|
420
|
+
gap: var(--fui-space-2, $fui-space-2);
|
|
421
|
+
padding: var(--fui-space-3, $fui-space-3) 0 var(--fui-space-2, $fui-space-2);
|
|
422
|
+
}
|
|
423
|
+
|
|
384
424
|
@keyframes mobileNavFadeIn {
|
|
385
425
|
from { opacity: 0; }
|
|
386
426
|
to { opacity: 1; }
|