@misoto22/design 0.3.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +124 -0
- package/bin/misoto22-design.mjs +205 -0
- package/dist/agent/Accordion.md +41 -0
- package/dist/agent/Alert.md +42 -0
- package/dist/agent/AppShell.md +40 -0
- package/dist/agent/AreaChart.md +68 -0
- package/dist/agent/Article.md +41 -0
- package/dist/agent/Avatar.md +32 -0
- package/dist/agent/Badge.md +40 -0
- package/dist/agent/BarChart.md +65 -0
- package/dist/agent/BarList.md +40 -0
- package/dist/agent/BigNumber.md +45 -0
- package/dist/agent/BoxPlot.md +58 -0
- package/dist/agent/Breadcrumb.md +32 -0
- package/dist/agent/BulletChart.md +48 -0
- package/dist/agent/Button.md +56 -0
- package/dist/agent/Calendar.md +42 -0
- package/dist/agent/Card.md +49 -0
- package/dist/agent/Checkbox.md +35 -0
- package/dist/agent/Collapsible.md +46 -0
- package/dist/agent/Combobox.md +50 -0
- package/dist/agent/Command.md +93 -0
- package/dist/agent/ComposedChart.md +57 -0
- package/dist/agent/ContextMenu.md +59 -0
- package/dist/agent/DatePicker.md +75 -0
- package/dist/agent/Diagram.md +46 -0
- package/dist/agent/Dialog.md +52 -0
- package/dist/agent/DropdownMenu.md +70 -0
- package/dist/agent/EmptyState.md +37 -0
- package/dist/agent/ErrorState.md +41 -0
- package/dist/agent/Facet.md +82 -0
- package/dist/agent/Field.md +37 -0
- package/dist/agent/FigureBand.md +37 -0
- package/dist/agent/FloatingIconButton.md +38 -0
- package/dist/agent/FunnelChart.md +52 -0
- package/dist/agent/Heatmap.md +53 -0
- package/dist/agent/Histogram.md +63 -0
- package/dist/agent/Input.md +30 -0
- package/dist/agent/Kbd.md +29 -0
- package/dist/agent/LineChart.md +60 -0
- package/dist/agent/LinkArrow.md +29 -0
- package/dist/agent/NativeSelect.md +40 -0
- package/dist/agent/NavItem.md +35 -0
- package/dist/agent/Pagination.md +43 -0
- package/dist/agent/PieChart.md +55 -0
- package/dist/agent/Popover.md +57 -0
- package/dist/agent/Progress.md +33 -0
- package/dist/agent/RadarChart.md +54 -0
- package/dist/agent/RadialChart.md +57 -0
- package/dist/agent/RadioGroup.md +44 -0
- package/dist/agent/SankeyChart.md +61 -0
- package/dist/agent/ScatterChart.md +54 -0
- package/dist/agent/ScrollArea.md +40 -0
- package/dist/agent/SearchableMenu.md +46 -0
- package/dist/agent/Select.md +75 -0
- package/dist/agent/Separator.md +35 -0
- package/dist/agent/Sheet.md +57 -0
- package/dist/agent/Skeleton.md +73 -0
- package/dist/agent/Slider.md +39 -0
- package/dist/agent/Sparkline.md +45 -0
- package/dist/agent/Spinner.md +39 -0
- package/dist/agent/StatusDot.md +36 -0
- package/dist/agent/StatusPill.md +28 -0
- package/dist/agent/Steps.md +44 -0
- package/dist/agent/Switch.md +29 -0
- package/dist/agent/Table.md +85 -0
- package/dist/agent/Tabs.md +48 -0
- package/dist/agent/Tag.md +35 -0
- package/dist/agent/Textarea.md +26 -0
- package/dist/agent/Toast.md +26 -0
- package/dist/agent/ToggleGroup.md +44 -0
- package/dist/agent/Tooltip.md +51 -0
- package/dist/agent/TreemapChart.md +52 -0
- package/dist/agent/WaterfallChart.md +62 -0
- package/dist/agent/catalog.json +1791 -0
- package/dist/agent/index.md +131 -0
- package/dist/article.css +393 -0
- package/dist/charts/AreaChart/AreaChart.d.ts +191 -0
- package/dist/charts/AreaChart/AreaChart.js +480 -0
- package/dist/charts/AreaChart/AreaChart.js.map +1 -0
- package/dist/charts/BarChart/BarChart.d.ts +179 -0
- package/dist/charts/BarChart/BarChart.js +591 -0
- package/dist/charts/BarChart/BarChart.js.map +1 -0
- package/dist/charts/BarList/BarList.d.ts +57 -0
- package/dist/charts/BarList/BarList.js +71 -0
- package/dist/charts/BarList/BarList.js.map +1 -0
- package/dist/charts/BigNumber/BigNumber.d.ts +56 -0
- package/dist/charts/BigNumber/BigNumber.js +31 -0
- package/dist/charts/BigNumber/BigNumber.js.map +1 -0
- package/dist/charts/BoxPlot/BoxPlot.d.ts +177 -0
- package/dist/charts/BoxPlot/BoxPlot.js +495 -0
- package/dist/charts/BoxPlot/BoxPlot.js.map +1 -0
- package/dist/charts/BulletChart/BulletChart.d.ts +100 -0
- package/dist/charts/BulletChart/BulletChart.js +162 -0
- package/dist/charts/BulletChart/BulletChart.js.map +1 -0
- package/dist/charts/ComposedChart/ComposedChart.d.ts +171 -0
- package/dist/charts/ComposedChart/ComposedChart.js +667 -0
- package/dist/charts/ComposedChart/ComposedChart.js.map +1 -0
- package/dist/charts/Facet/Facet.d.ts +240 -0
- package/dist/charts/Facet/Facet.js +133 -0
- package/dist/charts/Facet/Facet.js.map +1 -0
- package/dist/charts/Facet/panels.d.ts +187 -0
- package/dist/charts/Facet/panels.js +203 -0
- package/dist/charts/Facet/panels.js.map +1 -0
- package/dist/charts/FunnelChart/FunnelChart.d.ts +101 -0
- package/dist/charts/FunnelChart/FunnelChart.js +147 -0
- package/dist/charts/FunnelChart/FunnelChart.js.map +1 -0
- package/dist/charts/Heatmap/Heatmap.d.ts +78 -0
- package/dist/charts/Heatmap/Heatmap.js +108 -0
- package/dist/charts/Heatmap/Heatmap.js.map +1 -0
- package/dist/charts/Histogram/Histogram.d.ts +165 -0
- package/dist/charts/Histogram/Histogram.js +350 -0
- package/dist/charts/Histogram/Histogram.js.map +1 -0
- package/dist/charts/LineChart/LineChart.d.ts +167 -0
- package/dist/charts/LineChart/LineChart.js +486 -0
- package/dist/charts/LineChart/LineChart.js.map +1 -0
- package/dist/charts/PieChart/PieChart.d.ts +128 -0
- package/dist/charts/PieChart/PieChart.js +309 -0
- package/dist/charts/PieChart/PieChart.js.map +1 -0
- package/dist/charts/RadarChart/RadarChart.d.ts +123 -0
- package/dist/charts/RadarChart/RadarChart.js +299 -0
- package/dist/charts/RadarChart/RadarChart.js.map +1 -0
- package/dist/charts/RadialChart/RadialChart.d.ts +124 -0
- package/dist/charts/RadialChart/RadialChart.js +257 -0
- package/dist/charts/RadialChart/RadialChart.js.map +1 -0
- package/dist/charts/SankeyChart/SankeyChart.d.ts +137 -0
- package/dist/charts/SankeyChart/SankeyChart.js +501 -0
- package/dist/charts/SankeyChart/SankeyChart.js.map +1 -0
- package/dist/charts/ScatterChart/ScatterChart.d.ts +128 -0
- package/dist/charts/ScatterChart/ScatterChart.js +269 -0
- package/dist/charts/ScatterChart/ScatterChart.js.map +1 -0
- package/dist/charts/Sparkline/Sparkline.d.ts +53 -0
- package/dist/charts/Sparkline/Sparkline.js +93 -0
- package/dist/charts/Sparkline/Sparkline.js.map +1 -0
- package/dist/charts/TreemapChart/TreemapChart.d.ts +93 -0
- package/dist/charts/TreemapChart/TreemapChart.js +118 -0
- package/dist/charts/TreemapChart/TreemapChart.js.map +1 -0
- package/dist/charts/WaterfallChart/WaterfallChart.d.ts +164 -0
- package/dist/charts/WaterfallChart/WaterfallChart.js +319 -0
- package/dist/charts/WaterfallChart/WaterfallChart.js.map +1 -0
- package/dist/charts/index.d.ts +41 -0
- package/dist/charts/index.js +128 -0
- package/dist/charts/index.js.map +1 -0
- package/dist/charts/lib/annotations.d.ts +103 -0
- package/dist/charts/lib/annotations.js +99 -0
- package/dist/charts/lib/annotations.js.map +1 -0
- package/dist/charts/lib/axis.d.ts +18 -0
- package/dist/charts/lib/axis.js +21 -0
- package/dist/charts/lib/axis.js.map +1 -0
- package/dist/charts/lib/background.d.ts +33 -0
- package/dist/charts/lib/background.js +173 -0
- package/dist/charts/lib/background.js.map +1 -0
- package/dist/charts/lib/brush.d.ts +94 -0
- package/dist/charts/lib/brush.js +535 -0
- package/dist/charts/lib/brush.js.map +1 -0
- package/dist/charts/lib/chart.d.ts +94 -0
- package/dist/charts/lib/chart.js +134 -0
- package/dist/charts/lib/chart.js.map +1 -0
- package/dist/charts/lib/dot.d.ts +29 -0
- package/dist/charts/lib/dot.js +78 -0
- package/dist/charts/lib/dot.js.map +1 -0
- package/dist/charts/lib/empty.d.ts +31 -0
- package/dist/charts/lib/empty.js +13 -0
- package/dist/charts/lib/empty.js.map +1 -0
- package/dist/charts/lib/export.d.ts +103 -0
- package/dist/charts/lib/export.js +204 -0
- package/dist/charts/lib/export.js.map +1 -0
- package/dist/charts/lib/figure.d.ts +61 -0
- package/dist/charts/lib/figure.js +59 -0
- package/dist/charts/lib/figure.js.map +1 -0
- package/dist/charts/lib/format.d.ts +46 -0
- package/dist/charts/lib/format.js +56 -0
- package/dist/charts/lib/format.js.map +1 -0
- package/dist/charts/lib/legend.d.ts +45 -0
- package/dist/charts/lib/legend.js +117 -0
- package/dist/charts/lib/legend.js.map +1 -0
- package/dist/charts/lib/loading.d.ts +48 -0
- package/dist/charts/lib/loading.js +105 -0
- package/dist/charts/lib/loading.js.map +1 -0
- package/dist/charts/lib/paint.d.ts +154 -0
- package/dist/charts/lib/paint.js +551 -0
- package/dist/charts/lib/paint.js.map +1 -0
- package/dist/charts/lib/sonify-control.d.ts +163 -0
- package/dist/charts/lib/sonify-control.js +172 -0
- package/dist/charts/lib/sonify-control.js.map +1 -0
- package/dist/charts/lib/sonify.d.ts +248 -0
- package/dist/charts/lib/sonify.js +262 -0
- package/dist/charts/lib/sonify.js.map +1 -0
- package/dist/charts/lib/toolbar.d.ts +143 -0
- package/dist/charts/lib/toolbar.js +156 -0
- package/dist/charts/lib/toolbar.js.map +1 -0
- package/dist/charts/lib/tooltip.d.ts +59 -0
- package/dist/charts/lib/tooltip.js +135 -0
- package/dist/charts/lib/tooltip.js.map +1 -0
- package/dist/charts/lib/values.d.ts +56 -0
- package/dist/charts/lib/values.js +71 -0
- package/dist/charts/lib/values.js.map +1 -0
- package/dist/charts/lib/zoom.d.ts +139 -0
- package/dist/charts/lib/zoom.js +314 -0
- package/dist/charts/lib/zoom.js.map +1 -0
- package/dist/components/AppShell/AppShell.d.ts +15 -1
- package/dist/components/AppShell/AppShell.js +8 -4
- package/dist/components/AppShell/AppShell.js.map +1 -1
- package/dist/components/Article/Article.d.ts +51 -0
- package/dist/components/Article/Article.js +21 -0
- package/dist/components/Article/Article.js.map +1 -0
- package/dist/components/Button/Button.js +2 -2
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Calendar/Calendar.d.ts +1 -1
- package/dist/components/Calendar/Calendar.js +259 -24
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.js +1 -1
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/Collapsible/Collapsible.d.ts +15 -1
- package/dist/components/Collapsible/Collapsible.js +18 -0
- package/dist/components/Collapsible/Collapsible.js.map +1 -1
- package/dist/components/Combobox/Combobox.js +1 -1
- package/dist/components/Combobox/Combobox.js.map +1 -1
- package/dist/components/Command/Command.js +7 -7
- package/dist/components/Command/Command.js.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.js +2 -2
- package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
- package/dist/components/Diagram/Diagram.d.ts +81 -0
- package/dist/components/Diagram/Diagram.js +139 -0
- package/dist/components/Diagram/Diagram.js.map +1 -0
- package/dist/components/Dialog/Dialog.js +1 -1
- package/dist/components/Dialog/Dialog.js.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.js +2 -2
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
- package/dist/components/FigureBand/FigureBand.js +41 -30
- package/dist/components/FigureBand/FigureBand.js.map +1 -1
- package/dist/components/Popover/Popover.js +1 -1
- package/dist/components/Popover/Popover.js.map +1 -1
- package/dist/components/Select/Select.js +2 -2
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Sheet/Sheet.js +1 -1
- package/dist/components/Sheet/Sheet.js.map +1 -1
- package/dist/components/Slider/Slider.js +1 -1
- package/dist/components/Slider/Slider.js.map +1 -1
- package/dist/components/Steps/Steps.d.ts +65 -0
- package/dist/components/Steps/Steps.js +55 -0
- package/dist/components/Steps/Steps.js.map +1 -0
- package/dist/components/Switch/Switch.js +1 -1
- package/dist/components/Switch/Switch.js.map +1 -1
- package/dist/components/Tooltip/Tooltip.js +1 -1
- package/dist/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/useSelectionIndicator.js +14 -10
- package/dist/lib/useSelectionIndicator.js.map +1 -1
- package/dist/semantic.css +19 -0
- package/dist/styles.css +1 -1
- package/dist/themes.css +103 -7
- package/dist/tokens.css +193 -10
- package/dist/tokens.d.ts +25 -0
- package/dist/tokens.js +154 -8
- package/dist/tokens.json +154 -8
- package/package.json +45 -20
- package/skills/misoto22-design/SKILL.md +171 -0
- package/skills/misoto22-design/evals/claims.json +95 -0
- package/skills/misoto22-design/rules/a11y.md +115 -0
- package/skills/misoto22-design/rules/composition.md +108 -0
- package/skills/misoto22-design/rules/forms.md +128 -0
- package/skills/misoto22-design/rules/naming.md +155 -0
- package/skills/misoto22-design/rules/tokens.md +131 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Command
|
|
2
|
+
|
|
3
|
+
A filterable list of actions — the ⌘K surface.
|
|
4
|
+
|
|
5
|
+
- Group: Overlays
|
|
6
|
+
- Import: `import { Command } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/command/
|
|
9
|
+
- Related: combobox, dialog
|
|
10
|
+
|
|
11
|
+
## Accessibility
|
|
12
|
+
|
|
13
|
+
- The list filters as you type, the highlight moves with the arrow keys, and focus stays in the input. That last part is the ARIA combobox pattern and the part a home-made palette gets wrong.
|
|
14
|
+
|
|
15
|
+
## Keyboard
|
|
16
|
+
|
|
17
|
+
- ↑ / ↓ — Moves the highlight. Focus stays in the input, so what you typed stays editable.
|
|
18
|
+
- Enter — Runs the highlighted item.
|
|
19
|
+
- Escape — Closes the palette.
|
|
20
|
+
|
|
21
|
+
## Command
|
|
22
|
+
|
|
23
|
+
A filterable list of actions — the ⌘K surface. Built on cmdk rather than on a `Select` or a menu, because the interaction is neither: the list is filtered as you type, the highlighted row moves with the arrow keys while focus STAYS in the input, and Enter runs the highlighted row. That is the ARIA combobox pattern, and it is the part nobody should hand-roll — `aria-activedescendant` moving without focus moving is precisely where a home-made palette stops working with a screen reader.
|
|
24
|
+
|
|
25
|
+
## CommandInput
|
|
26
|
+
|
|
27
|
+
The filter field. Carries the search icon and the combobox semantics.
|
|
28
|
+
|
|
29
|
+
## CommandList
|
|
30
|
+
|
|
31
|
+
## CommandEmpty
|
|
32
|
+
|
|
33
|
+
Shown when the filter matches nothing. Say what would match, not "no results".
|
|
34
|
+
|
|
35
|
+
## CommandFooter
|
|
36
|
+
|
|
37
|
+
The key-hint strip along the bottom. A palette is a keyboard surface whose keys are invisible: nothing on screen says the arrows move the row or that Enter runs it, and a reader who reaches for the mouse has been failed by the design rather than by themselves.
|
|
38
|
+
|
|
39
|
+
## CommandHint
|
|
40
|
+
|
|
41
|
+
One key-and-verb pair inside a `CommandFooter`.
|
|
42
|
+
|
|
43
|
+
### Props
|
|
44
|
+
|
|
45
|
+
- `keys` (required) — `string[]`. The keys this hint describes, printed as `Kbd` chips.
|
|
46
|
+
- `children` (required) — `ReactNode`. What they do — a verb, lowercase, no sentence.
|
|
47
|
+
|
|
48
|
+
Also accepts: `Omit<ComponentProps<'span'>, 'children'>`.
|
|
49
|
+
|
|
50
|
+
## CommandGroup
|
|
51
|
+
|
|
52
|
+
## CommandSeparator
|
|
53
|
+
|
|
54
|
+
A divider between groups. Marked presentational, because ARIA permits a `listbox` to contain only `option` and `group` — and the library renders this as `role="separator"`, which puts a critical `aria-required-children` violation inside every palette that uses one. The grouping is already announced by the groups themselves, so removing the divider from the accessibility tree loses nothing.
|
|
55
|
+
|
|
56
|
+
## CommandItem
|
|
57
|
+
|
|
58
|
+
### Props
|
|
59
|
+
|
|
60
|
+
- `shortcut` — `string`. A shortcut printed at the end of the row.
|
|
61
|
+
- `icon` — `ReactNode`. A leading glyph. Pass the icon element, sized 16. It is what makes a long list scannable — the eye sorts by shape before it reads, and forty identical rows of text defeat that.
|
|
62
|
+
- `meta` — `ReactNode`. A quiet note at the end of the row — what kind of thing this is, or its current state. Not a description: a palette that prints a sentence per row stops being scannable at about six of them.
|
|
63
|
+
|
|
64
|
+
Also accepts: `ComponentProps<typeof CommandPrimitive.Item>`.
|
|
65
|
+
|
|
66
|
+
## CommandDialog
|
|
67
|
+
|
|
68
|
+
The palette in a modal, which is how it is nearly always used. The dialog's own padding is removed: a palette is edge-to-edge, and its input is the first thing focus lands on.
|
|
69
|
+
|
|
70
|
+
### Props
|
|
71
|
+
|
|
72
|
+
- `open` (required) — `boolean`.
|
|
73
|
+
- `onOpenChange` (required) — `(open: boolean) => void`.
|
|
74
|
+
- `label` (required) — `string`. Names the palette for assistive tech.
|
|
75
|
+
- `children` (required) — `ReactNode`.
|
|
76
|
+
|
|
77
|
+
## Examples
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
<Command label="Command palette">
|
|
81
|
+
<CommandInput placeholder="Type a command…" />
|
|
82
|
+
<CommandList>
|
|
83
|
+
<CommandEmpty>Nothing matches.</CommandEmpty>
|
|
84
|
+
<CommandGroup heading="Navigate">
|
|
85
|
+
<CommandItem onSelect={go}>Components</CommandItem>
|
|
86
|
+
</CommandGroup>
|
|
87
|
+
</CommandList>
|
|
88
|
+
</Command>
|
|
89
|
+
<CommandFooter>
|
|
90
|
+
<CommandHint keys={['↑', '↓']}>navigate</CommandHint>
|
|
91
|
+
<CommandHint keys={['↵']}>open</CommandHint>
|
|
92
|
+
</CommandFooter>
|
|
93
|
+
```
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# ComposedChart
|
|
2
|
+
|
|
3
|
+
Bars and lines over one axis — the volume, and the rate it moved at.
|
|
4
|
+
|
|
5
|
+
- Group: Charts
|
|
6
|
+
- Import: `import { ComposedChart } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/composed-chart/
|
|
9
|
+
- Related: bar-chart, line-chart
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
Two measures that share a scale. Two that do NOT share one belong in two charts or indexed to a common base: there is no second y-axis here, on purpose.
|
|
14
|
+
|
|
15
|
+
## Accessibility
|
|
16
|
+
|
|
17
|
+
- title is required; the rows are also rendered as a visually hidden table.
|
|
18
|
+
- One value axis only. A dual-axis chart lets its author choose where the lines cross, which is the single most misleading thing a chart can do.
|
|
19
|
+
- enableHoverHighlight dims every bar outside the hovered column, driven by the chart’s own tooltip index.
|
|
20
|
+
|
|
21
|
+
## ComposedChart
|
|
22
|
+
|
|
23
|
+
Bars and lines over one axis — the shape for "the volume, and the rate it moved at". One axis, always. Two measures at different scales belong in two charts or indexed to a common base; a second y-scale lets the author choose where the lines cross, which is the single most misleading thing a chart can do.
|
|
24
|
+
|
|
25
|
+
### Props
|
|
26
|
+
|
|
27
|
+
- `config` (required) — `TConfig & ValidateKeys<TData, TConfig>`.
|
|
28
|
+
- `data` (required) — `TData[]`. The rows the chart draws. One entry per point, bar or category.
|
|
29
|
+
- `title` (required) — `string`. What the chart shows, in a sentence a reader could act on. Required, and announced to a screen reader even when it is not printed.
|
|
30
|
+
- `showTitle` — `boolean`. Prints the title above the plot instead of hiding it from sight.
|
|
31
|
+
- `description` — `ReactNode`. A line under the title — the unit, the window, the caveat.
|
|
32
|
+
- `children` (required) — `ReactNode`. The composed parts — axes, grid, tooltip, legend, and the marks themselves.
|
|
33
|
+
- `className` — `string`. Merged onto the figure, last, so a call site can size or space it.
|
|
34
|
+
- `chartProps` — `ComponentProps<typeof RechartsComposedChart>`. Escape hatch onto the raw Recharts chart element.
|
|
35
|
+
- `curveType` — `ChartCurveType` default `'linear'`. How the line between two points is interpolated. Every mark inherits it unless it says otherwise.
|
|
36
|
+
- `animationType` — `ChartRevealType` default `'forward'`.
|
|
37
|
+
- `barGap` — `number`.
|
|
38
|
+
- `barCategoryGap` — `number`.
|
|
39
|
+
- `defaultSelectedDataKey` — `string | null` default `null`. The series lit on first render. Selection dims every other series.
|
|
40
|
+
- `onSelectionChange` — `(selectedDataKey: string | null) => void`. Fires when the selection changes, and with null when it is cleared.
|
|
41
|
+
- `isLoading` — `boolean` default `false`. Swaps the marks for an animated skeleton, keeping the measured height so the page does not jump when the data lands.
|
|
42
|
+
- `loadingBars` — `number`. How many bars the skeleton draws.
|
|
43
|
+
- `xDataKey` — `keyof TData & string`. The row field on the category axis. Needed by the brush and by the table view.
|
|
44
|
+
- `hideDataTable` — `boolean` default `false`. Drops the hidden table view. Only correct when the page prints the data itself.
|
|
45
|
+
- `empty` — `ChartEmptyProps | false`. What the chart shows when it has nothing to draw. Rendered instead of the plot whenever `data` is empty and the chart is not loading — the state a real dashboard reaches within a week, and the one an empty pair of axes is indistinguishable from a failed load. `false` keeps the axes, for a chart whose emptiness is itself the reading.
|
|
46
|
+
|
|
47
|
+
## Examples
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
<ComposedChart title="Revenue and profit" config={config} data={data}>
|
|
51
|
+
<ComposedChart.Grid />
|
|
52
|
+
<ComposedChart.XAxis dataKey="month" />
|
|
53
|
+
<ComposedChart.Tooltip />
|
|
54
|
+
<ComposedChart.Bar dataKey="revenue" variant="duotone" />
|
|
55
|
+
<ComposedChart.Line dataKey="profit" />
|
|
56
|
+
</ComposedChart>
|
|
57
|
+
```
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# ContextMenu
|
|
2
|
+
|
|
3
|
+
The menu a right-click opens.
|
|
4
|
+
|
|
5
|
+
- Group: Overlays
|
|
6
|
+
- Import: `import { ContextMenu } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/context-menu/
|
|
9
|
+
- Related: dropdown-menu
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
Never as the only way to reach an action. Touch users, trackpad users and keyboard users may have no way to open it.
|
|
14
|
+
|
|
15
|
+
## Keyboard
|
|
16
|
+
|
|
17
|
+
- Shift / F10 — Opens the menu from the keyboard, where the platform supports it.
|
|
18
|
+
- ↑ / ↓ — Moves between items.
|
|
19
|
+
- Escape — Closes it.
|
|
20
|
+
|
|
21
|
+
## ContextMenu
|
|
22
|
+
|
|
23
|
+
Radix ContextMenu root and trigger, as typed passthroughs.
|
|
24
|
+
|
|
25
|
+
## ContextMenuTrigger
|
|
26
|
+
|
|
27
|
+
## ContextMenuContent
|
|
28
|
+
|
|
29
|
+
The menu a right-click opens. Never the only way to reach an action. A context menu is opened by a secondary pointer button or a keyboard's own menu key, and a meaningful share of readers have neither — a touch user, someone on a trackpad they have not configured, anyone driving the page by keyboard alone. Whatever is in here belongs somewhere reachable too: a row's overflow button, a toolbar.
|
|
30
|
+
|
|
31
|
+
## ContextMenuItem
|
|
32
|
+
|
|
33
|
+
A row. Highlight follows `data-highlighted`, which covers hover and keyboard.
|
|
34
|
+
|
|
35
|
+
### Props
|
|
36
|
+
|
|
37
|
+
- `icon` — `LucideIcon`.
|
|
38
|
+
- `destructive` — `boolean` default `false`.
|
|
39
|
+
|
|
40
|
+
Also accepts: `ComponentProps<typeof ContextMenuPrimitive.Item>`.
|
|
41
|
+
|
|
42
|
+
## ContextMenuSeparator
|
|
43
|
+
|
|
44
|
+
Hairline divider between groups.
|
|
45
|
+
|
|
46
|
+
## ContextMenuLabel
|
|
47
|
+
|
|
48
|
+
Mono eyebrow heading for a group.
|
|
49
|
+
|
|
50
|
+
## Examples
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
<ContextMenu>
|
|
54
|
+
<ContextMenuTrigger asChild><Card>Right-click me</Card></ContextMenuTrigger>
|
|
55
|
+
<ContextMenuContent>
|
|
56
|
+
<ContextMenuItem icon={Copy}>Copy</ContextMenuItem>
|
|
57
|
+
</ContextMenuContent>
|
|
58
|
+
</ContextMenu>
|
|
59
|
+
```
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# DatePicker
|
|
2
|
+
|
|
3
|
+
A date — or a span of them — chosen from a calendar.
|
|
4
|
+
|
|
5
|
+
- Group: Forms
|
|
6
|
+
- Import: `import { DatePicker } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/date-picker/
|
|
9
|
+
- Related: calendar, field
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
Deliberately not a text input with a calendar attached: parsing a typed date needs a format, and 03/04 is March the fourth in one country and the third of April in the next. When the date is a long way back, the calendar’s month and year are dropdowns.
|
|
14
|
+
|
|
15
|
+
## Accessibility
|
|
16
|
+
|
|
17
|
+
- The trigger prints the date in the visitor’s own locale, not a fixed dd/mm/yyyy.
|
|
18
|
+
- DateRangePicker keeps the panel open until both ends are chosen — a range is not a value until it has a second date.
|
|
19
|
+
- The shortcut rail is plain buttons, not a menu: they set the same value the grid beside them sets, so they belong to one control and Tab in the same pass.
|
|
20
|
+
- Presets are computed on click, so “today” means today even on a tab left open overnight.
|
|
21
|
+
|
|
22
|
+
## Keyboard
|
|
23
|
+
|
|
24
|
+
- Enter / Space — Opens the calendar.
|
|
25
|
+
- Escape — Closes it without choosing.
|
|
26
|
+
|
|
27
|
+
## RANGE_PRESETS
|
|
28
|
+
|
|
29
|
+
The shortcuts a range picker is asked for on nearly every screen it appears on, so they ship rather than being rebuilt per dashboard. Computed on click: a preset list built at render time freezes "today" at whenever the page loaded, which is wrong for anything left open overnight.
|
|
30
|
+
|
|
31
|
+
## DATE_PRESETS
|
|
32
|
+
|
|
33
|
+
The single-date equivalent.
|
|
34
|
+
|
|
35
|
+
## DatePicker
|
|
36
|
+
|
|
37
|
+
A date, chosen from a calendar. A trigger and a `Calendar` in a `Popover` — not a new component so much as the composition people otherwise assemble slightly differently on every screen. It is deliberately NOT a text input with a calendar attached. A typed date needs parsing, and parsing needs a format, and a format is a locale argument nobody wins. When typing genuinely matters — a birth date, a long way back — the calendar's month and year are dropdowns, which is the same journey without the ambiguity.
|
|
38
|
+
|
|
39
|
+
### Props
|
|
40
|
+
|
|
41
|
+
- `value` — `Date`.
|
|
42
|
+
- `defaultValue` — `Date`.
|
|
43
|
+
- `onValueChange` — `(value: Date | undefined) => void`.
|
|
44
|
+
- `label` (required) — `string`. Names the control. Required — the trigger's text is a value, not a label.
|
|
45
|
+
- `placeholder` — `string` default `'Pick a date'`.
|
|
46
|
+
- `disabled` — `boolean` default `false`.
|
|
47
|
+
- `disabledDates` — `ComponentProps<typeof Calendar>['disabled']`. Days the reader may not choose. Passed straight to the calendar.
|
|
48
|
+
- `format` — `(date: Date) => string` default `formatDate`. How the chosen date is printed on the trigger.
|
|
49
|
+
- `presets` — `boolean | DatePreset<Date>[]`. Shortcuts shown beside the grid. Pass `true` for the built-in set, an array for your own, or leave it off for none.
|
|
50
|
+
- `className` — `string`.
|
|
51
|
+
|
|
52
|
+
## DateRangePicker
|
|
53
|
+
|
|
54
|
+
A span of dates — a stay, a reporting period, a filter. Two months side by side, because a range that crosses a month boundary is the common case, and paging back and forth to see both ends is what makes a range picker tiring. They stack under `sm`, where two would not fit — the calendar's own `months` class already carries that, so there is nothing to override. The panel stays open until both ends are chosen: a range is not a value until it has a second date, and closing on the first one would mean re-opening to finish.
|
|
55
|
+
|
|
56
|
+
### Props
|
|
57
|
+
|
|
58
|
+
- `value` — `DateRange`.
|
|
59
|
+
- `defaultValue` — `DateRange`.
|
|
60
|
+
- `onValueChange` — `(value: DateRange | undefined) => void`.
|
|
61
|
+
- `label` (required) — `string`.
|
|
62
|
+
- `placeholder` — `string` default `'Pick a range'`.
|
|
63
|
+
- `disabled` — `boolean` default `false`.
|
|
64
|
+
- `disabledDates` — `ComponentProps<typeof Calendar>['disabled']`.
|
|
65
|
+
- `months` — `number` default `2`. How many months are shown side by side. Falls back to one under `sm`.
|
|
66
|
+
- `format` — `(date: Date) => string` default `formatDate`.
|
|
67
|
+
- `presets` — `boolean | DatePreset<DateRange>[]` default `true`. Shortcuts shown beside the grid — Last 30 days and its neighbours. `true` for the built-in set, an array for your own. On by default here and off on the single picker, because "last 30 days" is most of what a range picker is ever asked for, while a single date is usually a specific one.
|
|
68
|
+
- `className` — `string`.
|
|
69
|
+
|
|
70
|
+
## Examples
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
<Field label="Publish on"><DatePicker label="Publish on" /></Field>
|
|
74
|
+
<DateRangePicker label="Reporting period" />
|
|
75
|
+
```
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Diagram
|
|
2
|
+
|
|
3
|
+
A flow or architecture figure, drawn out of the system’s own parts.
|
|
4
|
+
|
|
5
|
+
- Group: Display
|
|
6
|
+
- Import: `import { Diagram } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/diagram/
|
|
9
|
+
- Related: card, figure-band
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
A picture of structure, in a page rather than in a terminal. Nesting is containment and an edge is a step between siblings — a diagram that needs arbitrary wiring wants a drawing, not this.
|
|
14
|
+
|
|
15
|
+
## Accessibility
|
|
16
|
+
|
|
17
|
+
- A <figure> with role="group", named by its caption, so the whole picture is one thing a reader can skip.
|
|
18
|
+
- Arrows are aria-hidden: assistive tech reads the nodes in document order and has no use for a glyph pointing at the next one.
|
|
19
|
+
- Server-rendered markup, not a canvas — every label is real text a screen reader and a search engine can read.
|
|
20
|
+
|
|
21
|
+
## Diagram
|
|
22
|
+
|
|
23
|
+
A flow or architecture diagram, drawn out of the system's own parts. The alternative it replaces is a fenced block of box-drawing characters — `┌──────┬──────┐` — which is a picture rendered in a font chosen for code. It inherits the code block's frame and scrollbar, so a diagram reads as terminal output; it cannot wrap, so on a phone it either overflows or is scaled to nothing; the box edges are text, so a screen reader reads the rules out loud; and none of it responds to the theme. The other alternative is a diagramming library, which is several hundred kilobytes of layout engine, renders after hydration, and draws in its own palette. This is neither: hairline frames on the radius scale, mono labels, the muted step for anything supporting — so a diagram belongs to the page it sits on. It server-renders, because it is markup. NESTING IS CONTAINMENT, which is what most architecture diagrams actually describe: this is inside that, and these two sit beside each other. Edges are for the sequence between siblings, not for arbitrary wiring — a diagram that needs arbitrary wiring is a diagram that wants a drawing, and this will not pretend otherwise. It takes a spec rather than markup, so a fenced ```diagram block in an article and a hand-written figure on a page are one renderer and one look — and a wrong diagram is corrected by editing data.
|
|
24
|
+
|
|
25
|
+
### Props
|
|
26
|
+
|
|
27
|
+
- `spec` (required) — `DiagramSpec`.
|
|
28
|
+
- `className` — `string`.
|
|
29
|
+
|
|
30
|
+
## Examples
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
<Diagram
|
|
34
|
+
spec={{
|
|
35
|
+
caption: 'One request, end to end.',
|
|
36
|
+
edges: [{ from: 'edge', to: 'app', label: 'HTTPS' }],
|
|
37
|
+
nodes: [
|
|
38
|
+
{ id: 'edge', label: 'Edge', note: 'CDN' },
|
|
39
|
+
{ id: 'app', label: 'Application', accent: true, children: [
|
|
40
|
+
{ label: 'Router' },
|
|
41
|
+
{ label: 'Handlers' },
|
|
42
|
+
] },
|
|
43
|
+
],
|
|
44
|
+
}}
|
|
45
|
+
/>
|
|
46
|
+
```
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Dialog
|
|
2
|
+
|
|
3
|
+
A modal surface: portal, scrim, centred panel.
|
|
4
|
+
|
|
5
|
+
- Group: Overlays
|
|
6
|
+
- Import: `import { Dialog } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/dialog/
|
|
9
|
+
- Related: dropdown-menu, tooltip
|
|
10
|
+
|
|
11
|
+
## Accessibility
|
|
12
|
+
|
|
13
|
+
- Radix owns the focus trap, Escape, the scroll lock and aria-modal.
|
|
14
|
+
- A dialog without a visible heading still renders a hidden title, rather than shipping an unnamed modal.
|
|
15
|
+
|
|
16
|
+
## Keyboard
|
|
17
|
+
|
|
18
|
+
- Escape — Closes it, and focus returns to the trigger it came from.
|
|
19
|
+
- Tab — Cycles inside the dialog; focus cannot leave while it is open.
|
|
20
|
+
|
|
21
|
+
## Dialog
|
|
22
|
+
|
|
23
|
+
Radix Dialog root + trigger + close, re-exported as typed passthroughs.
|
|
24
|
+
|
|
25
|
+
## DialogTrigger
|
|
26
|
+
|
|
27
|
+
## DialogClose
|
|
28
|
+
|
|
29
|
+
## DialogContent
|
|
30
|
+
|
|
31
|
+
A modal surface: portal → scrim → centred panel. Radix owns the focus trap, the escape key, the scroll lock and the `aria-modal` wiring — all of which a hand-rolled dialog gets subtly wrong, usually by leaving focus behind in the page underneath. Radix requires a `Dialog.Title` whether or not one is shown, so a dialog without a visible heading still renders a hidden one rather than logging a warning and shipping an unnamed modal.
|
|
32
|
+
|
|
33
|
+
### Props
|
|
34
|
+
|
|
35
|
+
- `title` — `ReactNode`. Heading text. When omitted, a visually-hidden title is rendered for a11y.
|
|
36
|
+
- `description` — `ReactNode`. Sub-heading under the title.
|
|
37
|
+
- `className` — `string`.
|
|
38
|
+
- `showClose` — `boolean` default `true`. Show the top-right close control (default true).
|
|
39
|
+
- `hideTitle` — `boolean` default `false`. Keeps the title for assistive tech and hides it visually. For a surface whose purpose is obvious to anyone who can see it — a command palette, a media lightbox — where a printed heading would be furniture. The title itself is never optional: Radix requires one, and a modal with no accessible name drops a screen reader into an unnamed region.
|
|
40
|
+
|
|
41
|
+
Also accepts: `Omit<ComponentProps<typeof DialogPrimitive.Content>, 'title' | 'className'>`.
|
|
42
|
+
|
|
43
|
+
## Examples
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
<Dialog>
|
|
47
|
+
<DialogTrigger asChild><Button>Delete</Button></DialogTrigger>
|
|
48
|
+
<DialogContent title="Delete file" description="This cannot be undone.">
|
|
49
|
+
<DialogClose asChild><Button variant="secondary">Cancel</Button></DialogClose>
|
|
50
|
+
</DialogContent>
|
|
51
|
+
</Dialog>
|
|
52
|
+
```
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# DropdownMenu
|
|
2
|
+
|
|
3
|
+
A menu of actions.
|
|
4
|
+
|
|
5
|
+
- Group: Overlays
|
|
6
|
+
- Import: `import { DropdownMenu } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/dropdown-menu/
|
|
9
|
+
- Related: dialog, select
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
Actions. Items that navigate belong in a nav; items that set a value are a Select or a RadioGroup.
|
|
14
|
+
|
|
15
|
+
## Accessibility
|
|
16
|
+
|
|
17
|
+
- Inside a bounded frame — a device preview, an embedded console — wrap the subtree in `<OverlayContainer container={el}>`. The panel then renders into that element and collides with its edges instead of the viewport’s, and inherits the `dir` and `data-density` set there.
|
|
18
|
+
- Highlight is driven by data-highlighted, which covers hover AND keyboard focus — styling :hover alone leaves the keyboard user unable to see where they are.
|
|
19
|
+
|
|
20
|
+
## Keyboard
|
|
21
|
+
|
|
22
|
+
- Enter / Space / ↓ — Opens the menu and lands on the first item.
|
|
23
|
+
- ↑ / ↓ — Moves between items.
|
|
24
|
+
- a–z — Jumps to the next item starting with that letter.
|
|
25
|
+
- Escape — Closes the menu and returns focus to the trigger.
|
|
26
|
+
|
|
27
|
+
## DropdownMenu
|
|
28
|
+
|
|
29
|
+
Radix DropdownMenu root + trigger, re-exported as typed passthroughs.
|
|
30
|
+
|
|
31
|
+
## DropdownMenuTrigger
|
|
32
|
+
|
|
33
|
+
## DropdownMenuContent
|
|
34
|
+
|
|
35
|
+
A menu surface. A menu is a list of ACTIONS. If the items navigate somewhere, they belong in a nav; if they set a value, that is a `Select` or a `RadioGroup` — Radix has menu variants for both, and a plain item pretending to be a choice loses the checked state a screen reader needs.
|
|
36
|
+
|
|
37
|
+
Also accepts: `ComponentProps<typeof DropdownMenuPrimitive.Content>`.
|
|
38
|
+
|
|
39
|
+
## DropdownMenuItem
|
|
40
|
+
|
|
41
|
+
A menu row. Highlight is driven by Radix's `data-highlighted`, which covers both pointer hover and keyboard focus — styling `:hover` alone leaves the keyboard user unable to see where they are.
|
|
42
|
+
|
|
43
|
+
### Props
|
|
44
|
+
|
|
45
|
+
- `icon` — `LucideIcon`. Optional leading icon, rendered before the label.
|
|
46
|
+
- `destructive` — `boolean` default `false`. Paints the row as destructive. Use for delete, revoke, disconnect.
|
|
47
|
+
|
|
48
|
+
Also accepts: `ComponentProps<typeof DropdownMenuPrimitive.Item>`.
|
|
49
|
+
|
|
50
|
+
## DropdownMenuSeparator
|
|
51
|
+
|
|
52
|
+
Hairline divider between menu groups.
|
|
53
|
+
|
|
54
|
+
## DropdownMenuLabel
|
|
55
|
+
|
|
56
|
+
Mono eyebrow heading for a group of items.
|
|
57
|
+
|
|
58
|
+
## Examples
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
<DropdownMenu>
|
|
62
|
+
<DropdownMenuTrigger asChild><Button variant="secondary">Menu</Button></DropdownMenuTrigger>
|
|
63
|
+
<DropdownMenuContent>
|
|
64
|
+
<DropdownMenuLabel>Account</DropdownMenuLabel>
|
|
65
|
+
<DropdownMenuItem icon={Settings}>Settings</DropdownMenuItem>
|
|
66
|
+
<DropdownMenuSeparator />
|
|
67
|
+
<DropdownMenuItem icon={LogOut}>Sign out</DropdownMenuItem>
|
|
68
|
+
</DropdownMenuContent>
|
|
69
|
+
</DropdownMenu>
|
|
70
|
+
```
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# EmptyState
|
|
2
|
+
|
|
3
|
+
A collection with nothing in it — yet.
|
|
4
|
+
|
|
5
|
+
- Group: Feedback
|
|
6
|
+
- Import: `import { EmptyState } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/empty-state/
|
|
9
|
+
- Related: error-state, skeleton
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
Nothing went wrong. The copy says what to do, not what failed.
|
|
14
|
+
|
|
15
|
+
## EmptyState
|
|
16
|
+
|
|
17
|
+
A collection with nothing in it — yet. Distinct from `ErrorState`: nothing went wrong here, so the copy says what to do rather than what failed. The two are different components because the shared temptation — one component with a `variant` — produces error pages that read like empty folders.
|
|
18
|
+
|
|
19
|
+
### Props
|
|
20
|
+
|
|
21
|
+
- `icon` — `LucideIcon`. Optional lucide icon, shown muted inside a quiet circle.
|
|
22
|
+
- `title` (required) — `ReactNode`.
|
|
23
|
+
- `description` — `ReactNode`.
|
|
24
|
+
- `action` — `ReactNode`. The one thing to do next. An empty state without an action is a dead end.
|
|
25
|
+
|
|
26
|
+
Also accepts: `Omit<HTMLAttributes<HTMLDivElement>, 'title'>`.
|
|
27
|
+
|
|
28
|
+
## Examples
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
<EmptyState
|
|
32
|
+
icon={Inbox}
|
|
33
|
+
title="No projects yet"
|
|
34
|
+
description="Create your first project to get started."
|
|
35
|
+
action={<Button>New project</Button>}
|
|
36
|
+
/>
|
|
37
|
+
```
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# ErrorState
|
|
2
|
+
|
|
3
|
+
A page that could not be shown.
|
|
4
|
+
|
|
5
|
+
- Group: Feedback
|
|
6
|
+
- Import: `import { ErrorState } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/error-state/
|
|
9
|
+
- Related: empty-state, alert
|
|
10
|
+
|
|
11
|
+
## Accessibility
|
|
12
|
+
|
|
13
|
+
- The big status code is aria-hidden; the heading immediately after says the same thing in words.
|
|
14
|
+
|
|
15
|
+
## ERROR_ACTION_CLASS
|
|
16
|
+
|
|
17
|
+
The recovery affordance's look, exported so every error page offers the same one rather than each inventing a link style.
|
|
18
|
+
|
|
19
|
+
## ErrorState
|
|
20
|
+
|
|
21
|
+
A page that could not be shown. The code is set at the top of the type ladder and marked `aria-hidden` — read aloud, "404" before the sentence explaining it is noise, and the heading immediately after says the same thing in words.
|
|
22
|
+
|
|
23
|
+
### Props
|
|
24
|
+
|
|
25
|
+
- `code` (required) — `ReactNode`. The status, set large — "404", "500". Decorative; the heading carries the meaning.
|
|
26
|
+
- `heading` (required) — `ReactNode`.
|
|
27
|
+
- `message` (required) — `ReactNode`.
|
|
28
|
+
- `action` (required) — `ReactNode`. The way back. Render it with .
|
|
29
|
+
|
|
30
|
+
Also accepts: `HTMLAttributes<HTMLElement>`.
|
|
31
|
+
|
|
32
|
+
## Examples
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
<ErrorState
|
|
36
|
+
code="404"
|
|
37
|
+
heading="Page not found"
|
|
38
|
+
message="The page you're looking for has moved, or never existed."
|
|
39
|
+
action={<a href="/" className={ERROR_ACTION_CLASS}>Back home</a>}
|
|
40
|
+
/>
|
|
41
|
+
```
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Facet
|
|
2
|
+
|
|
3
|
+
The same chart once per group, on one shared scale.
|
|
4
|
+
|
|
5
|
+
- Group: Charts
|
|
6
|
+
- Import: `import { Facet } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/facet/
|
|
9
|
+
- Related: line-chart, sparkline
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
Eight series overplot into a hairball in one frame. Two or three series that genuinely need comparing point-for-point still belong in one chart.
|
|
14
|
+
|
|
15
|
+
## Accessibility
|
|
16
|
+
|
|
17
|
+
- The shared domain is the default and the whole point: on independent scales a group peaking at 40 and one peaking at 4,000 draw the same shape, and the comparison the reader came for is not merely lost but inverted.
|
|
18
|
+
- Every panel is a figure with its own accessible name, so a screen reader walks eight named charts rather than one unnamed grid.
|
|
19
|
+
- Panels beyond max fold into a stated overflow rather than being dropped, and the count is printed — a grid silently missing four groups is not something a reader can detect.
|
|
20
|
+
- Panel order is a choice the call site makes explicitly through sort, because reading order is what a reader takes as ranking.
|
|
21
|
+
|
|
22
|
+
## Facet
|
|
23
|
+
|
|
24
|
+
The same chart repeated once per group, on one shared scale — small multiples. The answer to the question a multi-series chart stops being able to answer at around five series: eight lines in one plot is a hairball, and the reader spends their attention untangling strands instead of reading them. Splitting the same lines across eight small plots costs the direct overlay comparison and buys back every individual shape, which is almost always the better trade — this is Tufte's small multiple, and Observable Plot and Vega-Lite both treat it as a first-class operation for the same reason. Reach for a multi-series `<LineChart>` or `<AreaChart>` instead when the series really do have to be read AGAINST each other — crossovers, gaps, shares of one total — and when there are few enough of them to tell apart. Reach for this when each group has its own shape worth seeing, when the groups are many, or when the reader's question is "which of these is different". What it gets right that a hand-rolled `data.map()` does not: the panels share one domain by default. On independent scales every panel fills its own plot, so a group peaking at 40 and a group peaking at 4,000 come out the same shape — the comparison is not merely lost, it is inverted, and nothing on screen says so. `panel.domain` is that shared scale; the render function has to pass it to the panel's value axis. It also caps the grid, folds or counts the tail, and prints one legend and one axis label instead of twelve.
|
|
25
|
+
|
|
26
|
+
### Props
|
|
27
|
+
|
|
28
|
+
- `title` (required) — `string`. What the whole grid shows, in a sentence a reader could act on. Required, and announced to a screen reader even when it is not printed.
|
|
29
|
+
- `showTitle` — `boolean`. Prints the title above the grid instead of hiding it from sight.
|
|
30
|
+
- `description` — `ReactNode`. A line under the title — the unit, the window, the caveat.
|
|
31
|
+
- `data` (required) — `TRow[]`. Every row, across every group. The split happens here, not at the call site.
|
|
32
|
+
- `by` (required) — `keyof TRow & string`. The row field the data is split on. One panel per distinct value.
|
|
33
|
+
- `value` (required) — `(keyof TRow & string) | (keyof TRow & string)[]`. The row field, or fields, holding the numbers. This is what the shared domain is measured over and what a statistical sort reads, so it has to name every series a panel draws — a panel that plots a field this does not mention can still overflow its own axis.
|
|
34
|
+
- `xDataKey` — `keyof TRow & string`. The shared category field — the x axis every panel has in common. Feeds the hidden table view, and is what lets `overflow="fold"` add the tail up at each category instead of concatenating it.
|
|
35
|
+
- `scales` — `FacetScales` default `'shared'`. Whether every panel is drawn against one domain or against its own. `"shared"` — the default, and the entire reason this component exists. On independent scales every panel fills its own plot, so a group peaking at 40 and a group peaking at 4,000 come out the same shape, and the comparison the reader opened the grid to make is not merely hard but actively wrong. The shared domain is computed across all the panels that survive the cap and handed to each one as `panel.domain`; a panel that does not pass it to its value axis has opted back into the broken version. `"independent"` is the escape hatch for the case where the panels are not comparable — different units, different orders of magnitude that carry no relation — and where each panel's own shape is the only reading. It is never the safe answer, which is why it is not the default.
|
|
36
|
+
- `domain` — `[number, number]`. Pins the domain outright, ignoring the data and `scales` alike.
|
|
37
|
+
- `includeZero` — `boolean` default `true`. Pulls the shared domain out to include zero. On by default, and the same default Recharts applies on its own: bars and areas read against a truncated baseline overstate every difference in the grid, and a grid exists to be compared. Turn it off when the values live far from zero and the differences between them ARE the reading — temperatures, latencies, ratings out of five.
|
|
38
|
+
- `nice` — `boolean` default `true`. Rounds the domain out so the panels' ticks land on numbers a reader recognises. Off, a shared domain of `[0, 314]` gives ticks at 78.5.
|
|
39
|
+
- `sort` — `FacetSort<TRow>` default `'max'`. The panel order. Defaults to the largest peak first, because that is what makes a grid readable: eye order becomes rank order, and "which of these is the problem" is answered by position before a single axis is read. `"name"` for a grid a reader will look things up in, an explicit array of names for an order the data does not carry — stages, weekdays, severities — and a comparator over `{ name, rows, stats }` for anything else.
|
|
40
|
+
- `order` — `'asc' | 'desc'`. The sort direction. Omit and it follows the sort: A→Z for a name or an explicit list, biggest first for a statistic.
|
|
41
|
+
- `limit` — `number | false` default `12`. How many panels are drawn before the rest are dealt with. Twelve by default rather than unlimited, because the failure this prevents is silent: a `by` field with forty values renders forty plots, each one roughly a postage stamp, and nothing on the page says the grid stopped being readable. `false` lifts the cap when the call site has genuinely decided to draw them all.
|
|
42
|
+
- `overflow` — `FacetOverflow` default `'note'`. What happens to the groups past the cap. `"note"` — the default — draws the top N and prints a line under the grid saying how many are missing. `"fold"` adds one more panel holding the tail summed at each category, the same bargain `BarList`'s "Other" row makes: the total stays true, and one panel absorbs the long tail. Either way a capped grid says so; nothing is dropped in silence.
|
|
43
|
+
- `otherLabel` — `string` default `'Other'`. What the folded panel is called.
|
|
44
|
+
- `overflowNote` — `(info: FacetOverflowInfo) => ReactNode` default `defaultOverflowNote`. Writes the line under a capped grid. The default sentence is English; this is where a translated call site replaces it.
|
|
45
|
+
- `columns` — `'auto' | number` default `'auto'`. How many columns the grid holds at its widest. `"auto"` — the default — fits as many panels as `minPanelWidth` allows and reflows on its own, which is the behaviour a card, a sidebar and a full-width page all need from the same call site. A number caps the count without pinning it: the grid still drops to fewer columns when the container is narrow, rather than shrinking twelve plots to nothing.
|
|
46
|
+
- `minPanelWidth` — `number` default `MIN_PANEL_PX`. How narrow a panel may get before the grid drops a column, in pixels.
|
|
47
|
+
- `legend` — `ReactNode`. One key for the whole grid, printed above it. A legend inside every panel is the same three swatches repeated twelve times, which is ink spent restating what the reader learned from the first panel. Put `<LineChart.Legend>` in one panel and this is unnecessary; put it here and take it out of the panels.
|
|
48
|
+
- `yLabel` — `ReactNode`. The value axis's name, printed once above the grid instead of per panel.
|
|
49
|
+
- `xLabel` — `ReactNode`. The category axis's name, printed once under the grid.
|
|
50
|
+
- `showPanelNames` — `boolean` default `true`. Prints each panel's group name above its plot. On by default. Turning it off only hides the name — it stays in the accessibility tree, because a grid whose panels a screen reader cannot tell apart is a grid with one figure and twelve anonymous plots in it.
|
|
51
|
+
- `hideDataTable` — `boolean` default `false`. Drops the hidden table view of every row. Worth setting when the panels' own charts already ship theirs — each chart in the package renders its rows as a table too, so a twelve-panel grid can otherwise put thirteen tables in the accessibility tree.
|
|
52
|
+
- `empty` — `ChartEmptyProps`. What the grid shows when the data yields no groups at all. No `false` escape hatch, unlike a single chart's: an empty pair of axes is at least a chart, but an empty grid is nothing — there is no reading for the absence to be.
|
|
53
|
+
- `className` — `string`. Merged onto the figure, last, so a call site can size or space it.
|
|
54
|
+
- `children` (required) — `(panel: FacetPanel<TRow>) => ReactNode`. One panel, called once per group. Hand `panel.domain` to the panel chart's value axis. That single line is what the component is for; without it the panels are on independent scales and the grid is decorative.
|
|
55
|
+
|
|
56
|
+
## Examples
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
<Facet title="Visitors by channel" data={rows} by="channel" value="visitors" xDataKey="month">
|
|
60
|
+
{(panel) => (
|
|
61
|
+
<LineChart title={`${panel.name} visitors`} config={config} data={panel.rows}>
|
|
62
|
+
<LineChart.XAxis dataKey="month" />
|
|
63
|
+
<LineChart.YAxis domain={panel.domain} />
|
|
64
|
+
<LineChart.Line dataKey="visitors" />
|
|
65
|
+
</LineChart>
|
|
66
|
+
)}
|
|
67
|
+
</Facet>
|
|
68
|
+
// Biggest first, six panels, the rest summed into one — and the grid says so.
|
|
69
|
+
<Facet
|
|
70
|
+
title="Requests by endpoint"
|
|
71
|
+
data={rows}
|
|
72
|
+
by="endpoint"
|
|
73
|
+
value="requests"
|
|
74
|
+
xDataKey="hour"
|
|
75
|
+
sort="sum"
|
|
76
|
+
limit={6}
|
|
77
|
+
overflow="fold"
|
|
78
|
+
columns={3}
|
|
79
|
+
>
|
|
80
|
+
{(panel) => <MiniBars rows={panel.rows} domain={panel.domain} />}
|
|
81
|
+
</Facet>
|
|
82
|
+
```
|