@acronis-platform/ui-react 5.5.9 → 7.0.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/components/ui/chart/chart.js +14 -11
- package/dist/components/ui/chart/chart.js.map +1 -1
- package/dist/components/ui/chart-state/chart-state.js +47 -37
- package/dist/components/ui/chart-state/chart-state.js.map +1 -1
- package/dist/components/ui/chart-widget/chart-widget.js +21 -23
- package/dist/components/ui/chart-widget/chart-widget.js.map +1 -1
- package/dist/components/ui/data-table/data-table.js +174 -173
- package/dist/components/ui/data-table/data-table.js.map +1 -1
- package/dist/components/ui/dialog/dialog.js +52 -38
- package/dist/components/ui/dialog/dialog.js.map +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu.js +8 -2
- package/dist/components/ui/dropdown-menu/dropdown-menu.js.map +1 -1
- package/dist/components/ui/page-header/page-header.js +4 -4
- package/dist/components/ui/page-header/page-header.js.map +1 -1
- package/dist/components/ui/pie-chart/pie-chart.js +88 -84
- package/dist/components/ui/pie-chart/pie-chart.js.map +1 -1
- package/dist/index.js +45 -46
- package/dist/llms/chart-state.md +81 -164
- package/dist/llms/chart-widget.md +27 -25
- package/dist/llms/data-table.md +24 -14
- package/dist/llms/dialog-root.md +40 -13
- package/dist/llms/dialog.md +109 -14
- package/dist/llms/dropdown-menu.md +68 -3
- package/dist/llms/page-header.md +68 -11
- package/dist/llms/stepper-item.md +10 -7
- package/dist/llms.txt +4 -4
- package/dist/react.js +45 -46
- package/dist/src/components/ui/chart/chart.d.ts +3 -3
- package/dist/src/components/ui/chart-state/chart-state.d.ts +5 -14
- package/dist/src/components/ui/chart-state/index.d.ts +0 -1
- package/dist/src/components/ui/chart-widget/chart-widget.d.ts +10 -15
- package/dist/src/components/ui/data-table/data-table.d.ts +11 -5
- package/dist/src/components/ui/data-table/data-table.docs.d.ts +10 -4
- package/dist/src/components/ui/dialog/dialog.d.ts +10 -0
- package/dist/src/components/ui/dialog/dialog.docs.d.ts +7 -1
- package/dist/src/components/ui/dropdown-menu/dropdown-menu.d.ts +8 -1
- package/dist/src/components/ui/dropdown-menu/index.d.ts +1 -1
- package/dist/src/components/ui/page-header/page-header.d.ts +3 -1
- package/dist/src/components/ui/pie-chart/pie-chart.d.ts +1 -1
- package/dist/ui-react.css +1 -1
- package/package.json +13 -13
- package/dist/components/ui/chart-state/chart-state-illustrations.js +0 -412
- package/dist/components/ui/chart-state/chart-state-illustrations.js.map +0 -1
- package/dist/src/components/ui/chart-state/chart-state-illustrations.d.ts +0 -6
package/dist/llms/chart-state.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ChartState
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Shared loading / empty / warning / error / number visuals for a chart slot. Empty, warning, and error use the Breakpoints visual treatment: a 64px status circle with a 24px glyph and centered message. Number shows a centered KPI value; loading uses the shared spinner. Consumers select the state and may localize its content through `description`. Distinct from `WidgetPlaceholder`, which is the composable skeleton for a non-chart widget.
|
|
4
4
|
|
|
5
5
|
**Status:** draft · **Category:** data-display · **Since:** v0.58.0
|
|
6
6
|
|
|
@@ -14,190 +14,107 @@ import { ChartState } from '@acronis-platform/ui-react'
|
|
|
14
14
|
|
|
15
15
|
```tsx
|
|
16
16
|
<ChartState state="loading" />
|
|
17
|
-
<ChartState state="empty"
|
|
18
|
-
<ChartState
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
/>
|
|
17
|
+
<ChartState state="empty" description={t('chart.noData')} />
|
|
18
|
+
<ChartState state="warning" description={t('chart.partialData')} />
|
|
19
|
+
<ChartState state="error" description={t('chart.loadError')} />
|
|
20
|
+
<ChartState state="number" description="0 GB" />
|
|
22
21
|
```
|
|
23
22
|
|
|
24
|
-
A shared
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
A shared visual state for one chart slot. Use it while chart data is loading,
|
|
24
|
+
missing, incomplete, or has failed, or when a KPI should show its numeric empty
|
|
25
|
+
value. Empty, warning, and error share the Breakpoints state circles; number
|
|
26
|
+
uses the centered disabled-style KPI value; loading uses the shared spinner.
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
> `InputSelectStatus`. There is no `--ui-chart-*` token tier yet, so it themes
|
|
31
|
-
> from existing semantic tokens directly.
|
|
32
|
-
|
|
33
|
-
## When to use
|
|
34
|
-
|
|
35
|
-
- A chart cannot render yet (data in flight), has no data to plot, or failed to
|
|
36
|
-
load — swap the chart for the matching `ChartState`.
|
|
37
|
-
- You want the same placeholder across every chart type, rather than each chart
|
|
38
|
-
hand-rolling its own.
|
|
39
|
-
|
|
40
|
-
## When not to use
|
|
41
|
-
|
|
42
|
-
- A full-page empty state (illustration, title, description, primary action) —
|
|
43
|
-
use the larger `Empty` component instead.
|
|
44
|
-
- A bare loading indicator with no surrounding message — use `Spinner` directly.
|
|
45
|
-
|
|
46
|
-
## Example
|
|
28
|
+
Consumers select the semantic state and pass localized or context-specific
|
|
29
|
+
content through `description`. `ChartState` does not infer the state from data.
|
|
47
30
|
|
|
48
31
|
```tsx
|
|
49
|
-
import { ChartState
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
Try again
|
|
60
|
-
</Button>
|
|
61
|
-
}
|
|
62
|
-
/>
|
|
63
|
-
);
|
|
64
|
-
if (!data.length) return <ChartState state="empty" />;
|
|
65
|
-
|
|
66
|
-
return (
|
|
67
|
-
<ChartContainer config={config} className="h-[300px] w-[500px]">
|
|
68
|
-
{/* …the chart… */}
|
|
69
|
-
</ChartContainer>
|
|
70
|
-
);
|
|
71
|
-
}
|
|
32
|
+
import { ChartState } from '@acronis-platform/ui-react';
|
|
33
|
+
|
|
34
|
+
if (status === 'loading') return <ChartState state="loading" />;
|
|
35
|
+
if (status === 'warning')
|
|
36
|
+
return <ChartState state="warning" description={t('chart.partialData')} />;
|
|
37
|
+
if (status === 'error')
|
|
38
|
+
return <ChartState state="error" description={t('chart.loadError')} />;
|
|
39
|
+
if (isEmptyKpi) return <ChartState state="number" description="0 GB" />;
|
|
40
|
+
if (!data.length)
|
|
41
|
+
return <ChartState state="empty" description={t('chart.noData')} />;
|
|
72
42
|
```
|
|
73
43
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
label, and `action` to add a retry affordance to the error state. Long unbroken
|
|
77
|
-
error descriptions (CTI paths, API URLs) wrap at word boundaries and scroll
|
|
78
|
-
vertically when they exceed the slot height.
|
|
44
|
+
`ChartState` fills the chart's slot. It does not own the containing widget card
|
|
45
|
+
or dashboard composition; see `ChartWidget` for a single chart card.
|
|
79
46
|
|
|
80
47
|
## Props
|
|
81
48
|
|
|
82
49
|
| Prop | Type | Default | Required | Description |
|
|
83
50
|
|------|------|---------|----------|-------------|
|
|
84
|
-
| `state` | `'loading' | 'empty' | 'error'` | — | yes | Which
|
|
85
|
-
| `
|
|
86
|
-
| `description` | `ReactNode` | — | no | Text shown below the illustration or glyph. Defaults to `"Data is loading…"` / `"No data found"` / `"Something went wrong"` based on `state`. Pass a value to override for any state. |
|
|
87
|
-
| `action` | `ReactNode` | — | no | Trailing action rendered for the `error` state only (e.g. a "Try again" button). |
|
|
51
|
+
| `state` | `'loading' | 'empty' | 'warning' | 'error' | 'number'` | — | yes | Which state to show. Loading uses the shared spinner; empty, warning, and error use the shared circular status icon; number shows a centered disabled-style KPI value. Error is an assertive alert; other states are polite status messages. |
|
|
52
|
+
| `description` | `ReactNode` | — | no | Localized or context-specific content. For `number`, this is the numeric readout. Defaults to "Data is loading…", "No data found", "Data may be incomplete", "Something went wrong", or "0". |
|
|
88
53
|
|
|
89
54
|
## Behavior
|
|
90
55
|
|
|
91
56
|
### Rendering per state
|
|
92
57
|
|
|
93
58
|
- **Given** `state="loading"`, **when** rendered, **then** it shows the shared
|
|
94
|
-
`Spinner`
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
- **Given**
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
`empty` is the one state the design draws per chart type: an area silhouette for
|
|
134
|
-
an area chart, a ring for a donut, a funnel for a funnel. An empty widget then
|
|
135
|
-
still says what it _would_ have shown, which a single generic glyph can't.
|
|
136
|
-
|
|
137
|
-
`variant` selects it. `donut` and `radial` share one ring — a radial-bar widget
|
|
138
|
-
with no data has nothing to tell it apart. Without a `variant` the empty state
|
|
139
|
-
shows no artwork — just the text.
|
|
140
|
-
|
|
141
|
-
The geometry is exported from the Figma instances rather than redrawn, and every
|
|
142
|
-
path is `currentColor`: the tone is set once on the container, so brand and theme
|
|
143
|
-
overrides reach the artwork. Two of the eleven silhouettes use a second, fainter
|
|
144
|
-
tone (the table and metric-list ones tint their header row darker than the body
|
|
145
|
-
rows); that hierarchy is kept as `fill-opacity` on the same colour rather than a
|
|
146
|
-
second token.
|
|
147
|
-
|
|
148
|
-
The caption is **one line, in one style**. Figma styles it `body/default` on
|
|
149
|
-
`text/onSurface/primary` — 14/24, centred, _not_ muted — which is what the root
|
|
150
|
-
already applies, so the description and the fallback status label read
|
|
151
|
-
identically. For a per-type empty state that line is the `description`: the mockups draw the silhouette over "Widget description" with no
|
|
152
|
-
status label, because the artwork already says "no data" and the sentence worth
|
|
153
|
-
the space is what the widget _would_ show. With no `description` it falls back to
|
|
154
|
-
the status label, so a caller that only sets `variant` still reads sensibly.
|
|
155
|
-
|
|
156
|
-
`loading` and `error` deliberately keep one shared treatment — the design only
|
|
157
|
-
redesigned `empty`.
|
|
158
|
-
|
|
159
|
-
### Not `WidgetPlaceholder`
|
|
160
|
-
|
|
161
|
-
Two components, two jobs, and they are not interchangeable:
|
|
162
|
-
|
|
163
|
-
- **`ChartState`** is the placeholder _inside_ a chart's slot. It fills whatever
|
|
164
|
-
gives the slot its height, renders one of three states, and is what a chart
|
|
165
|
-
widget swaps in for its plot.
|
|
166
|
-
- **`WidgetPlaceholder`** is a composable skeleton with its own header, footer
|
|
167
|
-
and action parts, plus an `interactive` affordance — for a dashboard widget
|
|
168
|
-
that isn't a chart, or a whole tile that is still being set up.
|
|
169
|
-
|
|
170
|
-
`WidgetPlaceholder` predates the per-type empty states and is used by consuming
|
|
171
|
-
MFEs, so it stays.
|
|
59
|
+
large `Spinner` and the default message "Data is loading…".
|
|
60
|
+
- **Given** `state="empty"`, **when** rendered, **then** it shows the neutral
|
|
61
|
+
circle with the `CircleMinusGray` glyph and the default message "No data
|
|
62
|
+
found".
|
|
63
|
+
- **Given** `state="warning"`, **when** rendered, **then** it shows the warning
|
|
64
|
+
circle with the `TriangleWarningYellow` glyph and the default message "Data
|
|
65
|
+
may be incomplete".
|
|
66
|
+
- **Given** `state="error"`, **when** rendered, **then** it shows the critical
|
|
67
|
+
circle with the `DiamondWarningRed` glyph and the default message "Something
|
|
68
|
+
went wrong".
|
|
69
|
+
- **Given** `state="number"`, **when** rendered, **then** it shows the centered
|
|
70
|
+
disabled-style numeric value "0" without a state icon.
|
|
71
|
+
- **Given** empty, warning, or error, **when** rendered, **then** the group is
|
|
72
|
+
centered and uses a 64px state circle, a 24px glyph, 12px separation, and
|
|
73
|
+
centered 14px / 24px text.
|
|
74
|
+
|
|
75
|
+
### Copy
|
|
76
|
+
|
|
77
|
+
- **Given** a `description`, **when** rendered in any state, **then** the supplied
|
|
78
|
+
content replaces that state's fallback message. Consumers provide localized
|
|
79
|
+
or context-specific copy.
|
|
80
|
+
|
|
81
|
+
### Layout and overflow
|
|
82
|
+
|
|
83
|
+
- **Given** any state, **when** placed in a chart slot, **then** the block fills
|
|
84
|
+
the slot without forcing a minimum height beyond its content.
|
|
85
|
+
- **Given** loading, empty, or warning, **when** rendered, **then** the content
|
|
86
|
+
is centered in the slot.
|
|
87
|
+
- **Given** `state="error"` with a short message, **when** rendered, **then**
|
|
88
|
+
the icon and message are vertically centered.
|
|
89
|
+
- **Given** an error with a long message, **when** it exceeds the slot height,
|
|
90
|
+
**then** the icon remains fully visible, the state scrolls vertically, and
|
|
91
|
+
unbroken strings wrap within the available width.
|
|
92
|
+
|
|
93
|
+
### Composition boundary
|
|
94
|
+
|
|
95
|
+
`ChartState` controls the state visuals inside one chart slot. It does not set
|
|
96
|
+
the chart-widget card border or arrange a group of widgets; those belong to
|
|
97
|
+
their respective component or consuming application.
|
|
172
98
|
|
|
173
99
|
## Accessibility
|
|
174
100
|
|
|
175
|
-
- The root is
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
- The live-region attributes (`role` / `aria-live`) are applied after the prop
|
|
189
|
-
spread, so the state's a11y contract is not clobbered by a consumer-passed
|
|
190
|
-
attribute.
|
|
191
|
-
- The label text is a real `<p>`, so the state message is always in the
|
|
192
|
-
accessible tree — the glyph is decorative and does not need its own label.
|
|
193
|
-
- **Do not rely on the glyph color alone** to convey the state — the label
|
|
194
|
-
carries the meaning. Icon colors (`--ui-glyph-on-status-info` /
|
|
195
|
-
`--ui-glyph-on-status-warning`) and the label (`--ui-text-on-surface-primary`)
|
|
196
|
-
resolve to semantic tokens that meet contrast in both themes.
|
|
197
|
-
- If the error state offers a retry, pass an actual interactive control as
|
|
198
|
-
`action` (a `Button`) so it is focusable and keyboard-operable.
|
|
101
|
+
- The root is the live region: loading, empty, warning, and number use
|
|
102
|
+
`role="status"` with `aria-live="polite"`; error uses `role="alert"` with
|
|
103
|
+
`aria-live="assertive"`.
|
|
104
|
+
- The root live-region attributes are applied after the prop spread, so the
|
|
105
|
+
selected state's announcement semantics cannot be overwritten by consumer
|
|
106
|
+
props.
|
|
107
|
+
- The loading Spinner and state glyphs are decorative. The displayed content
|
|
108
|
+
supplies the state meaning independently of icon color.
|
|
109
|
+
- The root does not carry `aria-busy`. This placeholder is unmounted when the
|
|
110
|
+
chart replaces it, and some screen readers defer announcements inside a busy
|
|
111
|
+
region. Put `aria-busy` on the chart-slot container if a busy signal is needed.
|
|
112
|
+
- Long error text can scroll vertically, and long unbroken strings wrap within
|
|
113
|
+
the available width.
|
|
199
114
|
|
|
200
115
|
## Contrast
|
|
201
116
|
|
|
202
|
-
|
|
203
|
-
|
|
117
|
+
Message text uses `--ui-text-on-surface-primary`. The state glyphs are the
|
|
118
|
+
multi-color design assets, placed on semantic neutral, warning, and critical
|
|
119
|
+
background tokens. The textual message communicates meaning without relying on
|
|
120
|
+
color.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ChartWidget
|
|
2
2
|
|
|
3
|
-
> The dashboard card a chart sits in: a `Card` with the standard widget header (title, optional filter chip and the ⋯ actions menu) and an optional metric readout above the plot. Adds the one thing a `Card` doesn't know about — the body's loading / empty / error
|
|
3
|
+
> The dashboard card a chart sits in: a `Card` with the standard widget header (title, optional filter chip and the ⋯ actions menu) and an optional metric readout above the plot. Adds the one thing a `Card` doesn't know about — the body's loading / empty / warning / error / number state — and re-implements nothing else. The consumer selects the state explicitly; the widget does not infer it from chart data. its `header` is `CardHeaderProps`, spread. It declares no size: the grid sizes the card and the widget passes that height down, so a `size-full` chart fills whatever the header leaves. The per-type chart components stay card-less, so a chart is still usable outside a widget.
|
|
4
4
|
|
|
5
5
|
**Status:** draft · **Category:** data-display · **Since:** v2.1.0
|
|
6
6
|
|
|
@@ -35,10 +35,11 @@ readout, then the plot. `ChartWidget` is that composition — and only that.
|
|
|
35
35
|
|
|
36
36
|
## What it adds
|
|
37
37
|
|
|
38
|
-
One thing a `Card` legitimately doesn't know about: **what the body shows
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
not
|
|
38
|
+
One thing a `Card` legitimately doesn't know about: **what the body shows for
|
|
39
|
+
an explicitly selected state.** `state="loading" | "empty" | "warning" |
|
|
40
|
+
"error" | "number"` renders `ChartState` in place of the metric and chart. The
|
|
41
|
+
consumer chooses the state; the widget does not infer it from data. Card chrome
|
|
42
|
+
remains consistent for each state.
|
|
42
43
|
|
|
43
44
|
## What it doesn't add
|
|
44
45
|
|
|
@@ -63,7 +64,7 @@ the rest of the card. See `behavior.md`.
|
|
|
63
64
|
| ------------------ | ------------------------------------------------------------------ |
|
|
64
65
|
| `index.yaml` | Identity, category, status, `since`. |
|
|
65
66
|
| `api.yaml` | The prop contract and the per-framework adapters. |
|
|
66
|
-
| `anatomy.yaml` | Parts, the schematic, and the
|
|
67
|
+
| `anatomy.yaml` | Parts, the schematic, and the five widget states. |
|
|
67
68
|
| `behavior.md` | Composition, how the height reaches the plot, state, localization. |
|
|
68
69
|
| `accessibility.md` | Roles, the placeholder's live region, header controls. |
|
|
69
70
|
| `tokens.yaml` | The `--ui-*` tokens the widget references. |
|
|
@@ -87,12 +88,10 @@ chart.
|
|
|
87
88
|
| `header` | `CardHeaderProps` | — | no | The card header, forwarded verbatim to `CardHeader` — `title`, `description`, `extras` (a filter chip), `actions` (the ⋯ menu), `isDraggable`, `isSwitchable`, `hasAvatar`, `hasRename`, `isCollapsible`. Omit for a header-less widget. |
|
|
88
89
|
| `orientation` | `'vertical' | 'horizontal'` | `vertical` | no | How the `metric` and plot are arranged inside the card body. `vertical` (default) — metric above the plot, full width; the metric takes its natural height and the plot fills the rest. `horizontal` — metric and plot side by side, each `flex-1`; use for compact (sm/288px) widgets where vertical space is at a premium. |
|
|
89
90
|
| `metric` | `ReactNode` | — | no | The readout beside or above the plot (depending on `orientation`), typically a `Metric`. |
|
|
90
|
-
| `
|
|
91
|
-
| `
|
|
92
|
-
| `stateDescription` | `ReactNode` | — | no | Text below the placeholder illustration or glyph. Forwarded to `ChartState` as `description`. Defaults to the per-state built-in ("Data is loading…" / "No data found" / "Something went wrong"). |
|
|
93
|
-
| `stateAction` | `ReactNode` | — | no | Trailing action on the `error` placeholder — e.g. a retry button. |
|
|
91
|
+
| `state` | `'loading' | 'empty' | 'warning' | 'error' | 'number'` | — | no | Renders `ChartState` in place of the metric and plot, keeping the header. The consumer selects the state; no state is inferred from the data. Card chrome remains consistent for all states. |
|
|
92
|
+
| `stateDescription` | `ReactNode` | — | no | Localized or context-specific content shown by `ChartState`. For `number`, pass the numeric value and unit. Defaults to per-state fallback content, including `0` for `number`. |
|
|
94
93
|
| `bodyClassName` | `string` | — | no | Class for the card body. Rarely needed — the body already fills the card. For the case where neither the grid nor the content gives a height, e.g. a placeholder-only widget outside a sized cell. |
|
|
95
|
-
| `children` | `ReactNode` | — | no | The chart
|
|
94
|
+
| `children` | `ReactNode` | — | no | The selected state replaces this chart and the metric while `state` is set. |
|
|
96
95
|
| `render` | `useRender.RenderProp` | — | no | Replace the rendered `<div>` with another element or component (Base UI composition), forwarded to `Card`. How a dashboard gives each widget a landmark role — `render={<section aria-label="Sessions" />}` — which is the one thing the widget can't infer for itself. |
|
|
97
96
|
|
|
98
97
|
## Behavior
|
|
@@ -142,21 +141,23 @@ design constraint, and hard-coding them would have fought the grid.
|
|
|
142
141
|
|
|
143
142
|
### State
|
|
144
143
|
|
|
145
|
-
`state`
|
|
144
|
+
The consumer selects `state` explicitly; the widget does not infer it from chart
|
|
145
|
+
data. When set, `ChartState` replaces both the `metric` and `children`. The
|
|
146
|
+
header stays. The `number` state shows a centered numeric KPI value.
|
|
146
147
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
The card surface and border remain the same for loading, empty, warning, error,
|
|
149
|
+
and number. State-specific visuals are contained within `ChartState` in the
|
|
150
|
+
body.
|
|
150
151
|
|
|
151
|
-
`ChartState` owns the live-region contract (`role="status"` for loading
|
|
152
|
-
`role="alert"` for error), so the announcement follows
|
|
153
|
-
than being re-declared on the widget.
|
|
152
|
+
`ChartState` owns the live-region contract (`role="status"` for loading, empty,
|
|
153
|
+
warning, and number; `role="alert"` for error), so the announcement follows
|
|
154
|
+
the state rather than being re-declared on the widget.
|
|
154
155
|
|
|
155
156
|
### Localization
|
|
156
157
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
158
|
+
The header's `title` / `description`, the metric's labels, and
|
|
159
|
+
`stateDescription` can be supplied by the consumer. The `stateDescription`
|
|
160
|
+
prop lets applications localize or contextualize the state content.
|
|
160
161
|
|
|
161
162
|
## Accessibility
|
|
162
163
|
|
|
@@ -187,7 +188,7 @@ name, so a chart inside should not repeat it in its own accessible name.
|
|
|
187
188
|
## The placeholder is the live region
|
|
188
189
|
|
|
189
190
|
While `state` is set, `ChartState` is the live region — `role="status"`
|
|
190
|
-
(`aria-live="polite"`) for loading
|
|
191
|
+
(`aria-live="polite"`) for loading, empty, warning, and number; `role="alert"`
|
|
191
192
|
(`aria-live="assertive"`) for error. The widget deliberately does **not** add
|
|
192
193
|
`aria-busy` around it: the placeholder is unmounted and replaced by the plot
|
|
193
194
|
rather than un-busied, and some assistive tech defers announcing a busy region's
|
|
@@ -203,7 +204,8 @@ switch, rename button and collapse trigger each take a label prop with a
|
|
|
203
204
|
default, and the `actions` slot is the caller's own control (an icon button
|
|
204
205
|
needs its own `aria-label` — the mockups' ⋯ menu has no visible text).
|
|
205
206
|
|
|
206
|
-
##
|
|
207
|
+
## State meaning
|
|
207
208
|
|
|
208
|
-
|
|
209
|
-
|
|
209
|
+
The widget card border stays consistent across states. `ChartState` supplies a
|
|
210
|
+
state icon and message (or the numeric KPI value), so meaning does not rely on
|
|
211
|
+
color alone.
|
package/dist/llms/data-table.md
CHANGED
|
@@ -72,10 +72,12 @@ from it too (see **Server-driven usage** below).
|
|
|
72
72
|
- **Infinite scroll** — set `paginationMode="infinite"` and pass the full
|
|
73
73
|
accumulated `data`, `hasNextPage`, `isLoadingMore`, and an `onLoadMore`
|
|
74
74
|
callback. DataTable renders a sentinel row that calls `onLoadMore` once it
|
|
75
|
-
scrolls into view
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
scrolls into view. While `isLoadingMore` is true, it hides the sentinel and
|
|
76
|
+
shows a centered status row with "Loading more data..."; override
|
|
77
|
+
`loadingMoreLabel` to localize it. Loaded rows stay visible. The `skeleton`
|
|
78
|
+
prop remains the initial-load treatment. The sentinel needs at least one row
|
|
79
|
+
already rendered — it can't drive an empty table's very first fetch, so seed
|
|
80
|
+
the first page yourself (e.g. on mount). Pass `loadMoreRootMargin` (e.g. `'400px'`) to fire `onLoadMore`
|
|
79
81
|
before the sentinel is literally visible, so the fetch has a head start on
|
|
80
82
|
the user's scroll — tune it relative to your page size, since a large
|
|
81
83
|
margin with small pages can trigger several `onLoadMore` calls back-to-back
|
|
@@ -153,13 +155,13 @@ as `children` of the toolbar for per-column filtering.
|
|
|
153
155
|
| `expand-label` | `string` | `'Expand row'` | no | On the expand-trigger part — accessible name while the row is collapsed. Override to localize. |
|
|
154
156
|
| `collapse-label` | `string` | `'Collapse row'` | no | On the expand-trigger part — accessible name while the row is expanded. Override to localize. |
|
|
155
157
|
| `sort-label` | `(title: string) => string` | `(title) => `Sort by ${title}`` | no | On the column-header part — builds the accessible label of the sort toggle from the column title. Override to localize. |
|
|
156
|
-
| `table` | `Table<TData>` | — | no | Render from an externally-built TanStack `table` instance instead of DataTable's own — DataTable then owns no state. Makes the following no-ops (configure the equivalent on the external instance instead): columnVisibility, onColumnVisibilityChange, onColumnSizingChange, enableColumnResizing, getRowCanExpand, manualSorting, sorting, onSortingChange, paginationMode, onLoadMore, loadMoreRootMargin, hasNextPage, isLoadingMore. meta.pin-driven column pinning is also skipped — pin/unpin the external instance directly via TanStack's `column.pin()`. |
|
|
158
|
+
| `table` | `Table<TData>` | — | no | Render from an externally-built TanStack `table` instance instead of DataTable's own — DataTable then owns no state. Makes the following no-ops (configure the equivalent on the external instance instead): columnVisibility, onColumnVisibilityChange, onColumnSizingChange, enableColumnResizing, getRowCanExpand, manualSorting, sorting, onSortingChange, paginationMode, onLoadMore, loadMoreRootMargin, hasNextPage, isLoadingMore, loadingMoreLabel. meta.pin-driven column pinning is also skipped — pin/unpin the external instance directly via TanStack's `column.pin()`. |
|
|
157
159
|
| `getRowCanExpand` | `(row: Row<TData>) => boolean` | — | no | Enables row expansion for rows that return true. Pair with renderExpandedRow. |
|
|
158
160
|
| `renderExpandedRow` | `(row: Row<TData>) => ReactNode` | — | no | Renders the detail content for an expanded row. |
|
|
159
161
|
| `striped` | `boolean` | `false` | no | Alternating row backgrounds (borrowed from the Vue AvTable). |
|
|
160
162
|
| `bordered` | `boolean` | `false` | no | Vertical borders between columns (rows already have horizontal borders). |
|
|
161
163
|
| `highlightCurrentRow` | `boolean` | `false` | no | Highlight the row the user last clicked (the "current" row). |
|
|
162
|
-
| `skeleton` | `boolean` | `false` | no | Render
|
|
164
|
+
| `skeleton` | `boolean` | `false` | no | Render shared Skeleton placeholders for initial loading, replacing the data rows while keeping the header visible. |
|
|
163
165
|
| `skeletonRows` | `number` | `5` | no | Number of skeleton rows when skeleton is set. |
|
|
164
166
|
| `enableColumnResizing` | `boolean` | `false` | no | Opt in to interactive column resizing — renders a drag handle at the trailing edge of each resizable header (TanStack's native `columnResizing`, `columnResizeMode: 'onChange'`). |
|
|
165
167
|
| `enableColumnReordering` | `boolean` | `false` | no | Opt in to column reordering by dragging a header cell onto another one (native HTML5 drag-and-drop driving TanStack's `columnOrder`; the dragged header dims while the gesture is in flight). Pinned columns are excluded — they're anchored to a table edge by definition. Pointer-only: there is no keyboard equivalent yet. No-op when `table` is passed. |
|
|
@@ -188,9 +190,10 @@ as `children` of the toolbar for per-column filtering.
|
|
|
188
190
|
| `renderRow` | `(row: Row<TData>, rowIndex: number) => ReactNode` | — | no | Renders a full row, bypassing DataTable's default per-cell `flexRender` path entirely. Use to swap in a custom, independently memoizable row component — the caller owns the row's markup and equality semantics. Reuse the exported `getCellStyle` / `getPinnedStyle` / `getColumnWidth` helpers to match DataTable's default cell styling if desired. Also bypasses `renderExpandedRow` — a row rendered via `renderRow` never gets an expanded-content row appended; read `row.getIsExpanded()` and render it yourself if needed. |
|
|
189
191
|
| `renderEmptyState` | `(context: { hasFilters: boolean }) => ReactNode` | — | no | Renders a custom empty state instead of the default "No results." row. Receives `hasFilters` (whether any column filter is currently applied) so the caller can distinguish "no data at all" from "no matches" — the copy/wording/localization stays the caller's job. |
|
|
190
192
|
| `paginationMode` | `'page' | 'infinite'` | `'page'` | no | `'page'` keeps today's client-paginated behavior. `'infinite'` omits the paginated row model — `data` is the full accumulated array the caller appends to on each `onLoadMore` — and renders a sentinel row that calls `onLoadMore` once it scrolls into view. The sentinel requires at least one row already rendered, so it cannot drive an empty table's very first fetch — seed the first page yourself (e.g. on mount) and use `onLoadMore` for subsequent pages. No-op when `table` is passed. Does not compose with virtualization; for a large accumulated list, virtualize the raw `Table` primitives yourself instead. |
|
|
191
|
-
| `loadMoreRootMargin` | `string` | — | no | Expands the sentinel's `IntersectionObserver` root margin (native CSS margin syntax, e.g. "400px") so `onLoadMore` fires before the sentinel is literally visible, reducing how often the trailing loading row is seen. `paginationMode="infinite"` only; no-op when `table` is passed. How far this actually prefetches also depends on page size — a large margin with small pages can trigger several `onLoadMore` calls back-to-back as the user scrolls normally, which is expected; tune it relative to page size. |
|
|
193
|
+
| `loadMoreRootMargin` | `string` | — | no | Expands the sentinel's `IntersectionObserver` root margin (native CSS margin syntax, e.g. "400px") so `onLoadMore` fires before the sentinel is literally visible, reducing how often the trailing loading status row is seen. `paginationMode="infinite"` only; no-op when `table` is passed. How far this actually prefetches also depends on page size — a large margin with small pages can trigger several `onLoadMore` calls back-to-back as the user scrolls normally, which is expected; tune it relative to page size. |
|
|
192
194
|
| `hasNextPage` | `boolean` | `false` | no | Whether more rows are available to load. `paginationMode="infinite"` only. |
|
|
193
|
-
| `isLoadingMore` | `boolean` | `false` | no | Whether a load is in flight — suppresses further `onLoadMore` calls and renders a
|
|
195
|
+
| `isLoadingMore` | `boolean` | `false` | no | Whether a load is in flight — suppresses further `onLoadMore` calls and renders a centered status row with `loadingMoreLabel`. The observer sentinel is omitted while loading. `paginationMode="infinite"` only; no-op when `table` is passed. |
|
|
196
|
+
| `loadingMoreLabel` | `string` | `'Loading more data...'` | no | Visible text in the infinite-scroll loading status row. Override to localize. `paginationMode="infinite"` only; no-op when `table` is passed. |
|
|
194
197
|
|
|
195
198
|
## Events
|
|
196
199
|
|
|
@@ -264,12 +267,18 @@ Scenario: Custom row rendering
|
|
|
264
267
|
Scenario: Infinite scroll
|
|
265
268
|
Given paginationMode="infinite" and hasNextPage is true
|
|
266
269
|
And at least one row is already rendered
|
|
267
|
-
|
|
270
|
+
And isLoadingMore is false
|
|
271
|
+
Then an aria-hidden sentinel row renders after the loaded rows
|
|
268
272
|
When the sentinel scrolls into view and isLoadingMore is false
|
|
269
273
|
Then onLoadMore fires
|
|
270
274
|
And no further onLoadMore calls fire while isLoadingMore is true
|
|
271
275
|
When isLoadingMore is true
|
|
272
|
-
Then
|
|
276
|
+
Then the sentinel is omitted
|
|
277
|
+
And a centered status row renders after the loaded rows
|
|
278
|
+
And the status row shows loadingMoreLabel (default "Loading more data...")
|
|
279
|
+
And the status row carries role="status" and aria-live="polite"
|
|
280
|
+
When isLoadingMore becomes false and hasNextPage is still true
|
|
281
|
+
Then the sentinel renders again
|
|
273
282
|
```
|
|
274
283
|
|
|
275
284
|
```gherkin
|
|
@@ -509,10 +518,11 @@ Scenario: Selection counts under an active filter — two deliberate scopes
|
|
|
509
518
|
renders no tooltip.
|
|
510
519
|
- Per-column filter fields live in a keyboard-navigable `FilterSearchFilters`
|
|
511
520
|
popover; each applied-filter chip below the toolbar removes its own filter.
|
|
512
|
-
- The infinite-scroll loading row (`paginationMode="infinite"`,
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
521
|
+
- The infinite-scroll loading status row (`paginationMode="infinite"`,
|
|
522
|
+
`isLoadingMore`) visibly shows `loadingMoreLabel` (default "Loading more
|
|
523
|
+
data...") and carries `role="status"`/`aria-live="polite"`. Override
|
|
524
|
+
`loadingMoreLabel` to localize the message. The observer sentinel is omitted
|
|
525
|
+
while this status row is shown.
|
|
516
526
|
|
|
517
527
|
## Known limitations
|
|
518
528
|
|
package/dist/llms/dialog-root.md
CHANGED
|
@@ -58,19 +58,19 @@ decision. Composable from parts; built on the Base UI Dialog primitive.
|
|
|
58
58
|
|
|
59
59
|
## Parts
|
|
60
60
|
|
|
61
|
-
| Part | Element (default) | Purpose
|
|
62
|
-
| -------------------------------- | ------------------ |
|
|
63
|
-
| `DialogRoot` | — | Root; owns the open state (Base UI `Root`).
|
|
64
|
-
| `DialogTrigger` | `button` | Opens the dialog.
|
|
65
|
-
| `DialogContent` | `div[role=dialog]` | The portaled
|
|
66
|
-
| `DialogHeaderRoot` | `div` | Top bar; holds the title and close button.
|
|
67
|
-
| `DialogTitle` | `h2` | Accessible dialog name (`aria-labelledby`).
|
|
68
|
-
| `DialogCloseButton` | `button` | Icon button that dismisses the dialog.
|
|
69
|
-
| `DialogBodyRoot` | `div` | Scrollable content region.
|
|
70
|
-
| `DialogDescription` | `p` | Supporting copy (`aria-describedby`).
|
|
71
|
-
| `DialogFooterRoot` | `div` | Right-aligned action bar.
|
|
72
|
-
| `DialogClose` | `button` | Closes the dialog; wrap a Button via `render`.
|
|
73
|
-
| `DialogOverlay` / `DialogPortal` | — | Lower-level parts (`DialogContent` renders them).
|
|
61
|
+
| Part | Element (default) | Purpose |
|
|
62
|
+
| -------------------------------- | ------------------ | ---------------------------------------------------------------------------------------- |
|
|
63
|
+
| `DialogRoot` | — | Root; owns the open state (Base UI `Root`). |
|
|
64
|
+
| `DialogTrigger` | `button` | Opens the dialog. |
|
|
65
|
+
| `DialogContent` | `div[role=dialog]` | The portaled popup (+ overlay); centered by default, or top-aligned via `verticalAlign`. |
|
|
66
|
+
| `DialogHeaderRoot` | `div` | Top bar; holds the title and close button. |
|
|
67
|
+
| `DialogTitle` | `h2` | Accessible dialog name (`aria-labelledby`). |
|
|
68
|
+
| `DialogCloseButton` | `button` | Icon button that dismisses the dialog. |
|
|
69
|
+
| `DialogBodyRoot` | `div` | Scrollable content region. |
|
|
70
|
+
| `DialogDescription` | `p` | Supporting copy (`aria-describedby`). |
|
|
71
|
+
| `DialogFooterRoot` | `div` | Right-aligned action bar. |
|
|
72
|
+
| `DialogClose` | `button` | Closes the dialog; wrap a Button via `render`. |
|
|
73
|
+
| `DialogOverlay` / `DialogPortal` | — | Lower-level parts (`DialogContent` renders them). |
|
|
74
74
|
|
|
75
75
|
## Sizes
|
|
76
76
|
|
|
@@ -79,6 +79,12 @@ decision. Composable from parts; built on the Base UI Dialog primitive.
|
|
|
79
79
|
`large` (832px) is a legacy backward-compatibility size with no design token,
|
|
80
80
|
kept for existing call sites (see the public `Dialog` recipe's `wide` variant).
|
|
81
81
|
|
|
82
|
+
## Placement
|
|
83
|
+
|
|
84
|
+
`DialogContent` takes a `verticalAlign` prop: `center` (default) centers the
|
|
85
|
+
popup in the viewport; `top` pins it 48px from the top edge, horizontally
|
|
86
|
+
centered, keeping its content height (still capped at `100dvh - 96px`).
|
|
87
|
+
|
|
82
88
|
## Example (internal usage only)
|
|
83
89
|
|
|
84
90
|
```tsx
|
|
@@ -124,6 +130,7 @@ import { Button } from '../button';
|
|
|
124
130
|
| `default-open` | `boolean` | `false` | no | Initial open state when uncontrolled. |
|
|
125
131
|
| `modal` | `boolean | 'trap-focus'` | `true` | no | Modal behavior — traps focus and locks background scroll while open. `'trap-focus'` keeps the focus trap but allows background interaction. |
|
|
126
132
|
| `size` | `'sm' | 'large'` | `'sm'` | no | Popup max-width (on the content part). `sm` (512px) has a Figma-defined token (`--ui-dialog-container-size-sm`); `large` (832px) is a legacy backward-compatibility size with no design token, kept for existing call sites (see the public `Dialog` recipe's `wide` variant). |
|
|
133
|
+
| `verticalAlign` | `'center' | 'top'` | `'center'` | no | Vertical placement of the popup (on the content part). `center` (the default) centers it in the viewport; `top` pins it 48px from the top edge of the viewport instead, keeping its content height. A ui-react-only extension beyond the Figma contract, like `size="large"`. |
|
|
127
134
|
| `portal` | `boolean` | `true` | no | Render the content inside a portal (the content part). Required by the underlying primitive for correct stacking; disable only when supplying your own portal ancestor. |
|
|
128
135
|
| `render` | `RenderProp` | `undefined` | no | Composition prop available on the trigger, close, title, description, and other primitive parts — replaces the rendered element with another component (e.g. render the trigger as a Button) while merging props. React-only; other frameworks use their own polymorphism. |
|
|
129
136
|
|
|
@@ -205,6 +212,26 @@ Scenario: Modal locks the background (default)
|
|
|
205
212
|
inside the dialog until it closes
|
|
206
213
|
```
|
|
207
214
|
|
|
215
|
+
### Placement
|
|
216
|
+
|
|
217
|
+
```gherkin
|
|
218
|
+
Scenario: The popup is centered by default
|
|
219
|
+
Given a DialogRoot whose DialogContent has no verticalAlign (or
|
|
220
|
+
verticalAlign = "center")
|
|
221
|
+
When it opens
|
|
222
|
+
Then the popup is centered in the viewport, horizontally and vertically
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
```gherkin
|
|
226
|
+
Scenario: verticalAlign = "top" pins the popup near the top edge
|
|
227
|
+
Given a DialogRoot whose DialogContent has verticalAlign = "top"
|
|
228
|
+
When it opens
|
|
229
|
+
Then the popup's top edge sits 48px below the top of the viewport
|
|
230
|
+
And it stays horizontally centered
|
|
231
|
+
And it keeps its content height (still capped at 100dvh - 96px), leaving
|
|
232
|
+
the viewport below it empty
|
|
233
|
+
```
|
|
234
|
+
|
|
208
235
|
## Accessibility
|
|
209
236
|
|
|
210
237
|
DialogRoot leans on the Base UI Dialog primitive for its modal semantics,
|