@maxio-com/react-ui-components 9.17.1 → 9.19.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.
|
@@ -31,10 +31,11 @@ Choose the visual treatment that fits the surrounding surface.
|
|
|
31
31
|
### Behavior
|
|
32
32
|
|
|
33
33
|
- **Mouse and touch**: selecting a tab updates the active tab and renders the matching panel.
|
|
34
|
-
- **Keyboard**: Tab moves focus into the tab list. ArrowRight and ArrowLeft move selection across enabled tabs.
|
|
34
|
+
- **Keyboard**: Tab moves focus into the tab list. ArrowRight and ArrowLeft move selection across enabled tabs, and Home/End jump to the first/last enabled tab.
|
|
35
35
|
- **Focus management**: the selected tab receives focus after keyboard selection.
|
|
36
36
|
- **Controlled state**: use `index` with `onChange` when the active tab needs to be driven by route state, saved preferences, or another component.
|
|
37
37
|
- **Uncontrolled state**: use `defaultIndex` when Tabs can manage its own selection after the initial render.
|
|
38
|
+
- **Overflow**: set `overflow="auto"` on `TabList` when a tab set can grow past the available width. Tabs that don't fit collapse into a "More" menu; the active tab is always kept visible, even if it would otherwise be the one to collapse.
|
|
38
39
|
|
|
39
40
|
### Accessibility
|
|
40
41
|
|
|
@@ -43,6 +44,7 @@ Choose the visual treatment that fits the surrounding surface.
|
|
|
43
44
|
- Give icon-only tabs an accessible name with `aria-label`.
|
|
44
45
|
- Do not put disabled tabs in the selected state.
|
|
45
46
|
- Keep focus indicators visible and preserve the built-in arrow-key behavior.
|
|
47
|
+
- The "More" overflow menu is fully keyboard-operable: `Enter`/`Space`/`ArrowDown` on the trigger opens it and focuses the first item, `ArrowUp`/`ArrowDown` move between items, and `Escape` closes it and returns focus to the trigger.
|
|
46
48
|
|
|
47
49
|
### Content
|
|
48
50
|
|
|
@@ -119,10 +121,31 @@ const Example = () => {
|
|
|
119
121
|
</Tabs>
|
|
120
122
|
```
|
|
121
123
|
|
|
124
|
+
### Handling overflow
|
|
125
|
+
|
|
126
|
+
Set `overflow="auto"` on `TabList` when a tab set can grow past the
|
|
127
|
+
available width (many tabs, narrow containers). Tabs that don't fit
|
|
128
|
+
collapse into a "More" menu, and the currently active tab is always
|
|
129
|
+
promoted to the visible row even if it would otherwise overflow.
|
|
130
|
+
`moreLabel` customizes the accessible label of the "More" trigger
|
|
131
|
+
(defaults to `"More"`).
|
|
132
|
+
|
|
133
|
+
The menu is built with
|
|
134
|
+
[react-aria-components](https://react-spectrum.adobe.com/react-aria/) and
|
|
135
|
+
is fully keyboard-operable out of the box:
|
|
136
|
+
|
|
137
|
+
- `Enter`, `Space`, or `ArrowDown` on the trigger opens the menu and
|
|
138
|
+
focuses its first item.
|
|
139
|
+
- `ArrowUp`/`ArrowDown` move focus between items.
|
|
140
|
+
- `Enter`/`Space` on a focused item selects it, closes the menu, and
|
|
141
|
+
returns focus to the trigger.
|
|
142
|
+
- `Escape` closes the menu without selecting anything and also returns
|
|
143
|
+
focus to the trigger.
|
|
144
|
+
|
|
122
145
|
## Imports
|
|
123
146
|
|
|
124
147
|
```tsx
|
|
125
|
-
import { Body, Icon, Tab, TabList, TabPanel, TabPanels, Tabs } from "@maxio-com/react-ui-components";
|
|
148
|
+
import { Body, Card, Icon, Tab, TabList, TabPanel, TabPanels, Tabs } from "@maxio-com/react-ui-components";
|
|
126
149
|
```
|
|
127
150
|
|
|
128
151
|
## Prop Types
|
|
@@ -133,7 +156,7 @@ import { Body, Icon, Tab, TabList, TabPanel, TabPanels, Tabs } from "@maxio-com/
|
|
|
133
156
|
| --- | --- | --- | --- | --- | --- |
|
|
134
157
|
| `defaultIndex` | `number` | no | `0` | Indicates which tab should be active by default | TypeLiteral |
|
|
135
158
|
| `index` | `number` | no | - | Indicates which tab should be active in controlled mode. | TypeLiteral |
|
|
136
|
-
| `onChange` | `
|
|
159
|
+
| `onChange` | `TabsOnChange` | no | - | Callback function that is fired when the tab is changed | TypeLiteral |
|
|
137
160
|
| `variant` | `"line" \| "contained"` | no | `line` | The variant of the tabs. | TabsContext |
|
|
138
161
|
| `withDivider` | `boolean` | no | `false` | Add divider between tabs | TabsContext |
|
|
139
162
|
|
|
@@ -191,3 +214,53 @@ const BareIcon = () => <Tabs>
|
|
|
191
214
|
</TabPanels>
|
|
192
215
|
</Tabs>;
|
|
193
216
|
```
|
|
217
|
+
|
|
218
|
+
### Overflow
|
|
219
|
+
|
|
220
|
+
Use `overflow="auto"` when a tab set can grow past the available width (many tabs, narrow containers). Tabs that don't fit collapse into a "More" menu; the active tab is always kept visible.
|
|
221
|
+
|
|
222
|
+
```tsx
|
|
223
|
+
const Overflow = () => <div style={{ width: '400px' }}>
|
|
224
|
+
<Tabs defaultIndex={0}>
|
|
225
|
+
<TabList ariaLabel="Account sections" overflow="auto">
|
|
226
|
+
{OVERFLOW_TABS.map((tab) => (
|
|
227
|
+
<Tab key={tab}>{tab}</Tab>
|
|
228
|
+
))}
|
|
229
|
+
</TabList>
|
|
230
|
+
<TabPanels>
|
|
231
|
+
{OVERFLOW_TABS.map((tab) => (
|
|
232
|
+
<TabPanel key={`${tab}-content`} style={{ height: '150px' }}>
|
|
233
|
+
<Body>{`${tab} content for Acme Billing.`}</Body>
|
|
234
|
+
</TabPanel>
|
|
235
|
+
))}
|
|
236
|
+
</TabPanels>
|
|
237
|
+
</Tabs>
|
|
238
|
+
</div>;
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### In Card
|
|
242
|
+
|
|
243
|
+
Use Tabs to drive a Card's own navigation when the card represents a sectioned view: put TabList in Card.Header so the tabs read as the card's title, and put each TabPanel's content in Card.Body so the panel reads as the card's body. Tabs still wraps both sections since it's the context provider connecting TabList's selection to TabPanels, regardless of where each one sits in the DOM.
|
|
244
|
+
|
|
245
|
+
```tsx
|
|
246
|
+
const InCard = () => <Tabs defaultIndex={0}>
|
|
247
|
+
<Card>
|
|
248
|
+
<Card.Header style={{ padding: 0 }}>
|
|
249
|
+
<TabList ariaLabel="Customer account sections">
|
|
250
|
+
{TABS.map((tab) => (
|
|
251
|
+
<Tab key={tab}>{tab}</Tab>
|
|
252
|
+
))}
|
|
253
|
+
</TabList>
|
|
254
|
+
</Card.Header>
|
|
255
|
+
<Card.Body style={{ borderTopLeftRadius: 0, borderTopRightRadius: 0 }}>
|
|
256
|
+
<TabPanels>
|
|
257
|
+
{TABS.map((tab) => (
|
|
258
|
+
<TabPanel key={`${tab}-content`}>
|
|
259
|
+
<Body>{`${tab} content for Acme Billing.`}</Body>
|
|
260
|
+
</TabPanel>
|
|
261
|
+
))}
|
|
262
|
+
</TabPanels>
|
|
263
|
+
</Card.Body>
|
|
264
|
+
</Card>
|
|
265
|
+
</Tabs>;
|
|
266
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maxio-com/react-ui-components",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.19.0",
|
|
4
4
|
"description": "React UI components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -45,10 +45,13 @@
|
|
|
45
45
|
"react-dom": "^19.1.1"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
+
"@atlaskit/pragmatic-drag-and-drop": "^2.0.1",
|
|
49
|
+
"@atlaskit/pragmatic-drag-and-drop-hitbox": "^2.0.0",
|
|
48
50
|
"@floating-ui/react-dom": "^2.1.6",
|
|
49
51
|
"@floating-ui/react-dom-interactions": "^0.13.3",
|
|
50
52
|
"@maxio-com/design-tokens": "^4.2.2",
|
|
51
53
|
"@react-aria/toast": "3.0.7",
|
|
54
|
+
"@react-aria/utils": "^3.33.1",
|
|
52
55
|
"@react-stately/checkbox": "^3.7.1",
|
|
53
56
|
"@react-stately/radio": "^3.11.1",
|
|
54
57
|
"@react-stately/toast": "3.1.2",
|
|
@@ -56,11 +59,11 @@
|
|
|
56
59
|
"@tanstack/react-table": "^8.21.3",
|
|
57
60
|
"classnames": "^2.5.1",
|
|
58
61
|
"framer-motion": "^12.23.19",
|
|
59
|
-
"react-aria": "^3.
|
|
60
|
-
"react-aria-components": "^1.
|
|
62
|
+
"react-aria": "^3.50.0",
|
|
63
|
+
"react-aria-components": "^1.19.0"
|
|
61
64
|
},
|
|
62
65
|
"publishConfig": {
|
|
63
66
|
"access": "public"
|
|
64
67
|
},
|
|
65
|
-
"gitHead": "
|
|
68
|
+
"gitHead": "550dc2c6524537ca3808d6b69a07c16f98c9848d"
|
|
66
69
|
}
|
package/typings/index.d.ts
CHANGED
|
@@ -149,7 +149,7 @@ declare const Breadcrumbs: React$1.FC<BreadcrumbsProps>;
|
|
|
149
149
|
declare const BreadcrumbsItem: React$1.FC<BreadcrumbsItemProps>;
|
|
150
150
|
//# sourceMappingURL=BreadcrumbsItem.d.ts.map
|
|
151
151
|
|
|
152
|
-
declare const Button:
|
|
152
|
+
declare const Button: React$1.ForwardRefExoticComponent<ButtonProps & React$1.RefAttributes<HTMLAnchorElement | HTMLButtonElement>>;
|
|
153
153
|
//# sourceMappingURL=Button.d.ts.map
|
|
154
154
|
|
|
155
155
|
type ButtonSize = 'sm' | 'md' | 'lg';
|
|
@@ -163,9 +163,41 @@ declare const IconButton: ({ "aria-label": ariaLabel, className, ...props }: Ico
|
|
|
163
163
|
|
|
164
164
|
type TableSize = 'sm' | 'md' | 'lg';
|
|
165
165
|
type ColumnAlign = 'left' | 'right';
|
|
166
|
+
type RowReorderMode = 'siblings' | 'same-level' | 'all';
|
|
167
|
+
type RowReorderPosition = 'before' | 'after' | 'inside';
|
|
168
|
+
type RowReorderLocation = {
|
|
169
|
+
parentRowId: string | null;
|
|
170
|
+
index: number;
|
|
171
|
+
};
|
|
172
|
+
type RowReorderEvent<TData extends RowData> = {
|
|
173
|
+
data: TData[];
|
|
174
|
+
row: Row<TData>;
|
|
175
|
+
rowId: string;
|
|
176
|
+
targetRow: Row<TData>;
|
|
177
|
+
targetRowId: string;
|
|
178
|
+
position: RowReorderPosition;
|
|
179
|
+
source: RowReorderLocation;
|
|
180
|
+
destination: RowReorderLocation;
|
|
181
|
+
};
|
|
166
182
|
type RequiredTableOptions<TData extends RowData> = Pick<TableOptions<TData>, 'data' | 'columns'>;
|
|
167
|
-
type OptionalTableOptions<TData extends RowData> = Partial<Omit<TableOptions<TData>, 'getCoreRowModel' | 'enableExpanding'>>;
|
|
168
|
-
type
|
|
183
|
+
type OptionalTableOptions<TData extends RowData> = Partial<Omit<TableOptions<TData>, 'getCoreRowModel' | 'enableExpanding' | 'enableSorting' | 'getSubRows'>>;
|
|
184
|
+
type RowReorderingOptions<TData extends RowData> = {
|
|
185
|
+
enableSorting?: TableOptions<TData>['enableSorting'];
|
|
186
|
+
enableRowReordering?: false;
|
|
187
|
+
getSubRows?: TableOptions<TData>['getSubRows'];
|
|
188
|
+
getRowReorderLabel?: never;
|
|
189
|
+
onRowReorder?: never;
|
|
190
|
+
rowReorderMode?: never;
|
|
191
|
+
} | {
|
|
192
|
+
enableSorting?: TableOptions<TData>['enableSorting'];
|
|
193
|
+
enableRowReordering: true;
|
|
194
|
+
getSubRows?: never;
|
|
195
|
+
getRowId: NonNullable<TableOptions<TData>['getRowId']>;
|
|
196
|
+
getRowReorderLabel?: (row: Row<TData>) => string;
|
|
197
|
+
onRowReorder: (event: RowReorderEvent<TData>) => void;
|
|
198
|
+
rowReorderMode?: RowReorderMode;
|
|
199
|
+
};
|
|
200
|
+
type DataTableBaseProps<TData extends RowData> = {
|
|
169
201
|
size?: TableSize;
|
|
170
202
|
pattern?: boolean;
|
|
171
203
|
align?: ColumnAlign;
|
|
@@ -179,6 +211,7 @@ type DataTableProps<TData extends RowData = unknown> = {
|
|
|
179
211
|
onSelect?: (selected: RowSelectionState) => void;
|
|
180
212
|
onSort?: (selected: SortingState) => void;
|
|
181
213
|
} & RequiredTableOptions<TData> & OptionalTableOptions<TData>;
|
|
214
|
+
type DataTableProps<TData extends RowData = unknown> = DataTableBaseProps<TData> & RowReorderingOptions<TData>;
|
|
182
215
|
declare module '@tanstack/react-table' {
|
|
183
216
|
interface ColumnMeta<TData extends RowData, TValue> {
|
|
184
217
|
align?: ColumnAlign;
|
|
@@ -188,7 +221,7 @@ declare module '@tanstack/react-table' {
|
|
|
188
221
|
}
|
|
189
222
|
}
|
|
190
223
|
|
|
191
|
-
declare const DataTable: <TData extends RowData>({ pattern, size, SubRowComponent, onExpand, onSelect, onSort, enableSorting, enableRowSelection, enableExpanding, columns: originalColumns, actions, actionsColumnSize, onRowAction, state: userState, ...props }: DataTableProps<TData>) => React$1.JSX.Element;
|
|
224
|
+
declare const DataTable: <TData extends RowData>({ pattern, size, SubRowComponent, onExpand, onSelect, onSort, enableSorting, enableRowSelection, enableExpanding, columns: originalColumns, actions, actionsColumnSize, onRowAction, enableRowReordering, getRowReorderLabel, onRowReorder, rowReorderMode, getRowId, getSubRows, state: userState, ...props }: DataTableProps<TData>) => React$1.JSX.Element;
|
|
192
225
|
//# sourceMappingURL=DataTable.d.ts.map
|
|
193
226
|
|
|
194
227
|
type DrawerPlacement = 'left' | 'right' | 'top' | 'bottom';
|
|
@@ -275,6 +308,8 @@ declare function useWindowSize(debounce?: number): {
|
|
|
275
308
|
windowHeight: number;
|
|
276
309
|
};
|
|
277
310
|
|
|
311
|
+
declare function useElementResizeObserver<T extends HTMLElement = HTMLElement>(ref: RefObject<T | null>): number;
|
|
312
|
+
|
|
278
313
|
type OverlayTriggerProps = {
|
|
279
314
|
children: React$1.ReactNode;
|
|
280
315
|
placement?: Placement;
|
|
@@ -396,9 +431,10 @@ interface SideNavTopDropdownItem extends AnchorHTMLAttributes<HTMLAnchorElement>
|
|
|
396
431
|
type SideNavWrapperProps = Omit<SideNavProviderProps, 'children'>;
|
|
397
432
|
declare const SideNavWrapper: ({ withIcons, shouldToggleSidebar, topDropdownItems, sections, collapseBreakpoint, isOpen, onChange, }: SideNavWrapperProps) => React$1.JSX.Element;
|
|
398
433
|
|
|
399
|
-
type CommonTabProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
434
|
+
type CommonTabProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'id'> & {
|
|
400
435
|
disabled?: boolean;
|
|
401
436
|
value?: number;
|
|
437
|
+
id?: string;
|
|
402
438
|
isCurrent?: boolean;
|
|
403
439
|
};
|
|
404
440
|
type IconTab = {
|
|
@@ -412,31 +448,32 @@ type DefaultTab = {
|
|
|
412
448
|
};
|
|
413
449
|
type TabProps = CommonTabProps & (DefaultTab | IconTab);
|
|
414
450
|
|
|
415
|
-
declare const Tab: ({ disabled, value, isCurrent, ...props }: TabProps) => React$1.JSX.Element;
|
|
451
|
+
declare const Tab: ({ disabled, value, className, id: legacyId, isCurrent, ...props }: TabProps) => React$1.JSX.Element;
|
|
416
452
|
//# sourceMappingURL=Tab.d.ts.map
|
|
417
453
|
|
|
418
454
|
type TabsVariant = 'line' | 'contained';
|
|
455
|
+
type TabsOnChange = ((idx: number) => void) | ((idx: number | ((prevIdx: number) => number)) => void);
|
|
419
456
|
interface TabsContext {
|
|
420
457
|
variant: TabsVariant;
|
|
421
458
|
withDivider: boolean;
|
|
422
|
-
onChange: (idx: number | ((prevIdx: number) => number)) => void;
|
|
423
|
-
currentIndex: number;
|
|
424
459
|
}
|
|
425
|
-
type TabsProviderProps =
|
|
460
|
+
type TabsProviderProps = Partial<TabsContext> & {
|
|
426
461
|
children: ReactNode;
|
|
427
462
|
defaultIndex?: number;
|
|
428
463
|
index?: number;
|
|
464
|
+
onChange?: TabsOnChange;
|
|
429
465
|
};
|
|
430
466
|
|
|
431
467
|
type TabsProps = TabsProviderProps;
|
|
432
468
|
declare const Tabs: ({ children, variant, withDivider, defaultIndex, index, onChange, }: TabsProps) => React$1.JSX.Element;
|
|
433
469
|
//# sourceMappingURL=Tabs.d.ts.map
|
|
434
470
|
|
|
435
|
-
interface TabPanelProps extends React$1.HtmlHTMLAttributes<HTMLDivElement> {
|
|
471
|
+
interface TabPanelProps extends Omit<React$1.HtmlHTMLAttributes<HTMLDivElement>, 'children' | 'id'> {
|
|
436
472
|
children: ReactNode;
|
|
437
473
|
value?: number;
|
|
474
|
+
id?: string;
|
|
438
475
|
}
|
|
439
|
-
declare const TabPanel: ({ children, value, ...props }: TabPanelProps) => React$1.JSX.Element;
|
|
476
|
+
declare const TabPanel: ({ children, value, className, id: legacyId, ...props }: TabPanelProps) => React$1.JSX.Element;
|
|
440
477
|
|
|
441
478
|
interface TabPanelsProps {
|
|
442
479
|
children: React$1.ReactNode;
|
|
@@ -447,8 +484,10 @@ declare const TabPanels: ({ children }: TabPanelsProps) => React$1.JSX.Element;
|
|
|
447
484
|
interface TabListProps extends React$1.HtmlHTMLAttributes<HTMLDivElement> {
|
|
448
485
|
ariaLabel: string;
|
|
449
486
|
children: ReactNode;
|
|
487
|
+
overflow?: 'auto' | 'none';
|
|
488
|
+
moreLabel?: string;
|
|
450
489
|
}
|
|
451
|
-
declare const TabList: ({ children, className, ariaLabel, ...props }: TabListProps) => React$1.JSX.Element;
|
|
490
|
+
declare const TabList: ({ children, className, ariaLabel, overflow, moreLabel, ...props }: TabListProps) => React$1.JSX.Element;
|
|
452
491
|
//# sourceMappingURL=TabList.d.ts.map
|
|
453
492
|
|
|
454
493
|
type TagSize = 'sm';
|
|
@@ -879,5 +918,5 @@ type AuthLayoutProps = {
|
|
|
879
918
|
declare const AuthLayout: ({ children, heading, description, sentiment, leadingElement, alert, topAddon, footer, }: AuthLayoutProps) => React$1.JSX.Element;
|
|
880
919
|
//# sourceMappingURL=AuthLayout.d.ts.map
|
|
881
920
|
|
|
882
|
-
export { ActionList, Alert, AuthLayout, Avatar, Banner, Body, Breadcrumbs, BreadcrumbsItem, Button, Card, Checkbox, CheckboxGroup, Chip, Code, ComboBox, DataTable, Display, Drawer, Flex, FormErrorMessage, FormHelperText, GlobalToastProvider, Grid, Heading, Icon, IconButton, Label, Link, ListBox, LoadingSpinner, Logo, Menu, MenuButton, MenuList, OverlayTrigger, Pagination, Popover, ProgressBar, Radio, RadioGroup, SegmentedControl, Select, SideNavWrapper as SideNav, Tab, TabList, TabPanel, TabPanels, Tabs, Tag, TextArea, TextField, TextInput, Tile, ToastProvider, ToastQueue, Toggle, Tooltip, TooltipTrigger, TopBar, useHover, useOverlayTrigger, useToast, useWindowSize };
|
|
921
|
+
export { ActionList, Alert, AuthLayout, Avatar, Banner, Body, Breadcrumbs, BreadcrumbsItem, Button, Card, Checkbox, CheckboxGroup, Chip, Code, ComboBox, DataTable, Display, Drawer, Flex, FormErrorMessage, FormHelperText, GlobalToastProvider, Grid, Heading, Icon, IconButton, Label, Link, ListBox, LoadingSpinner, Logo, Menu, MenuButton, MenuList, OverlayTrigger, Pagination, Popover, ProgressBar, Radio, RadioGroup, SegmentedControl, Select, SideNavWrapper as SideNav, Tab, TabList, TabPanel, TabPanels, Tabs, Tag, TextArea, TextField, TextInput, Tile, ToastProvider, ToastQueue, Toggle, Tooltip, TooltipTrigger, TopBar, useElementResizeObserver, useHover, useOverlayTrigger, useToast, useWindowSize };
|
|
883
922
|
export type { ComboBoxProps, DrawerProps, Interactions, OverlayAriaRole, Placement, PopoverProps, SegmentedControlItemProps, SegmentedControlProps, SegmentedControlSize, TextAreaProps, TextFieldProps, TextInputProps };
|