@maxio-com/react-ui-components 9.16.0 → 9.17.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/dist/index.esm.js +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/skills/maxio-react/SKILL.md +69 -0
- package/dist/skills/maxio-react/agents/openai.yaml +4 -0
- package/dist/skills/maxio-react/references/components-action-list.md +92 -0
- package/dist/skills/maxio-react/references/components-action-menu.md +162 -0
- package/dist/skills/maxio-react/references/components-avatar.md +66 -0
- package/dist/skills/maxio-react/references/components-breadcrumbs.md +86 -0
- package/dist/skills/maxio-react/references/components-buttons-button.md +170 -0
- package/dist/skills/maxio-react/references/components-buttons-iconbutton.md +102 -0
- package/dist/skills/maxio-react/references/components-card.md +175 -0
- package/dist/skills/maxio-react/references/components-chip.md +151 -0
- package/dist/skills/maxio-react/references/components-data-table.md +344 -0
- package/dist/skills/maxio-react/references/components-drawer.md +293 -0
- package/dist/skills/maxio-react/references/components-flex.md +185 -0
- package/dist/skills/maxio-react/references/components-forms-checkbox.md +257 -0
- package/dist/skills/maxio-react/references/components-forms-combobox.md +250 -0
- package/dist/skills/maxio-react/references/components-forms-radio-group.md +202 -0
- package/dist/skills/maxio-react/references/components-forms-select.md +295 -0
- package/dist/skills/maxio-react/references/components-forms-textarea.md +187 -0
- package/dist/skills/maxio-react/references/components-forms-textfield.md +254 -0
- package/dist/skills/maxio-react/references/components-grid.md +140 -0
- package/dist/skills/maxio-react/references/components-icon.md +169 -0
- package/dist/skills/maxio-react/references/components-link.md +180 -0
- package/dist/skills/maxio-react/references/components-listbox.md +205 -0
- package/dist/skills/maxio-react/references/components-loading-spinner.md +123 -0
- package/dist/skills/maxio-react/references/components-logo.md +91 -0
- package/dist/skills/maxio-react/references/components-notifications-alert.md +103 -0
- package/dist/skills/maxio-react/references/components-notifications-banner.md +173 -0
- package/dist/skills/maxio-react/references/components-notifications-toast.md +155 -0
- package/dist/skills/maxio-react/references/components-pagination.md +115 -0
- package/dist/skills/maxio-react/references/components-popover.md +176 -0
- package/dist/skills/maxio-react/references/components-progressbar.md +98 -0
- package/dist/skills/maxio-react/references/components-segmentedcontrol.md +292 -0
- package/dist/skills/maxio-react/references/components-tabs.md +193 -0
- package/dist/skills/maxio-react/references/components-tag.md +117 -0
- package/dist/skills/maxio-react/references/components-tile.md +114 -0
- package/dist/skills/maxio-react/references/components-toggle.md +218 -0
- package/dist/skills/maxio-react/references/components-tooltip.md +178 -0
- package/dist/skills/maxio-react/references/components-typography-body.md +101 -0
- package/dist/skills/maxio-react/references/components-typography-code.md +72 -0
- package/dist/skills/maxio-react/references/components-typography-display.md +91 -0
- package/dist/skills/maxio-react/references/components-typography-heading.md +88 -0
- package/dist/skills/maxio-react/references/components-typography-label.md +82 -0
- package/dist/skills/maxio-react/references/deprecated-textinput.md +250 -0
- package/dist/skills/maxio-react/references/foundations-dark-mode.md +85 -0
- package/dist/skills/maxio-react/references/foundations-design-tokens-about.md +108 -0
- package/dist/skills/maxio-react/references/foundations-design-tokens-colors-primitive-colors.md +33 -0
- package/dist/skills/maxio-react/references/foundations-design-tokens-colors-semantic-colors.md +11 -0
- package/dist/skills/maxio-react/references/foundations-start-here.md +128 -0
- package/dist/skills/maxio-react/references/patterns-auth-layout.md +318 -0
- package/dist/skills/maxio-react/references/patterns-side-nav.md +182 -0
- package/dist/skills/maxio-react/references/patterns-top-bar.md +214 -0
- package/package.json +2 -2
- package/typings/index.d.ts +15 -2
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# Card
|
|
2
|
+
|
|
3
|
+
## Usage Guidelines
|
|
4
|
+
|
|
5
|
+
### Overview
|
|
6
|
+
|
|
7
|
+
#### When to Use
|
|
8
|
+
|
|
9
|
+
- Use Card to group related content that should be scanned as one unit.
|
|
10
|
+
- Use Card for page sections, settings panels, summaries, and content blocks with local actions.
|
|
11
|
+
- Use Card.Header, Card.Body, and Card.Footer when a grouped section needs a title, content, and actions.
|
|
12
|
+
|
|
13
|
+
#### When Not to Use
|
|
14
|
+
|
|
15
|
+
- Do not use Card as a generic spacing wrapper when the content does not need a visible container.
|
|
16
|
+
- Do not use Card for a whole page layout. Use layout primitives such as Flex or Grid instead.
|
|
17
|
+
|
|
18
|
+
### Variants
|
|
19
|
+
|
|
20
|
+
Choose the surface treatment that matches the card's hierarchy.
|
|
21
|
+
|
|
22
|
+
| Variants | Purpose | Usage notes |
|
|
23
|
+
| :---------- | :--------------------------- | :------------------------------------------------------------- |
|
|
24
|
+
| `primary` | Standard grouped surface. | Use for the main card or focused section within a page area. |
|
|
25
|
+
| `secondary` | Lower-emphasis grouped area. | Use when header and footer should sit behind the card surface. |
|
|
26
|
+
|
|
27
|
+
### Behavior
|
|
28
|
+
|
|
29
|
+
- **Mouse and touch**: Card has no built-in interaction. Interactive controls inside the card keep their own behavior.
|
|
30
|
+
- **Keyboard**: Card does not enter the tab order unless you add focusable content inside it.
|
|
31
|
+
- **Focus management**: do not move focus to the card container; move focus to meaningful headings or controls when needed.
|
|
32
|
+
- **Composition**: keep Card.Header, Card.Body, and Card.Footer in visual reading order when using multiple sections.
|
|
33
|
+
|
|
34
|
+
### Accessibility
|
|
35
|
+
|
|
36
|
+
- Use Card as a visual grouping container, not as a landmark by default.
|
|
37
|
+
- Include a visible heading in Card.Header when the grouped content needs a label.
|
|
38
|
+
- Preserve semantic HTML for the content inside the card, such as headings, lists, tables, forms, links, and buttons.
|
|
39
|
+
- Keep actions in Card.Footer related to the card content they affect.
|
|
40
|
+
- Do not rely on the card surface color alone to communicate status, priority, or selection.
|
|
41
|
+
|
|
42
|
+
### Content
|
|
43
|
+
|
|
44
|
+
- Keep card headings short and specific to the grouped content.
|
|
45
|
+
- Put primary details in Card.Body and supporting actions in Card.Footer.
|
|
46
|
+
- Avoid mixing unrelated topics or actions in the same card.
|
|
47
|
+
- Consider long customer-generated content and make sure it can wrap without hiding actions.
|
|
48
|
+
|
|
49
|
+
### Related
|
|
50
|
+
|
|
51
|
+
- **[Tile](components-tile.md)**: use when the entire surface is clickable or navigates.
|
|
52
|
+
- **[Flex](components-flex.md)**: use for alignment and spacing without adding a bordered container.
|
|
53
|
+
- **[Grid](components-grid.md)**: use for arranging multiple sections in responsive layouts.
|
|
54
|
+
|
|
55
|
+
## React
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
import { Card } from '@maxio-com/react-ui-components';
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Imports
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import { Body, Button, Card, Flex, Heading } from "@maxio-com/react-ui-components";
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Stories
|
|
68
|
+
|
|
69
|
+
### Default
|
|
70
|
+
|
|
71
|
+
Use Default for a simple static content group. Always wrap the main content in Card.Body so spacing remains consistent if header or footer sections are added later.
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
const Default = () => <Card>
|
|
75
|
+
<Card.Body>
|
|
76
|
+
<Body size="sm">Subscription details and supporting context stay grouped in one
|
|
77
|
+
surface.
|
|
78
|
+
</Body>
|
|
79
|
+
</Card.Body>
|
|
80
|
+
</Card>;
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### With Header
|
|
84
|
+
|
|
85
|
+
Use WithHeader when the card needs a visible title or section label. The heading level should fit the surrounding page hierarchy.
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
const WithHeader = () => <Card>
|
|
89
|
+
<Card.Header>
|
|
90
|
+
<Heading size="sm">Billing summary</Heading>
|
|
91
|
+
</Card.Header>
|
|
92
|
+
<Card.Body>
|
|
93
|
+
<Body size="sm">Review the customer plan, renewal date, and current balance before
|
|
94
|
+
making changes.
|
|
95
|
+
</Body>
|
|
96
|
+
</Card.Body>
|
|
97
|
+
</Card>;
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### With Footer
|
|
101
|
+
|
|
102
|
+
Use WithFooter when the card includes actions that apply to the grouped content. Keep footer actions specific to this card.
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
const WithFooter = () => <Card>
|
|
106
|
+
<Card.Body>
|
|
107
|
+
<Body size="sm">Send the upcoming invoice reminder after confirming the billing
|
|
108
|
+
contact.
|
|
109
|
+
</Body>
|
|
110
|
+
</Card.Body>
|
|
111
|
+
<Card.Footer>
|
|
112
|
+
<Button variant="primary">Send reminder</Button>
|
|
113
|
+
</Card.Footer>
|
|
114
|
+
</Card>;
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Secondary
|
|
118
|
+
|
|
119
|
+
Use Secondary for supporting panels that should sit behind the primary card hierarchy while still grouping related content.
|
|
120
|
+
|
|
121
|
+
```tsx
|
|
122
|
+
const Secondary = () => <Card variant="secondary">
|
|
123
|
+
<Card.Body>
|
|
124
|
+
<Body size="sm">Use a quieter surface for supplemental account notes or background
|
|
125
|
+
details.
|
|
126
|
+
</Body>
|
|
127
|
+
</Card.Body>
|
|
128
|
+
</Card>;
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Full
|
|
132
|
+
|
|
133
|
+
Use Full when the card has a title, primary content, and local actions. Header, body, and footer sections should remain in that order.
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
const Full = () => <Card>
|
|
137
|
+
<Card.Header>
|
|
138
|
+
<Heading size="sm">Payment method</Heading>
|
|
139
|
+
</Card.Header>
|
|
140
|
+
<Card.Body>
|
|
141
|
+
<Body size="sm">Visa ending in 4242 is used for subscription renewals and invoice
|
|
142
|
+
retries.
|
|
143
|
+
</Body>
|
|
144
|
+
</Card.Body>
|
|
145
|
+
<Card.Footer>
|
|
146
|
+
<Flex gap={2} justifyContent="end">
|
|
147
|
+
<Button variant="secondary">Cancel</Button>
|
|
148
|
+
<Button variant="primary">Update method</Button>
|
|
149
|
+
</Flex>
|
|
150
|
+
</Card.Footer>
|
|
151
|
+
</Card>;
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Full Secondary
|
|
155
|
+
|
|
156
|
+
Use FullSecondary for lower-emphasis sections that still need the complete header, body, and footer composition.
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
const FullSecondary = () => <Card variant="secondary">
|
|
160
|
+
<Card.Header>
|
|
161
|
+
<Heading size="sm">Account notes</Heading>
|
|
162
|
+
</Card.Header>
|
|
163
|
+
<Card.Body>
|
|
164
|
+
<Body size="sm">Capture internal context that supports the customer record without
|
|
165
|
+
competing with billing tasks.
|
|
166
|
+
</Body>
|
|
167
|
+
</Card.Body>
|
|
168
|
+
<Card.Footer>
|
|
169
|
+
<Flex gap={2} justifyContent="end">
|
|
170
|
+
<Button variant="secondary">Cancel</Button>
|
|
171
|
+
<Button variant="primary">Save notes</Button>
|
|
172
|
+
</Flex>
|
|
173
|
+
</Card.Footer>
|
|
174
|
+
</Card>;
|
|
175
|
+
```
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Chip
|
|
2
|
+
|
|
3
|
+
## Usage Guidelines
|
|
4
|
+
|
|
5
|
+
### Overview
|
|
6
|
+
|
|
7
|
+
Chip is used for compact, interactive values such as applied filters that can be selected, toggled, or dismissed without leaving the current context.
|
|
8
|
+
|
|
9
|
+
#### When to Use
|
|
10
|
+
|
|
11
|
+
- Use Chip for compact interactive values, such as applied filters, selected criteria, or removable tokens.
|
|
12
|
+
- Use Chip when the value can be toggled, selected, or dismissed in the current context.
|
|
13
|
+
- Use Chip in toolbars, filter summaries, and dense workflows where a full button would add too much visual weight.
|
|
14
|
+
|
|
15
|
+
#### When Not to Use
|
|
16
|
+
|
|
17
|
+
- Do not use Chip for static labels or status metadata. Use Tag instead.
|
|
18
|
+
- Do not use Chip for primary page actions. Use Button instead.
|
|
19
|
+
- Do not use Chip for navigation to another page or resource. Use Link or Button rendered as a link when stronger emphasis is required.
|
|
20
|
+
|
|
21
|
+
### Behavior
|
|
22
|
+
|
|
23
|
+
- **Mouse and touch**: pressing the chip button toggles selection and calls `onPress`; pressing the dismiss button calls `onDismiss`.
|
|
24
|
+
- **Keyboard**: the chip button and dismiss button are separate tab stops. Native button behavior supports Enter and Space activation.
|
|
25
|
+
- **Focus management**: keep both focus indicators visible. After dismissing a chip, move focus to the next logical control in the owning workflow.
|
|
26
|
+
- **Controlled state**: use `defaultSelected` for uncontrolled state, or pair `isSelected` with `onChange` when another component owns selection.
|
|
27
|
+
- **Dismissal**: provide `dismissLabel` whenever the chip can be dismissed so the icon-only button has an accessible name.
|
|
28
|
+
|
|
29
|
+
### Accessibility
|
|
30
|
+
|
|
31
|
+
- Use native `button` semantics for both the chip control and dismiss control.
|
|
32
|
+
- Provide a visible label that identifies the chip value.
|
|
33
|
+
- Use `aria-pressed` to communicate selected state on the chip button.
|
|
34
|
+
- Give the dismiss button a specific accessible name, such as "Remove Status: Active filter".
|
|
35
|
+
- Do not rely on color alone to communicate selection; preserve the pressed state and visible focus treatment.
|
|
36
|
+
|
|
37
|
+
### Content
|
|
38
|
+
|
|
39
|
+
- Keep labels short and specific, especially when chips appear in groups.
|
|
40
|
+
- Use the value the user selected, such as "Status: Active" or "Plan: Growth".
|
|
41
|
+
- Avoid generic labels like "Filter" when several chips appear together.
|
|
42
|
+
- Write dismiss labels that include the chip value when the visible label is not adjacent in the accessibility tree.
|
|
43
|
+
|
|
44
|
+
### Related
|
|
45
|
+
|
|
46
|
+
- **[Tag](components-tag.md)**: use for static labels, metadata, or statuses.
|
|
47
|
+
- **[Button](components-buttons-button.md)**: use for standalone actions with stronger emphasis.
|
|
48
|
+
- **[DataTable](components-data-table.md)**: chips are often used to summarize applied table filters.
|
|
49
|
+
|
|
50
|
+
## React
|
|
51
|
+
|
|
52
|
+
```jsx
|
|
53
|
+
import { Chip } from '@maxio-com/react-ui-components';
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### State Management
|
|
57
|
+
|
|
58
|
+
Chip can manage its own selected state with `defaultSelected`, or it can be controlled with `isSelected` and `onChange`.
|
|
59
|
+
|
|
60
|
+
Use uncontrolled state for a chip that only needs to toggle itself. Use controlled state when selection is owned by another component, such as a filter menu, table toolbar, or saved view.
|
|
61
|
+
|
|
62
|
+
## Imports
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
import { Chip } from "@maxio-com/react-ui-components";
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Prop Types
|
|
69
|
+
|
|
70
|
+
### Chip
|
|
71
|
+
|
|
72
|
+
| Prop | Type | Required | Default | Description | Source |
|
|
73
|
+
| --- | --- | --- | --- | --- | --- |
|
|
74
|
+
| `dismissLabel` | `string` | no | - | An aria-label for the dismiss button | TypeLiteral |
|
|
75
|
+
| `label` | `string` | yes | - | Button's visible label | TypeLiteral |
|
|
76
|
+
| `leadingIcon` | `string` | no | - | Adds a leading icon to the chip | TypeLiteral |
|
|
77
|
+
| `onDismiss` | `(() => void)` | no | - | Callback function when the dismiss button is pressed | TypeLiteral |
|
|
78
|
+
| `title` | `string` | no | - | Adds a title to the chip | TypeLiteral |
|
|
79
|
+
| `trailingIcon` | `string` | no | - | Adds a trailing icon to the chip | TypeLiteral |
|
|
80
|
+
|
|
81
|
+
## Stories
|
|
82
|
+
|
|
83
|
+
### Default
|
|
84
|
+
|
|
85
|
+
Use Chip for a selected, actionable value such as an applied filter. Include a dismiss button when users can remove that value from the current context.
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
const Default = (args: any) => {
|
|
89
|
+
const chipProps = {
|
|
90
|
+
...args,
|
|
91
|
+
onDismiss: args?.onDismiss && action('Chip dismissed'),
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
return <Chip {...chipProps}>{args.label}</Chip>;
|
|
95
|
+
};
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Selected
|
|
99
|
+
|
|
100
|
+
Use the selected state when the chip represents an active toggle, filter, or segmented choice. Keep `aria-pressed` synchronized with the visual selected state in static HTML.
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
const Selected = (args: any) => {
|
|
104
|
+
const chipProps = {
|
|
105
|
+
...args,
|
|
106
|
+
defaultSelected: true,
|
|
107
|
+
onDismiss: undefined,
|
|
108
|
+
trailingIcon: undefined,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
return <Chip {...chipProps}>{args.label}</Chip>;
|
|
112
|
+
};
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### With Icons
|
|
116
|
+
|
|
117
|
+
Use icons only when they help identify the chip value faster. Icons are supporting visuals; the visible label still provides the accessible name.
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
const WithIcons = (args: any) => {
|
|
121
|
+
const chipProps = {
|
|
122
|
+
...args,
|
|
123
|
+
onDismiss: undefined,
|
|
124
|
+
leadingIcon: 'dollar',
|
|
125
|
+
trailingIcon: 'arrow-right',
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
return <Chip {...chipProps}>{args.label}</Chip>;
|
|
129
|
+
};
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Controlled
|
|
133
|
+
|
|
134
|
+
Use controlled state when another component owns the selection, such as a filter menu, table toolbar, or saved view. Update `isSelected` from `onChange` so visual and announced state stay in sync.
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
const Controlled = (args: any) => {
|
|
138
|
+
const [isSelected, setSelected] = useState(false);
|
|
139
|
+
const chipProps = {
|
|
140
|
+
...args,
|
|
141
|
+
isSelected,
|
|
142
|
+
onDismiss: args?.onDismiss && action('Chip dismissed'),
|
|
143
|
+
onChange: (nextSelected: boolean) => {
|
|
144
|
+
setSelected(nextSelected);
|
|
145
|
+
action('Selected state')(String(nextSelected));
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
return <Chip {...chipProps}>{args.label}</Chip>;
|
|
150
|
+
};
|
|
151
|
+
```
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
# DataTable
|
|
2
|
+
|
|
3
|
+
## Usage Guidelines
|
|
4
|
+
|
|
5
|
+
### Overview
|
|
6
|
+
|
|
7
|
+
Displays TanStack Table data with Maxio table semantics, styling, and common interactions such as sorting, row selection, expansion, row actions, and pinned columns.
|
|
8
|
+
|
|
9
|
+
DataTable uses TanStack Table for column, row, sorting, selection, expansion,
|
|
10
|
+
and pinning state while rendering Maxio table markup and classes.
|
|
11
|
+
|
|
12
|
+
#### When to Use
|
|
13
|
+
|
|
14
|
+
- Use DataTable for tabular customer, invoice, subscription, or finance data.
|
|
15
|
+
- Use DataTable when rows need sorting, selection, expansion, row actions, or pinned columns.
|
|
16
|
+
- Use DataTable when a table needs consistent Maxio styling and accessible table semantics.
|
|
17
|
+
- Use DataTable when the product surface already defines data and columns with TanStack Table.
|
|
18
|
+
|
|
19
|
+
#### When Not to Use
|
|
20
|
+
|
|
21
|
+
- Do not use DataTable for simple key-value summaries or static comparison tables. Use primitive table components or layout primitives instead.
|
|
22
|
+
- Do not use DataTable for non-tabular card, list, or navigation layouts.
|
|
23
|
+
- Do not hand-code sorting, selection, expansion, or pinning behavior outside TanStack Table.
|
|
24
|
+
|
|
25
|
+
### Configuration
|
|
26
|
+
|
|
27
|
+
DataTable renders the Maxio table shell around TanStack data and column
|
|
28
|
+
definitions. Configure cell content, alignment, widths, grouped headers,
|
|
29
|
+
sorting behavior, and pinned columns through TanStack column definitions and
|
|
30
|
+
table state.
|
|
31
|
+
|
|
32
|
+
| Option | Purpose | Usage notes |
|
|
33
|
+
| :-------------------- | :------------------------------------------------------- | :------------------------------------------------------------------------------ |
|
|
34
|
+
| `enableSorting` | Allows sortable columns to cycle sort state. | Configure per-column sorting behavior in the TanStack column definition. |
|
|
35
|
+
| `enableRowSelection` | Adds checkbox controls for selecting rows. | Use controlled row selection state when selections drive actions outside table. |
|
|
36
|
+
| `enableExpanding` | Adds row expansion controls. | Use `rowsOnly` when the table should not show an expand-all header control. |
|
|
37
|
+
| `actions` | Adds a pinned row actions cell. | Use `IconButton` size `sm` for icon-only row actions. |
|
|
38
|
+
| `onRowAction` | Makes each parent row activate a primary row action. | Keep nested controls interactive without triggering the row action. |
|
|
39
|
+
| `SubRowComponent` | Renders custom expanded content connected to parent row. | Keep expanded content concise and related to the row. |
|
|
40
|
+
| `state.columnPinning` | Pins important columns to the left or right. | Set numeric column `size` values when multiple columns are pinned on one side. |
|
|
41
|
+
|
|
42
|
+
### Behavior
|
|
43
|
+
|
|
44
|
+
- **Mouse and touch**: header controls sort columns, row checkboxes select rows, expand controls show nested or custom row content, and row action controls activate row-specific commands.
|
|
45
|
+
- **Keyboard**: interactive controls are reachable with Tab. Buttons and checkboxes keep their native keyboard behavior. Actionable rows receive keyboard focus.
|
|
46
|
+
- **Focus management**: keep focus indicators visible on row controls, sortable headers, action buttons, links, and actionable rows.
|
|
47
|
+
- **Controlled state**: use TanStack Table state props when sorting, selection, expansion, or column pinning must be controlled by the product surface.
|
|
48
|
+
- **Column pinning**: set numeric `size` values for multiple pinned columns on the same side so TanStack can calculate sticky offsets correctly.
|
|
49
|
+
|
|
50
|
+
### Accessibility
|
|
51
|
+
|
|
52
|
+
- Use semantic `<table>`, `<thead>`, `<tbody>`, `<tr>`, `<th>`, and `<td>` markup.
|
|
53
|
+
- Keep sortable header state synchronized with `aria-sort`.
|
|
54
|
+
- Give selection, expansion, and row action controls clear accessible names.
|
|
55
|
+
- Label actionable rows from visible row content with `aria-labelledby`.
|
|
56
|
+
- Preserve table semantics when rendering links, tags, buttons, or custom content inside cells.
|
|
57
|
+
- Do not rely on color alone to communicate sorted, selected, expanded, or actionable state.
|
|
58
|
+
|
|
59
|
+
### Content
|
|
60
|
+
|
|
61
|
+
- Use concise column headers that match the data users need to compare.
|
|
62
|
+
- Put units in headers when they apply to the whole column, such as "Home Revenue (USD)".
|
|
63
|
+
- Keep row action labels specific to the command or provide a descriptive `aria-label` for icon-only actions.
|
|
64
|
+
- Prefer scannable cell values over long prose. Use expandable custom rows for secondary detail.
|
|
65
|
+
|
|
66
|
+
### Related
|
|
67
|
+
|
|
68
|
+
- **[Link](components-link.md)**: use for plain text navigation inside table cells.
|
|
69
|
+
- **[IconButton](components-buttons-iconbutton.md)**: use for icon-only row actions.
|
|
70
|
+
- **[Checkbox](components-forms-checkbox.md)**: use for custom selection controls outside DataTable.
|
|
71
|
+
|
|
72
|
+
## React
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
import { DataTable } from '@maxio-com/react-ui-components';
|
|
76
|
+
import { createColumnHelper } from '@tanstack/react-table';
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Column Configuration
|
|
80
|
+
|
|
81
|
+
Define table data and columns with TanStack Table, then pass those columns and
|
|
82
|
+
rows to DataTable.
|
|
83
|
+
|
|
84
|
+
```tsx
|
|
85
|
+
type Customer = {
|
|
86
|
+
name: string;
|
|
87
|
+
accountNumber: string;
|
|
88
|
+
homeRevenue: number;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const columnHelper = createColumnHelper<Customer>();
|
|
92
|
+
|
|
93
|
+
const columns = [
|
|
94
|
+
columnHelper.accessor('name', {
|
|
95
|
+
header: 'Name',
|
|
96
|
+
cell: (info) => info.getValue(),
|
|
97
|
+
}),
|
|
98
|
+
columnHelper.accessor('accountNumber', {
|
|
99
|
+
header: 'Account #',
|
|
100
|
+
cell: (info) => info.getValue(),
|
|
101
|
+
}),
|
|
102
|
+
columnHelper.accessor('homeRevenue', {
|
|
103
|
+
header: 'Home Revenue (USD)',
|
|
104
|
+
cell: (info) => info.getValue(),
|
|
105
|
+
}),
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
<DataTable columns={columns} data={customers} />;
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Use the column `meta` field for Maxio-specific presentation details.
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
columnHelper.accessor('homeRevenue', {
|
|
115
|
+
header: 'Home Revenue (USD)',
|
|
116
|
+
cell: (info) => info.getValue(),
|
|
117
|
+
meta: {
|
|
118
|
+
align: 'right',
|
|
119
|
+
width: '12rem',
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### State Management
|
|
125
|
+
|
|
126
|
+
DataTable can let TanStack Table manage interaction state internally. Control
|
|
127
|
+
state when sorting, selection, expansion, or pinned columns need to drive
|
|
128
|
+
application behavior outside the table.
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
<DataTable
|
|
132
|
+
columns={columns}
|
|
133
|
+
data={customers}
|
|
134
|
+
enableSorting
|
|
135
|
+
enableRowSelection
|
|
136
|
+
state={{
|
|
137
|
+
columnPinning: {
|
|
138
|
+
left: ['name', 'accountNumber'],
|
|
139
|
+
right: ['homeRevenue'],
|
|
140
|
+
},
|
|
141
|
+
}}
|
|
142
|
+
onSort={setSorting}
|
|
143
|
+
onSelect={setRowSelection}
|
|
144
|
+
onExpand={setExpanded}
|
|
145
|
+
/>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Expansion
|
|
149
|
+
|
|
150
|
+
Use nested `subRows` data for child records with the same shape as their parent
|
|
151
|
+
row. Use `SubRowComponent` when expanded content needs a custom layout that is
|
|
152
|
+
still attached to the row.
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
<DataTable
|
|
156
|
+
columns={columns}
|
|
157
|
+
data={customers}
|
|
158
|
+
enableExpanding="rowsOnly"
|
|
159
|
+
SubRowComponent={({ original }) => <CustomerDetails customer={original} />}
|
|
160
|
+
/>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Imports
|
|
164
|
+
|
|
165
|
+
```tsx
|
|
166
|
+
import {
|
|
167
|
+
DataTable,
|
|
168
|
+
HeaderCell,
|
|
169
|
+
Icon,
|
|
170
|
+
IconButton,
|
|
171
|
+
Link,
|
|
172
|
+
Table,
|
|
173
|
+
TableBody,
|
|
174
|
+
TableCell,
|
|
175
|
+
TableHead,
|
|
176
|
+
TableRow,
|
|
177
|
+
} from "@maxio-com/react-ui-components";
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Prop Types
|
|
181
|
+
|
|
182
|
+
### DataTable
|
|
183
|
+
|
|
184
|
+
| Prop | Type | Required | Default | Description | Source |
|
|
185
|
+
| --- | --- | --- | --- | --- | --- |
|
|
186
|
+
| `actions` | `((row: Row<TData>, table: Table<TData>) => ReactNode)` | no | - | render custom actions cell content | TypeLiteral |
|
|
187
|
+
| `actionsColumnSize` | `number` | no | - | width (in px) of the actions column; defaults to 40 | TypeLiteral |
|
|
188
|
+
| `aggregationFns` | `Record<string, AggregationFn<any>>` | no | - | - | TypeLiteral |
|
|
189
|
+
| `align` | `"left" \| "right"` | no | - | - | TypeLiteral |
|
|
190
|
+
| `enableExpanding` | `boolean \| "rowsOnly"` | no | - | Enable nested row expansion. Include `'rowsOnly'` for row-level toggles without group expand/collapse header control. | TypeLiteral |
|
|
191
|
+
| `filterFns` | `Record<string, FilterFn<any>>` | no | - | - | TypeLiteral |
|
|
192
|
+
| `isLoading` | `boolean` | no | - | - | TypeLiteral |
|
|
193
|
+
| `onExpand` | `((expanded: ExpandedState) => void)` | no | - | function to peek into expanding state changes | TypeLiteral |
|
|
194
|
+
| `onRowAction` | `((row: Row<TData>) => void)` | no | - | function called with the pressed row | TypeLiteral |
|
|
195
|
+
| `onSelect` | `((selected: RowSelectionState) => void)` | no | - | function to peek into selection state changes | TypeLiteral |
|
|
196
|
+
| `onSort` | `((selected: SortingState) => void)` | no | - | function to peek into sorting state changes | TypeLiteral |
|
|
197
|
+
| `pattern` | `boolean` | no | - | - | TypeLiteral |
|
|
198
|
+
| `size` | `"sm" \| "md" \| "lg"` | no | `md` | - | TypeLiteral |
|
|
199
|
+
| `sortingFns` | `Record<string, SortingFn<any>>` | no | - | - | TypeLiteral |
|
|
200
|
+
| `SubRowComponent` | `((row: Row<TData>) => ReactNode)` | no | - | - | TypeLiteral |
|
|
201
|
+
|
|
202
|
+
## Stories
|
|
203
|
+
|
|
204
|
+
### Default
|
|
205
|
+
|
|
206
|
+
Use DataTable when a data set needs table semantics plus common interactions such as sorting, row selection, nested expansion, custom row actions, and pinned action or control columns.
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
const Default = () => <DataTable
|
|
210
|
+
enableSorting
|
|
211
|
+
enableRowSelection
|
|
212
|
+
enableExpanding
|
|
213
|
+
data={customRowsData}
|
|
214
|
+
columns={customRowsColumns}
|
|
215
|
+
onRowAction={logRowAction}
|
|
216
|
+
actions={rowActions('ellipsis')} />;
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Sorting
|
|
220
|
+
|
|
221
|
+
Use sorting when users need to compare rows by one or more column values. Sortable headers cycle through ascending, descending, and unsorted states.
|
|
222
|
+
|
|
223
|
+
```tsx
|
|
224
|
+
const Sorting = () => <DataTable enableSorting />;
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Selecting
|
|
228
|
+
|
|
229
|
+
Use row selection when users need to choose individual rows or select all rows in the current table state for a follow-up action.
|
|
230
|
+
|
|
231
|
+
```tsx
|
|
232
|
+
const Selecting = () => <DataTable enableRowSelection />;
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Nested Rows
|
|
236
|
+
|
|
237
|
+
Use nested rows when child records share the same shape as their parent row. Include `subRows` on the data and enable expansion controls.
|
|
238
|
+
|
|
239
|
+
```tsx
|
|
240
|
+
const NestedRows = () => <DataTable enableExpanding />;
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Custom Rows
|
|
244
|
+
|
|
245
|
+
Use custom rows when an expanded row needs richer content than the standard column layout while remaining connected to the parent row.
|
|
246
|
+
|
|
247
|
+
```tsx
|
|
248
|
+
const CustomRows = () => <DataTable
|
|
249
|
+
data={customRowsData}
|
|
250
|
+
columns={customRowsColumns}
|
|
251
|
+
actions={rowActions()}
|
|
252
|
+
SubRowComponent={ExpandedBio}
|
|
253
|
+
enableExpanding />;
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Actions
|
|
257
|
+
|
|
258
|
+
Use row actions for controls scoped to a single row. The actions cell is pinned to the right so those controls remain available while scrolling.
|
|
259
|
+
|
|
260
|
+
```tsx
|
|
261
|
+
const Actions = () => <DataTable data={customerData} columns={customerColumns} actions={rowActions()} />;
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Row Action
|
|
265
|
+
|
|
266
|
+
Use row action behavior when the whole row should activate a primary row destination or action while preserving keyboard access.
|
|
267
|
+
|
|
268
|
+
```tsx
|
|
269
|
+
const RowAction = () => <DataTable data={customerData} columns={customerColumns} onRowAction={logRowAction} />;
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Components
|
|
273
|
+
|
|
274
|
+
Use component cells when mapped values need Maxio components such as links, tags, or other inline display elements.
|
|
275
|
+
|
|
276
|
+
```tsx
|
|
277
|
+
const Components = () => <DataTable pattern size="lg" />;
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Header Groups
|
|
281
|
+
|
|
282
|
+
Use header groups when related columns need a shared parent heading above their individual column headers.
|
|
283
|
+
|
|
284
|
+
```tsx
|
|
285
|
+
const HeaderGroups = () => <DataTable />;
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Column Pinning
|
|
289
|
+
|
|
290
|
+
Use column pinning when important identifying columns or action columns must stay visible while the table scrolls horizontally.
|
|
291
|
+
|
|
292
|
+
```tsx
|
|
293
|
+
const ColumnPinning = () => <div style={{ overflowX: 'auto' }}>
|
|
294
|
+
<DataTable
|
|
295
|
+
enableRowSelection
|
|
296
|
+
data={customerData}
|
|
297
|
+
columns={pinningDemoColumns}
|
|
298
|
+
actions={rowActions()}
|
|
299
|
+
state={{
|
|
300
|
+
columnPinning: {
|
|
301
|
+
left: ['Name', 'Number'],
|
|
302
|
+
right: ['Home Revenue Total (USD)'],
|
|
303
|
+
},
|
|
304
|
+
}} />
|
|
305
|
+
</div>;
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Custom
|
|
309
|
+
|
|
310
|
+
Use the primitive table components only for simple static tables that do not need sorting, selection, expansion, pinning, or TanStack Table state.
|
|
311
|
+
|
|
312
|
+
```tsx
|
|
313
|
+
const Custom = () => (
|
|
314
|
+
<Table>
|
|
315
|
+
<TableHead>
|
|
316
|
+
<TableRow isHeader>
|
|
317
|
+
<HeaderCell colSpan={2}>Financial Summary</HeaderCell>
|
|
318
|
+
</TableRow>
|
|
319
|
+
<TableRow isHeader>
|
|
320
|
+
<HeaderCell></HeaderCell>
|
|
321
|
+
<HeaderCell>USD</HeaderCell>
|
|
322
|
+
</TableRow>
|
|
323
|
+
</TableHead>
|
|
324
|
+
<TableBody>
|
|
325
|
+
<TableRow>
|
|
326
|
+
<TableCell>Total Transactions:</TableCell>
|
|
327
|
+
<TableCell>28,000.00</TableCell>
|
|
328
|
+
</TableRow>
|
|
329
|
+
<TableRow>
|
|
330
|
+
<TableCell>Total Revenue Scheduled:</TableCell>
|
|
331
|
+
<TableCell>28,000.00</TableCell>
|
|
332
|
+
</TableRow>
|
|
333
|
+
<TableRow>
|
|
334
|
+
<TableCell>Total Invoice Line Items Scheduled:</TableCell>
|
|
335
|
+
<TableCell>28,000.00</TableCell>
|
|
336
|
+
</TableRow>
|
|
337
|
+
<TableRow>
|
|
338
|
+
<TableCell>Total Open Balance:</TableCell>
|
|
339
|
+
<TableCell>7,437.00</TableCell>
|
|
340
|
+
</TableRow>
|
|
341
|
+
</TableBody>
|
|
342
|
+
</Table>
|
|
343
|
+
);
|
|
344
|
+
```
|