@misoto22/design 0.7.0 → 0.8.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/AGENTS.md +87 -0
- package/CLAUDE.md +1 -0
- package/README.md +50 -5
- package/bin/misoto22-design.mjs +59 -13
- package/dist/agent/Accordion.md +24 -1
- package/dist/agent/Alert.md +23 -1
- package/dist/agent/AppShell.md +30 -2
- package/dist/agent/ArchitectureFigure.md +25 -2
- package/dist/agent/AreaChart.md +27 -2
- package/dist/agent/Article.md +26 -3
- package/dist/agent/AspectRatio.md +57 -0
- package/dist/agent/Avatar.md +25 -5
- package/dist/agent/Badge.md +22 -1
- package/dist/agent/BarChart.md +29 -2
- package/dist/agent/BarList.md +27 -1
- package/dist/agent/BigNumber.md +26 -2
- package/dist/agent/BoxPlot.md +24 -1
- package/dist/agent/Breadcrumb.md +24 -2
- package/dist/agent/BulletChart.md +23 -1
- package/dist/agent/Button.md +25 -1
- package/dist/agent/Calendar.md +37 -3
- package/dist/agent/Card.md +24 -2
- package/dist/agent/Checkbox.md +23 -2
- package/dist/agent/Code.md +50 -0
- package/dist/agent/CodeBlock.md +74 -0
- package/dist/agent/Collapsible.md +22 -1
- package/dist/agent/Combobox.md +29 -3
- package/dist/agent/Command.md +25 -2
- package/dist/agent/ComposedChart.md +26 -2
- package/dist/agent/ContextMenu.md +37 -4
- package/dist/agent/DataflowFigure.md +22 -1
- package/dist/agent/DatePicker.md +34 -6
- package/dist/agent/DescriptionList.md +68 -0
- package/dist/agent/Diagram.md +27 -3
- package/dist/agent/DiagramCanvas.md +24 -1
- package/dist/agent/DiagramExportMenu.md +29 -3
- package/dist/agent/DiagramInspector.md +23 -1
- package/dist/agent/DiagramLegend.md +22 -1
- package/dist/agent/DiagramMinimap.md +24 -4
- package/dist/agent/DiagramToolbar.md +23 -1
- package/dist/agent/Dialog.md +26 -3
- package/dist/agent/DropdownMenu.md +45 -6
- package/dist/agent/EmptyState.md +26 -1
- package/dist/agent/ErrorState.md +27 -2
- package/dist/agent/Facet.md +25 -1
- package/dist/agent/Field.md +45 -4
- package/dist/agent/FigureBand.md +24 -1
- package/dist/agent/FloatingIconButton.md +23 -1
- package/dist/agent/FunnelChart.md +23 -1
- package/dist/agent/Heading.md +64 -0
- package/dist/agent/Heatmap.md +25 -1
- package/dist/agent/Histogram.md +26 -2
- package/dist/agent/Input.md +22 -1
- package/dist/agent/Kbd.md +19 -1
- package/dist/agent/LifecycleFigure.md +22 -1
- package/dist/agent/LineChart.md +26 -2
- package/dist/agent/LinkArrow.md +20 -1
- package/dist/agent/Markdown.md +68 -0
- package/dist/agent/NativeSelect.md +23 -2
- package/dist/agent/NavItem.md +21 -1
- package/dist/agent/Pagination.md +28 -2
- package/dist/agent/PieChart.md +26 -2
- package/dist/agent/Popover.md +23 -1
- package/dist/agent/Progress.md +27 -3
- package/dist/agent/RadarChart.md +26 -2
- package/dist/agent/RadialChart.md +26 -3
- package/dist/agent/RadioGroup.md +23 -2
- package/dist/agent/SankeyChart.md +25 -2
- package/dist/agent/ScatterChart.md +27 -2
- package/dist/agent/ScrollArea.md +24 -3
- package/dist/agent/SearchableMenu.md +23 -1
- package/dist/agent/Select.md +29 -3
- package/dist/agent/Separator.md +28 -4
- package/dist/agent/SequenceFigure.md +23 -1
- package/dist/agent/Sheet.md +25 -2
- package/dist/agent/Skeleton.md +24 -2
- package/dist/agent/Slider.md +27 -4
- package/dist/agent/Sparkline.md +23 -1
- package/dist/agent/Spinner.md +24 -2
- package/dist/agent/StatusDot.md +20 -1
- package/dist/agent/StatusPill.md +28 -2
- package/dist/agent/Steps.md +24 -1
- package/dist/agent/Switch.md +21 -1
- package/dist/agent/Table.md +26 -3
- package/dist/agent/Tabs.md +24 -2
- package/dist/agent/Tag.md +40 -9
- package/dist/agent/Text.md +65 -0
- package/dist/agent/Textarea.md +20 -1
- package/dist/agent/Timestamp.md +64 -0
- package/dist/agent/Toast.md +26 -2
- package/dist/agent/ToggleGroup.md +24 -2
- package/dist/agent/Toolbar.md +71 -0
- package/dist/agent/Tooltip.md +23 -1
- package/dist/agent/TreemapChart.md +24 -1
- package/dist/agent/WaterfallChart.md +24 -1
- package/dist/agent/WorkflowFigure.md +24 -2
- package/dist/agent/catalog.json +5602 -745
- package/dist/agent/index.md +13 -4
- package/dist/article.css +16 -4
- package/dist/charts/AreaChart/AreaChart.d.ts +9 -2
- package/dist/charts/AreaChart/AreaChart.js +12 -13
- package/dist/charts/AreaChart/AreaChart.js.map +1 -1
- package/dist/charts/BarChart/BarChart.d.ts +14 -3
- package/dist/charts/BarChart/BarChart.js +20 -12
- package/dist/charts/BarChart/BarChart.js.map +1 -1
- package/dist/charts/BarList/BarList.d.ts +9 -1
- package/dist/charts/BarList/BarList.js +9 -1
- package/dist/charts/BarList/BarList.js.map +1 -1
- package/dist/charts/BigNumber/BigNumber.d.ts +19 -3
- package/dist/charts/BigNumber/BigNumber.js +25 -5
- package/dist/charts/BigNumber/BigNumber.js.map +1 -1
- package/dist/charts/BoxPlot/BoxPlot.js +4 -2
- package/dist/charts/BoxPlot/BoxPlot.js.map +1 -1
- package/dist/charts/BulletChart/BulletChart.js +28 -7
- package/dist/charts/BulletChart/BulletChart.js.map +1 -1
- package/dist/charts/ComposedChart/ComposedChart.d.ts +9 -2
- package/dist/charts/ComposedChart/ComposedChart.js +10 -10
- package/dist/charts/ComposedChart/ComposedChart.js.map +1 -1
- package/dist/charts/FunnelChart/FunnelChart.d.ts +7 -2
- package/dist/charts/FunnelChart/FunnelChart.js +6 -16
- package/dist/charts/FunnelChart/FunnelChart.js.map +1 -1
- package/dist/charts/Heatmap/Heatmap.d.ts +17 -3
- package/dist/charts/Heatmap/Heatmap.js +20 -11
- package/dist/charts/Heatmap/Heatmap.js.map +1 -1
- package/dist/charts/Histogram/Histogram.d.ts +24 -1
- package/dist/charts/Histogram/Histogram.js +43 -11
- package/dist/charts/Histogram/Histogram.js.map +1 -1
- package/dist/charts/LineChart/LineChart.d.ts +9 -2
- package/dist/charts/LineChart/LineChart.js +11 -12
- package/dist/charts/LineChart/LineChart.js.map +1 -1
- package/dist/charts/PieChart/PieChart.d.ts +15 -3
- package/dist/charts/PieChart/PieChart.js +14 -6
- package/dist/charts/PieChart/PieChart.js.map +1 -1
- package/dist/charts/RadarChart/RadarChart.d.ts +15 -3
- package/dist/charts/RadarChart/RadarChart.js +11 -9
- package/dist/charts/RadarChart/RadarChart.js.map +1 -1
- package/dist/charts/RadialChart/RadialChart.d.ts +22 -4
- package/dist/charts/RadialChart/RadialChart.js +28 -6
- package/dist/charts/RadialChart/RadialChart.js.map +1 -1
- package/dist/charts/SankeyChart/SankeyChart.d.ts +16 -4
- package/dist/charts/SankeyChart/SankeyChart.js +14 -6
- package/dist/charts/SankeyChart/SankeyChart.js.map +1 -1
- package/dist/charts/ScatterChart/ScatterChart.d.ts +24 -3
- package/dist/charts/ScatterChart/ScatterChart.js +21 -15
- package/dist/charts/ScatterChart/ScatterChart.js.map +1 -1
- package/dist/charts/Sparkline/Sparkline.js +5 -3
- package/dist/charts/Sparkline/Sparkline.js.map +1 -1
- package/dist/charts/TreemapChart/TreemapChart.d.ts +7 -2
- package/dist/charts/TreemapChart/TreemapChart.js +20 -11
- package/dist/charts/TreemapChart/TreemapChart.js.map +1 -1
- package/dist/charts/WaterfallChart/WaterfallChart.js +4 -2
- package/dist/charts/WaterfallChart/WaterfallChart.js.map +1 -1
- package/dist/charts/lib/export.d.ts +1 -0
- package/dist/charts/lib/figure.d.ts +21 -1
- package/dist/charts/lib/figure.js +5 -2
- package/dist/charts/lib/figure.js.map +1 -1
- package/dist/charts/lib/scale.d.ts +23 -0
- package/dist/charts/lib/scale.js +13 -0
- package/dist/charts/lib/scale.js.map +1 -0
- package/dist/charts/lib/selection.d.ts +20 -0
- package/dist/charts/lib/selection.js +18 -0
- package/dist/charts/lib/selection.js.map +1 -0
- package/dist/charts/lib/toolbar.d.ts +1 -0
- package/dist/components/Accordion/Accordion.js +8 -1
- package/dist/components/Accordion/Accordion.js.map +1 -1
- package/dist/components/AppShell/AppShell.d.ts +6 -0
- package/dist/components/AppShell/AppShell.js +34 -4
- package/dist/components/AppShell/AppShell.js.map +1 -1
- package/dist/components/Article/Article.d.ts +11 -4
- package/dist/components/Article/Article.js +13 -0
- package/dist/components/Article/Article.js.map +1 -1
- package/dist/components/AspectRatio/AspectRatio.d.ts +46 -0
- package/dist/components/AspectRatio/AspectRatio.js +33 -0
- package/dist/components/AspectRatio/AspectRatio.js.map +1 -0
- package/dist/components/Avatar/Avatar.d.ts +12 -3
- package/dist/components/Avatar/Avatar.js +6 -1
- package/dist/components/Avatar/Avatar.js.map +1 -1
- package/dist/components/Breadcrumb/Breadcrumb.d.ts +6 -0
- package/dist/components/Breadcrumb/Breadcrumb.js +15 -0
- package/dist/components/Breadcrumb/Breadcrumb.js.map +1 -1
- package/dist/components/Button/Button.js +14 -0
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Calendar/Calendar.d.ts +29 -3
- package/dist/components/Calendar/Calendar.js +60 -12
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/Card/Card.d.ts +6 -0
- package/dist/components/Card/Card.js +1 -1
- package/dist/components/Card/Card.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.d.ts +5 -2
- package/dist/components/Checkbox/Checkbox.js +12 -2
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/Code/Code.d.ts +30 -0
- package/dist/components/Code/Code.js +21 -0
- package/dist/components/Code/Code.js.map +1 -0
- package/dist/components/CodeBlock/CodeBlock.d.ts +141 -0
- package/dist/components/CodeBlock/CodeBlock.js +123 -0
- package/dist/components/CodeBlock/CodeBlock.js.map +1 -0
- package/dist/components/Collapsible/Collapsible.js +10 -2
- package/dist/components/Collapsible/Collapsible.js.map +1 -1
- package/dist/components/Combobox/Combobox.d.ts +15 -1
- package/dist/components/Combobox/Combobox.js +25 -5
- package/dist/components/Combobox/Combobox.js.map +1 -1
- package/dist/components/Command/Command.d.ts +4 -2
- package/dist/components/Command/Command.js +13 -1
- package/dist/components/Command/Command.js.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.d.ts +30 -5
- package/dist/components/ContextMenu/ContextMenu.js +32 -2
- package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
- package/dist/components/DatePicker/DatePicker.d.ts +36 -4
- package/dist/components/DatePicker/DatePicker.js +55 -12
- package/dist/components/DatePicker/DatePicker.js.map +1 -1
- package/dist/components/DescriptionList/DescriptionList.d.ts +73 -0
- package/dist/components/DescriptionList/DescriptionList.js +35 -0
- package/dist/components/DescriptionList/DescriptionList.js.map +1 -0
- package/dist/components/Diagram/Diagram.d.ts +8 -3
- package/dist/components/Diagram/Diagram.js +82 -10
- package/dist/components/Diagram/Diagram.js.map +1 -1
- package/dist/components/Dialog/Dialog.d.ts +18 -3
- package/dist/components/Dialog/Dialog.js +20 -2
- package/dist/components/Dialog/Dialog.js.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.d.ts +49 -11
- package/dist/components/DropdownMenu/DropdownMenu.js +32 -2
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
- package/dist/components/EmptyState/EmptyState.d.ts +25 -1
- package/dist/components/EmptyState/EmptyState.js +3 -1
- package/dist/components/EmptyState/EmptyState.js.map +1 -1
- package/dist/components/ErrorState/ErrorState.d.ts +22 -1
- package/dist/components/ErrorState/ErrorState.js +11 -2
- package/dist/components/ErrorState/ErrorState.js.map +1 -1
- package/dist/components/Field/Field.d.ts +70 -3
- package/dist/components/Field/Field.js +53 -12
- package/dist/components/Field/Field.js.map +1 -1
- package/dist/components/Field/field-control.d.ts +31 -0
- package/dist/components/Field/field-control.js +12 -0
- package/dist/components/Field/field-control.js.map +1 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js +2 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js.map +1 -1
- package/dist/components/Heading/Heading.d.ts +62 -0
- package/dist/components/Heading/Heading.js +44 -0
- package/dist/components/Heading/Heading.js.map +1 -0
- package/dist/components/Markdown/Markdown.d.ts +139 -0
- package/dist/components/Markdown/Markdown.js +135 -0
- package/dist/components/Markdown/Markdown.js.map +1 -0
- package/dist/components/Markdown/inline.d.ts +29 -0
- package/dist/components/Markdown/inline.js +74 -0
- package/dist/components/Markdown/inline.js.map +1 -0
- package/dist/components/Markdown/nodes.d.ts +65 -0
- package/dist/components/Markdown/nodes.js +1 -0
- package/dist/components/Markdown/nodes.js.map +1 -0
- package/dist/components/Markdown/parse.d.ts +24 -0
- package/dist/components/Markdown/parse.js +110 -0
- package/dist/components/Markdown/parse.js.map +1 -0
- package/dist/components/Markdown/slug.d.ts +15 -0
- package/dist/components/Markdown/slug.js +7 -0
- package/dist/components/Markdown/slug.js.map +1 -0
- package/dist/components/NativeSelect/NativeSelect.d.ts +6 -0
- package/dist/components/NativeSelect/NativeSelect.js +2 -3
- package/dist/components/NativeSelect/NativeSelect.js.map +1 -1
- package/dist/components/Pagination/Pagination.d.ts +24 -1
- package/dist/components/Pagination/Pagination.js +6 -3
- package/dist/components/Pagination/Pagination.js.map +1 -1
- package/dist/components/Progress/Progress.d.ts +17 -5
- package/dist/components/Progress/Progress.js +18 -6
- package/dist/components/Progress/Progress.js.map +1 -1
- package/dist/components/RadioGroup/RadioGroup.d.ts +6 -0
- package/dist/components/RadioGroup/RadioGroup.js +11 -1
- package/dist/components/RadioGroup/RadioGroup.js.map +1 -1
- package/dist/components/ScrollArea/ScrollArea.d.ts +15 -0
- package/dist/components/ScrollArea/ScrollArea.js +2 -2
- package/dist/components/ScrollArea/ScrollArea.js.map +1 -1
- package/dist/components/SearchableMenu/SearchableMenu.d.ts +11 -2
- package/dist/components/SearchableMenu/SearchableMenu.js +24 -2
- package/dist/components/SearchableMenu/SearchableMenu.js.map +1 -1
- package/dist/components/Select/Select.d.ts +18 -2
- package/dist/components/Select/Select.js +20 -3
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Separator/Separator.d.ts +21 -3
- package/dist/components/Separator/Separator.js +9 -1
- package/dist/components/Separator/Separator.js.map +1 -1
- package/dist/components/Sheet/Sheet.d.ts +3 -0
- package/dist/components/Sheet/Sheet.js +11 -2
- package/dist/components/Sheet/Sheet.js.map +1 -1
- package/dist/components/Skeleton/Skeleton.d.ts +8 -1
- package/dist/components/Skeleton/Skeleton.js +1 -1
- package/dist/components/Skeleton/Skeleton.js.map +1 -1
- package/dist/components/Slider/Slider.d.ts +21 -3
- package/dist/components/Slider/Slider.js +54 -27
- package/dist/components/Slider/Slider.js.map +1 -1
- package/dist/components/Spinner/Spinner.d.ts +8 -0
- package/dist/components/Spinner/Spinner.js +3 -2
- package/dist/components/Spinner/Spinner.js.map +1 -1
- package/dist/components/StatusPill/StatusPill.d.ts +5 -0
- package/dist/components/StatusPill/StatusPill.js +6 -0
- package/dist/components/StatusPill/StatusPill.js.map +1 -1
- package/dist/components/Table/Table.d.ts +6 -0
- package/dist/components/Table/Table.js +3 -1
- package/dist/components/Table/Table.js.map +1 -1
- package/dist/components/Tag/Tag.d.ts +68 -9
- package/dist/components/Tag/Tag.js +50 -10
- package/dist/components/Tag/Tag.js.map +1 -1
- package/dist/components/Text/Text.d.ts +62 -0
- package/dist/components/Text/Text.js +30 -0
- package/dist/components/Text/Text.js.map +1 -0
- package/dist/components/Timestamp/Timestamp.d.ts +59 -0
- package/dist/components/Timestamp/Timestamp.js +56 -0
- package/dist/components/Timestamp/Timestamp.js.map +1 -0
- package/dist/components/Toast/Toast.d.ts +9 -1
- package/dist/components/Toast/Toast.js +27 -4
- package/dist/components/Toast/Toast.js.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.d.ts +6 -1
- package/dist/components/ToggleGroup/ToggleGroup.js +11 -1
- package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -1
- package/dist/components/Toolbar/Toolbar.d.ts +55 -0
- package/dist/components/Toolbar/Toolbar.js +43 -0
- package/dist/components/Toolbar/Toolbar.js.map +1 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.d.ts +6 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js +48 -8
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js.map +1 -1
- package/dist/diagrams/DataflowFigure/DataflowFigure.js +21 -2
- package/dist/diagrams/DataflowFigure/DataflowFigure.js.map +1 -1
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.d.ts +14 -0
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.js +14 -7
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.js.map +1 -1
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.d.ts +38 -4
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js +14 -16
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js.map +1 -1
- package/dist/diagrams/DiagramInspector/DiagramInspector.js +2 -2
- package/dist/diagrams/DiagramInspector/DiagramInspector.js.map +1 -1
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.d.ts +23 -7
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.js +45 -18
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.js.map +1 -1
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.js +44 -12
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.js.map +1 -1
- package/dist/diagrams/SequenceFigure/SequenceFigure.js +35 -5
- package/dist/diagrams/SequenceFigure/SequenceFigure.js.map +1 -1
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.d.ts +3 -1
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.js +76 -28
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.js.map +1 -1
- package/dist/diagrams/index.d.ts +1 -0
- package/dist/diagrams/index.js +10 -0
- package/dist/diagrams/index.js.map +1 -1
- package/dist/diagrams/lib/dev.d.ts +61 -0
- package/dist/diagrams/lib/dev.js +96 -0
- package/dist/diagrams/lib/dev.js.map +1 -0
- package/dist/diagrams/lib/frame.d.ts +48 -7
- package/dist/diagrams/lib/frame.js +17 -2
- package/dist/diagrams/lib/frame.js.map +1 -1
- package/dist/diagrams/lib/wires.js.map +1 -1
- package/dist/diagrams/spec.d.ts +64 -12
- package/dist/index.d.ts +16 -4
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/keyframes.css +57 -3
- package/dist/lib/overlay-container.d.ts +14 -4
- package/dist/lib/overlay-container.js.map +1 -1
- package/dist/lib/warn.d.ts +73 -0
- package/dist/lib/warn.js +38 -0
- package/dist/lib/warn.js.map +1 -0
- package/dist/semantic.css +17 -6
- package/dist/styles.css +1 -1
- package/dist/tokens.css +20 -2
- package/dist/tokens.d.ts +1 -1
- package/dist/tokens.js +39 -36
- package/dist/tokens.json +39 -36
- package/llms.txt +35 -0
- package/package.json +5 -2
- package/skills/misoto22-design/evals/evals.json +84 -0
- package/skills/misoto22-design/rules/a11y.md +55 -3
- package/skills/misoto22-design/rules/forms.md +5 -0
|
@@ -4,7 +4,7 @@ A state machine: what something can be, and what moves it between states.
|
|
|
4
4
|
|
|
5
5
|
- Group: Diagrams
|
|
6
6
|
- Import: `import { LifecycleFigure } from '@misoto22/design/diagrams'`
|
|
7
|
-
- Version: 0.
|
|
7
|
+
- Version: 0.8.0
|
|
8
8
|
- Docs: https://ui.misoto22.com/components/lifecycle-figure/
|
|
9
9
|
- Related: workflow-figure, steps
|
|
10
10
|
|
|
@@ -12,6 +12,27 @@ A state machine: what something can be, and what moves it between states.
|
|
|
12
12
|
|
|
13
13
|
The one figure that spends colour, and it spends exactly the two tokens the system reserves for state. Every other distinction is shape, so a greyscale print keeps six of the eight.
|
|
14
14
|
|
|
15
|
+
## Anatomy
|
|
16
|
+
|
|
17
|
+
- **Figure shell** (required) — The frame around the picture. What a machine hands it is a transition list with each note folded in after an em dash, so the condition on an arrow — the timeout, the retry count — is in the text copy and not only on the line.
|
|
18
|
+
- **State plate** (required) — One shape per kind: a filled cap for a start, a diamond for a decision, a dashed frame for a wait, a cut corner for an external, and the two washes the system reserves for the terminals. The name is centred, step sits in the leading corner and tag along the bottom edge.
|
|
19
|
+
- **Main rail** — The first lane’s states, sorted by col and joined consecutively at the emphasis weight — one line per neighbouring pair the transitions do not already declare, so a spine written out in full is drawn from the transitions and a spine left implied is drawn anyway. Without it the top row reads as five unconnected boxes, because the spine of a machine is the part nobody writes down.
|
|
20
|
+
- **Transition** — A routed line with its label on a mask and its note in a quieter line beneath. A declared transition between two rail neighbours replaces the implicit one rather than doubling it.
|
|
21
|
+
- **Lane** — A rule with a mono caption above it, drawn only as far as that lane’s own states reach. A lane past the first has its columns shifted along the main rail, which is what keeps a drop out of the spine vertical rather than a dogleg.
|
|
22
|
+
|
|
23
|
+
## Best practices
|
|
24
|
+
|
|
25
|
+
### Do
|
|
26
|
+
|
|
27
|
+
- Keep the first lane for the ordered spine and nothing else. Consecutive states there are joined by the implicit rail even when no transition declares the pair, so a state parked in lane 0 for spacing invents an edge the machine does not have. A state whose lane id nothing declares is kept out of that rail and reported as DIAGRAM_LANE_UNKNOWN instead, because a typo should not be able to add an arrow.
|
|
28
|
+
- Count a secondary lane’s columns from the rail. Every col in a lane past the first is shifted two columns along, so col: 0 in the second lane sits under col: 2 in the first — the convention archify’s lifecycle contract already implies, restated here because it is what makes a drop land on the state it came from.
|
|
29
|
+
- Say whether a failure is recoverable with an edge, not with the type. type: "failure" only paints the plate; a retryable error and a terminal one are identical until a reader follows the arrows out, and the one with none is where the run ended.
|
|
30
|
+
|
|
31
|
+
### Don’t
|
|
32
|
+
|
|
33
|
+
- yOffset moves the plate and moves nothing out of its way. The lane’s rule is drawn from what that lane holds, so a negative nudge drags the rule up with the state and a large positive one drops the plate into the band below — a state needing that much room wants a column of its own rather than a push.
|
|
34
|
+
- The figure claims a state can be left only the ways its arrows say. A cancel that can happen from anywhere and is drawn from nowhere reads as impossible, which is a reading the picture makes and the specification never wrote — draw it, or say in the subtitle that it is not drawn.
|
|
35
|
+
|
|
15
36
|
## Accessibility
|
|
16
37
|
|
|
17
38
|
- success and failure are the only coloured marks in the package’s diagrams, and each is also a distinct plate shape — colour is never the only carrier.
|
package/dist/agent/LineChart.md
CHANGED
|
@@ -4,7 +4,7 @@ Several series compared over a continuous axis.
|
|
|
4
4
|
|
|
5
5
|
- Group: Charts
|
|
6
6
|
- Import: `import { LineChart } from '@misoto22/design/charts'`
|
|
7
|
-
- Version: 0.
|
|
7
|
+
- Version: 0.8.0
|
|
8
8
|
- Docs: https://ui.misoto22.com/components/line-chart/
|
|
9
9
|
- Related: area-chart, composed-chart
|
|
10
10
|
|
|
@@ -12,6 +12,29 @@ Several series compared over a continuous axis.
|
|
|
12
12
|
|
|
13
13
|
The reader is comparing series against each other. When the area under one line is the point, fill it — that is an AreaChart.
|
|
14
14
|
|
|
15
|
+
## Anatomy
|
|
16
|
+
|
|
17
|
+
- **Figure frame** (required) — ChartFigure’s <figure> and its sr-only caption. description is announced with the title and printed only under showTitle, which is where a note about a clipped axis belongs.
|
|
18
|
+
- **Lines** (required) — <LineChart.Line>, one per series at a 1.6px stroke. isClickable adds a second, fully transparent 15px line underneath the visible one, because a hairline is not a pointer target.
|
|
19
|
+
- **Point markers** — <LineChart.Dot> and <LineChart.ActiveDot>, both slots and both off by default. The resting dot shares the intro wipe mask so it arrives with its own line; the active dot is never masked, because it exists only on hover, long after the wipe has finished.
|
|
20
|
+
- **Buffer segment** — buffer draws the last leg dashed by measuring the real path with getPointAtLength, so a projection reads as a different kind of fact at any curve type. Fewer than two drawable points and it falls back to a plain curve.
|
|
21
|
+
- **Sonification control** — <LineChart.Sonify>, a real <button> above the plot that plays the visible rows as pitch. Sound never starts from an effect, only from that click, and it reads the brushed window rather than the whole series.
|
|
22
|
+
- **Hidden data table** — The sr-only table of the full data. Recharts’ accessibilityLayer gives a keyboard cursor that announces one point at a time, which is navigation; this is the figures.
|
|
23
|
+
|
|
24
|
+
## Best practices
|
|
25
|
+
|
|
26
|
+
### Do
|
|
27
|
+
|
|
28
|
+
- This is the one chart in the family that survives a truncated value axis. A line encodes by SLOPE, so clipping the domain to the data’s own range is often what makes a two percent move visible at all — state the range in description when you do it.
|
|
29
|
+
- Reach for buffer on a period still open rather than dropping it. A part-month plotted solid reads as a crash; plotted as a dashed final leg it reads as what it is, which is incomplete.
|
|
30
|
+
- Compose <LineChart.Dot> when the series is sparse. With dots off — the default — five points are four segments, and the reader cannot tell a measured value from a bend in the interpolation.
|
|
31
|
+
|
|
32
|
+
### Don’t
|
|
33
|
+
|
|
34
|
+
- A single row draws nothing at all: one point has no segment, dot is false unless composed, and the empty state does not fire because a row exists. Guard the one-row case at the call site.
|
|
35
|
+
- Eight lines in one frame is a hairball, and a 1.6px stroke over an eight-step grey ramp makes it a worse one than a chromatic chart would. Past about five series the answer is Facet, not a ninth ramp slot — SERIES_SLOTS is 8 and there is no ninth.
|
|
36
|
+
- connectNulls turns a gap into a straight segment that looks measured. It costs more here than on an area, because the reader reads the slope of that invented segment as a rate.
|
|
37
|
+
|
|
15
38
|
## Accessibility
|
|
16
39
|
|
|
17
40
|
- title is required; the rows are also rendered as a visually hidden table.
|
|
@@ -34,7 +57,8 @@ Several series compared over a continuous axis — the shape for "which of these
|
|
|
34
57
|
- `chartProps` — `ComponentProps<typeof RechartsLineChart>`. Escape hatch onto the raw Recharts chart element.
|
|
35
58
|
- `curveType` — `ChartCurveType` default `'linear'`. How the line between two points is interpolated. Every mark inherits it unless it says otherwise.
|
|
36
59
|
- `animationType` — `ChartRevealType` default `'forward'`.
|
|
37
|
-
- `defaultSelectedDataKey` — `string | null` default `null`. The series lit on first render
|
|
60
|
+
- `defaultSelectedDataKey` — `string | null` default `null`. The series lit on first render, when the chart keeps its own selection.
|
|
61
|
+
- `selectedDataKey` — `string | null`. The selected series, driven from outside. Give this and the chart follows it; leave it undefined and the chart keeps its own, starting from `defaultSelectedDataKey`.
|
|
38
62
|
- `onSelectionChange` — `(selectedDataKey: string | null) => void`. Fires when the selection changes, and with null when it is cleared.
|
|
39
63
|
- `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.
|
|
40
64
|
- `loadingPoints` — `number`. How many points the skeleton draws.
|
package/dist/agent/LinkArrow.md
CHANGED
|
@@ -4,9 +4,28 @@ The mark on a link that leaves the page.
|
|
|
4
4
|
|
|
5
5
|
- Group: Display
|
|
6
6
|
- Import: `import { LinkArrow } from '@misoto22/design'`
|
|
7
|
-
- Version: 0.
|
|
7
|
+
- Version: 0.8.0
|
|
8
8
|
- Docs: https://ui.misoto22.com/components/link-arrow/
|
|
9
9
|
|
|
10
|
+
## Anatomy
|
|
11
|
+
|
|
12
|
+
- **Marker box** (required) — An aria-hidden inline-block <span> carrying the 0.22em of lead-in, the 0.28em baseline lift and --ink-3-aa. inline-block is load-bearing twice over: it stops an underlined parent drawing its rule through the glyph, and it is what the alignment is measured against.
|
|
13
|
+
- **Glyph** (required) — The ↗ itself at 0.68em, so it tracks the type beside it instead of competing with it. Exported as EXTERNAL_LINK_ARROW, so a surface that is not React uses the same character.
|
|
14
|
+
|
|
15
|
+
## Best practices
|
|
16
|
+
|
|
17
|
+
### Do
|
|
18
|
+
|
|
19
|
+
- Put it inside the <a>, as the last child. Outside it, it is an arrow pointing at a link the pointer misses by 0.22em.
|
|
20
|
+
- Reach for EXTERNAL_LINK_ARROW when the surface is not React — a Markdown pipeline, an OG image, an email — so the mark stays one character rather than three near-identical arrows across a site.
|
|
21
|
+
- Pass a colour through className on a reversed plate: it is set in --ink-3-aa, which is the AA floor against paper and close to invisible on ink.
|
|
22
|
+
|
|
23
|
+
### Don’t
|
|
24
|
+
|
|
25
|
+
- The arrow is not the announcement. It is aria-hidden, and target="_blank" is not announced either, so a link that opens a new tab has to say so in its own accessible name — otherwise this glyph is the only warning anyone gets, and only if they can see it.
|
|
26
|
+
- Do not pin it to a px size. 0.68em is what makes one component right in body copy and in a heading; fixed at 11px it is correct in one of them and a speck in the other.
|
|
27
|
+
- Do not put it on every row of an index. It marks a change of destination, so a list where every link leaves the site marks nothing at all and pays 0.22em a row for it.
|
|
28
|
+
|
|
10
29
|
## Accessibility
|
|
11
30
|
|
|
12
31
|
- aria-hidden, so it is not read as “north east arrow” in the middle of a sentence.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Markdown
|
|
2
|
+
|
|
3
|
+
A Markdown string, rendered as this system’s components.
|
|
4
|
+
|
|
5
|
+
- Group: Display
|
|
6
|
+
- Import: `import { Markdown } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.8.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/markdown/
|
|
9
|
+
- Related: article, code-block, heading, text
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
Content nobody on this side wrote — a comment, a README, a model’s answer. Trusted HTML from your own pipeline is an Article.
|
|
14
|
+
|
|
15
|
+
## Anatomy
|
|
16
|
+
|
|
17
|
+
- **Fragment** (required) — What it renders. There is no wrapper element, because Article’s rhythm is a direct-child combinator — anything between the two, display: contents included, would cost every paragraph its spacing.
|
|
18
|
+
- **Parser** (required) — parseMarkdown by default: ATX headings, paragraphs, fenced code, blockquotes, nested lists, thematic breaks, and inline emphasis, strong, code, links, images and escapes. Raw HTML is dropped rather than rendered, so this path has no dangerouslySetInnerHTML in it at all.
|
|
19
|
+
- **Nodes** (required) — The system’s own components: Heading, Text, Code, CodeBlock and Separator. That is what makes it styled on its own rather than only inside a reading column. One of them is not server-only — a fenced block renders CodeBlock, which is ‘use client’ with useState, useEffect and two icons, so content containing code brings a client component with it.
|
|
20
|
+
- **Heading ids** (required) — Slugged from each heading’s own text, in any script, deduplicated within the document with -2, -3. Exported as slugify, so a table of contents can arrive at the same ids without reading them back off the DOM.
|
|
21
|
+
|
|
22
|
+
## Best practices
|
|
23
|
+
|
|
24
|
+
### Do
|
|
25
|
+
|
|
26
|
+
- Set headingLevelStart to the level BELOW the heading the content sits under. Markdown is written as a document, so its # is an <h1>; dropped into a page that already has one, that is two first-level headings and an outline nobody can navigate.
|
|
27
|
+
- Put it inside an Article — <Article as="div"> for a comment or an answer, <Article> for a document. Markdown makes the nodes, Article is the column they sit in and the only thing that spaces them, which is also why Markdown renders no element of its own.
|
|
28
|
+
- Pass idPrefix when two documents share a page. Both would otherwise claim #installation, and a fragment link lands on whichever the browser found first.
|
|
29
|
+
- Bring your own parser through parse for tables, footnotes or task lists. The package ships no parser dependency on purpose: markdown-it measures 110.7 kB minified against the 38.9 kB this package had left under its bundle budget.
|
|
30
|
+
|
|
31
|
+
### Don’t
|
|
32
|
+
|
|
33
|
+
- Do not hand it HTML. It parses Markdown; a string of tags renders as the text of those tags, which is the safe answer and not the one you wanted — trusted HTML belongs in Article.
|
|
34
|
+
- Do not expect the rhythm without a surface, and do not try to buy it with a gap. Every node renders m-0 into a bare fragment, and prose spacing is not uniform — article.css gives a heading 2.25em above and 0.75em below, which is what sits it with the paragraph it introduces. A uniform gap on a container cannot reproduce that; <Article as="div"> can.
|
|
35
|
+
- Do not assume the full GFM surface. Tables, footnotes, task lists, setext headings, reference links and hard breaks are outside the built-in parser, and asking for one silently gets you a paragraph.
|
|
36
|
+
|
|
37
|
+
## Accessibility
|
|
38
|
+
|
|
39
|
+
- headingLevelStart shifts the whole document at once, so nested content keeps a valid outline instead of restarting at h1.
|
|
40
|
+
- Every heading gets a stable, script-preserving id, deduplicated in document order, so a table of contents can link into it.
|
|
41
|
+
- A link whose href carries a scheme that is not http, https, mailto or tel renders as plain text — javascript: never becomes a control.
|
|
42
|
+
- A link that leaves for another site carries rel="noreferrer nofollow", so an untrusted author cannot spend the page’s ranking or read its URL out of the Referer. It is not configurable; markExternalLinks adds the visible outbound arrow and is off by default.
|
|
43
|
+
- A malformed or empty string renders nothing rather than throwing, which is the normal case for content a reader wrote.
|
|
44
|
+
|
|
45
|
+
## Markdown
|
|
46
|
+
|
|
47
|
+
A Markdown string, rendered as this system's components. The gap it fills is content nobody on this side wrote: a comment, a README, a model's answer, a description out of a database. `Article` cannot take those — it renders HTML through `dangerouslySetInnerHTML` and is documented as trusted-input-only — and until now the alternative was a `<pre>` or a sanitiser bolted onto a styling primitive. IT IS NOT AN `Article`, and the two do not merge. `Markdown` turns a string into nodes; `Article` is the reading column those nodes can sit in. It renders a FRAGMENT rather than a wrapper, which is what makes that nesting work — `Article`'s rhythm is a direct-child combinator, so any element between the two, `display: contents` included, would cost every paragraph its spacing. ── It brings type and colour, and no vertical rhythm ── The nodes carry the system's faces and inks on their own, so one of these looks right in isolation. It is not SPACED in isolation: every node renders `m-0`, and a fragment has no box of its own to put a gap in. Nor does a uniform `gap` on a container reproduce it, because prose spacing is not uniform — `article.css` gives a heading 2.25em above and 0.75em below, which is what sits a heading with the paragraph it introduces rather than midway between two. For anything longer than a sentence — a comment, an answer, a README — put it in `<Article as="div">` and get the real rhythm for the cost of one element. ── A fenced code block brings a client component with it ── The renderer is plain functions and has no state, but a fenced block renders `CodeBlock`, which is `'use client'` and arrives with `useState`, `useEffect` and two icons. That is correct — the copy button is the reason the block exists — but "server-rendered" only holds for content with no code in it, which is worth knowing before this goes into a route that has no client bundle yet. ── Why there is no parser in `dependencies` ── Three options, and the decision is written here because it is the one a reader will want to argue with. 1. BUNDLE A PARSER. markdown-it is the obvious pick, and the documentation site already depends on it — but the site is an app and this is a library, where the dependency list is part of the contract every consumer signs. Measured with the same esbuild pass `check:size` uses, markdown-it is 110.7 kB minified against the 38.9 kB this package had left under its bundle budget. It is not close, and "we will raise the budget" is how a design system becomes the largest thing on a page. 2. TAKE PRE-PARSED HTML, the way `Article` does. Cheapest, and wrong for the case this exists for: HTML from an untrusted author is the input this is supposed to make safe, and it cannot carry `headingLevelStart` or stable heading ids without the component parsing markup back apart to find them. 3. PARSE THE SUBSET WE STYLE, and take a `parse` function for the rest. Chosen. The block grammar is line-based and small (see `parse.ts`), it emits React elements rather than markup — so there is no `dangerouslySetInnerHTML` in this path at all, no sanitiser to configure and no sanitiser to get wrong — and a consumer who needs tables, footnotes or task lists passes `parse` and keeps every other promise the component makes. Headings carry an `id` slugged from their own text and deduplicated within the document, so a table of contents can link to them without the caller post-processing the DOM to find out where they went. A link in the source is validated here, at the boundary: a scheme that is not `http`, `https`, `mailto` or `tel` never becomes a link, and one that leaves for another site carries `rel="noreferrer nofollow"` — so an author the page does not trust cannot spend its ranking or read its URL out of the `Referer`.
|
|
48
|
+
|
|
49
|
+
### Props
|
|
50
|
+
|
|
51
|
+
- `children` (required) — `string`. The Markdown source. A string — not nodes, not HTML.
|
|
52
|
+
- `headingLevelStart` — `MarkdownHeadingLevel` default `1`. The level the document's top heading renders at. Markdown is written as a document, so its `#` is an `<h1>`. Dropped into a page that already has one — inside an `<h2>` section, in a card, under a dialog's title — that produces two first-level headings and an outline a screen reader cannot navigate. Set this to the level BELOW the heading the content sits under, and every level in the document shifts with it.
|
|
53
|
+
- `idPrefix` — `string`. Namespaces the generated heading ids. Two documents on one page both containing "Installation" would otherwise both claim `#installation`, and a fragment link would land on whichever the browser found first.
|
|
54
|
+
- `markExternalLinks` — `boolean` default `false`. Adds the system's outbound arrow to links that leave for another site. Off by default, and opt-in rather than automatic for two reasons. The mark is an addition to a sentence the component did not write, which is a different kind of act from styling one. And `Markdown` has no idea what origin it is being rendered on, so "leaves for another site" can only mean "carries an `http`/`https` scheme" — an absolute link back to your own domain gets the arrow too. A caller who knows the shape of their content turns it on; one who does not should not have it turned on for them. The `rel` on an outbound link is NOT opt-in and cannot be turned off: it is the security half of the same boundary as the scheme check.
|
|
55
|
+
- `parse` — `(source: string) => MarkdownNode[]` default `parseMarkdown`. Bring your own parser. Anything that turns the source into `MarkdownNode`s: markdown-it, remark, or a pipeline that already has an AST and only needs mapping. The node shapes are exported alongside the component as `MarkdownNode`, `MarkdownInline` and `MarkdownHeadingLevel`. The built-in parser covers the subset this system styles; this is the seam for tables, footnotes, task lists and everything else.
|
|
56
|
+
|
|
57
|
+
## Examples
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
// A comment body or an answer: the reading column is what spaces it.
|
|
61
|
+
<Article as="div">
|
|
62
|
+
<Markdown headingLevelStart={3} idPrefix="answer">{answer}</Markdown>
|
|
63
|
+
</Article>
|
|
64
|
+
// A whole document, in the column it was written for.
|
|
65
|
+
<Article><Markdown>{readme}</Markdown></Article>
|
|
66
|
+
// Tables and footnotes, via the consumer's own pipeline.
|
|
67
|
+
<Markdown parse={(source) => toMarkdownNodes(md.parse(source, {}))}>{post}</Markdown>
|
|
68
|
+
```
|
|
@@ -4,7 +4,7 @@ The platform’s own picker, restyled where it can be.
|
|
|
4
4
|
|
|
5
5
|
- Group: Forms
|
|
6
6
|
- Import: `import { NativeSelect } from '@misoto22/design'`
|
|
7
|
-
- Version: 0.
|
|
7
|
+
- Version: 0.8.0
|
|
8
8
|
- Docs: https://ui.misoto22.com/components/native-select/
|
|
9
9
|
- Related: select, field
|
|
10
10
|
|
|
@@ -12,6 +12,27 @@ The platform’s own picker, restyled where it can be.
|
|
|
12
12
|
|
|
13
13
|
The escape hatch, not the default. Reach for it where the platform genuinely wins: a very long list on a phone, a form that must work without JavaScript, a page counting its last kilobyte.
|
|
14
14
|
|
|
15
|
+
## Anatomy
|
|
16
|
+
|
|
17
|
+
- **Wrapper** (required) — A relative <div> around the pair, and the element className lands on. It is the only control in this group where className does not go to the field itself, because the chevron is pinned to this box: a width set anywhere else strands the arrow at the far edge of the row.
|
|
18
|
+
- **Control box** (required) — The <select> on CONTROL_BASE, appearance-none so the platform’s own arrow is gone, with pe-9 of end padding so the longest option clears the drawn one. It fills the wrapper, so the wrapper’s width is the field’s width.
|
|
19
|
+
- **Chevron** (required) — A pointer-events-none icon pinned to the wrapper’s end edge. It is ours, not the platform’s, so it does not flip or move when the picker opens.
|
|
20
|
+
- **Option list** — children, drawn by the operating system on open. <option> and <optgroup> are the only things in it, and neither takes these tokens.
|
|
21
|
+
|
|
22
|
+
## Best practices
|
|
23
|
+
|
|
24
|
+
### Do
|
|
25
|
+
|
|
26
|
+
- Give it an explicit empty first option, or a defaultValue. A <select> nobody touches has its first option selected, so an untouched form submits the top of the list as though someone chose it.
|
|
27
|
+
- Group with <optgroup>: it is the one piece of structure the OS picker actually renders, and there is no styled equivalent to fall back on the way SelectLabel gives Select one.
|
|
28
|
+
- Set the width with className. It lands on the wrapper the chevron is pinned to and the select fills it, so the arrow travels with the edge of the field rather than staying where the row ends.
|
|
29
|
+
|
|
30
|
+
### Don’t
|
|
31
|
+
|
|
32
|
+
- multiple and size do not survive the styling: appearance-none plus a chevron pinned to the middle of the wrapper turns a list box into a scrolling column with an arrow drawn across it. Use checkboxes, or a multiple Combobox.
|
|
33
|
+
- Do not use the first option as the label. “Select a country” is announced as a choosable value and it is the value an untouched form submits — put the name in a Field and give that option value="" and disabled.
|
|
34
|
+
- Do not send the control’s own ink or border through className: it dresses the wrapper, and the <select> inside keeps CONTROL_BASE whatever the box around it says.
|
|
35
|
+
|
|
15
36
|
## Accessibility
|
|
16
37
|
|
|
17
38
|
- Typeahead and the mobile wheel come free, from the browser.
|
|
@@ -24,7 +45,7 @@ The escape hatch, not the default. Reach for it where the platform genuinely win
|
|
|
24
45
|
|
|
25
46
|
## NativeSelect
|
|
26
47
|
|
|
27
|
-
A native `<select>`, restyled. The escape hatch, not the default — `Select` is the styled one. Reach for this where the platform's own picker is genuinely better: a very long list on a phone, a form that must work without JavaScript, a page where the last kilobyte matters. The browser gives typeahead and the mobile wheel for free, and those are real. What it cannot do is look like the rest of the system once open. The option list is drawn by the operating system, so it carries none of these tokens — which is exactly why it stopped being the default.
|
|
48
|
+
A native `<select>`, restyled. The escape hatch, not the default — `Select` is the styled one. Reach for this where the platform's own picker is genuinely better: a very long list on a phone, a form that must work without JavaScript, a page where the last kilobyte matters. The browser gives typeahead and the mobile wheel for free, and those are real. What it cannot do is look like the rest of the system once open. The option list is drawn by the operating system, so it carries none of these tokens — which is exactly why it stopped being the default. `className` sizes the WRAPPER, not the `<select>` inside it. This is the one control here that renders two elements, and the chevron is pinned to the wrapper's end edge: a width on the select alone narrowed the box and left the arrow floating at the far side of the row. The select fills whatever the wrapper is.
|
|
28
49
|
|
|
29
50
|
### Props
|
|
30
51
|
|
package/dist/agent/NavItem.md
CHANGED
|
@@ -4,10 +4,30 @@ A row in a sidebar.
|
|
|
4
4
|
|
|
5
5
|
- Group: Navigation
|
|
6
6
|
- Import: `import { NavItem } from '@misoto22/design'`
|
|
7
|
-
- Version: 0.
|
|
7
|
+
- Version: 0.8.0
|
|
8
8
|
- Docs: https://ui.misoto22.com/components/nav-item/
|
|
9
9
|
- Related: app-shell
|
|
10
10
|
|
|
11
|
+
## Anatomy
|
|
12
|
+
|
|
13
|
+
- **Row** (required) — An <a href> at --control-h-sm with the --radius corner — or, under asChild, the router link you handed it, which receives the classes and aria-current and becomes the row itself.
|
|
14
|
+
- **Icon** — An optional lucide component at 18px, aria-hidden, ahead of the label. It is rendered by the native branch only: a slotted row takes its icon inside the child, because Slot accepts exactly one.
|
|
15
|
+
- **Label** (required) — children, and the row’s whole accessible name — the icon contributes nothing to it.
|
|
16
|
+
- **Active ground** — What active turns on, in one move: a --stone fill, medium weight, and aria-current="page". Three signals, so the current row survives monochrome and low contrast.
|
|
17
|
+
|
|
18
|
+
## Best practices
|
|
19
|
+
|
|
20
|
+
### Do
|
|
21
|
+
|
|
22
|
+
- Repeat href on the slotted child: asChild forwards the classes and aria-current and nothing else, so a <Link> that does not carry its own href is a row that navigates nowhere.
|
|
23
|
+
- Put the icon inside the child in asChild mode — the icon prop is silently dropped there, which is how a whole sidebar renders as a column of unlabelled-looking rows.
|
|
24
|
+
- Derive active from the router’s current path rather than from the last click: it is what writes aria-current="page", so a sidebar tracking its own clicks tells a reader they are on the row they pressed instead of the page they are on.
|
|
25
|
+
|
|
26
|
+
### Don’t
|
|
27
|
+
|
|
28
|
+
- Do not mark a parent row active to show which section contains the page: active means aria-current="page", and two of them is a reader told they are in two places at once.
|
|
29
|
+
- Do not tighten the row further: it is --control-h-sm, which is 36px comfortable and 30px under data-density="compact", and a py class below that leaves a column of targets a thumb has to aim at.
|
|
30
|
+
|
|
11
31
|
## Accessibility
|
|
12
32
|
|
|
13
33
|
- aria-current="page" and not only a colour: the active row is also carried by weight and a filled ground.
|
package/dist/agent/Pagination.md
CHANGED
|
@@ -4,14 +4,37 @@ Numbered pages, with the middle elided.
|
|
|
4
4
|
|
|
5
5
|
- Group: Navigation
|
|
6
6
|
- Import: `import { Pagination } from '@misoto22/design'`
|
|
7
|
-
- Version: 0.
|
|
7
|
+
- Version: 0.8.0
|
|
8
8
|
- Docs: https://ui.misoto22.com/components/pagination/
|
|
9
9
|
- Related: breadcrumb
|
|
10
10
|
|
|
11
|
+
## Anatomy
|
|
12
|
+
|
|
13
|
+
- **Nav** (required) — A <nav> named by label, “Pagination” by default. Nothing else here is a landmark, so this is how a reader jumps to the pager rather than scrolling to it.
|
|
14
|
+
- **Step buttons** (required) — Previous and Next, pill-cornered at --control-h-sm, named by previousLabel and nextLabel — “Previous page” and “Next page” until a call site says otherwise. Each is disabled at its end of the range, which takes it out of the tab order rather than leaving a control that does nothing.
|
|
15
|
+
- **Page list** (required) — An <ol> of numbers, each a <button> named by pageLabel — “Page N” by default — and carrying aria-current on the one you are on.
|
|
16
|
+
- **Travelling pill** — One aria-hidden fill, measured from the selected button and moved with a transform rather than two grounds cross-fading. It is absent until the first measurement lands, and holds still under prefers-reduced-motion.
|
|
17
|
+
- **Ellipsis** — An aria-hidden <li> wherever the sequence skips more than one page. A single skipped page is printed instead — “1 … 3” is longer than “1 2 3” and says less.
|
|
18
|
+
|
|
19
|
+
## Best practices
|
|
20
|
+
|
|
21
|
+
### Do
|
|
22
|
+
|
|
23
|
+
- Move page in the same state update that fetches: it is fully controlled, so a handler that loads the next page without setting page leaves the pager marking the page the reader just left.
|
|
24
|
+
- Raise siblings rather than lowering it — below 2 × siblings + 5 pages every page is printed anyway, so the prop does nothing on a short list and is the only lever you have on a long one.
|
|
25
|
+
- Import paginationRange when something else has to agree with the pager: it is exported and pure, which is how a server-rendered summary and this component end up describing one window instead of two.
|
|
26
|
+
- Let the surrounding row collapse: the component returns null at one page or fewer, so a footer built to a fixed height shows an empty strip on the day the list gets short.
|
|
27
|
+
|
|
28
|
+
### Don’t
|
|
29
|
+
|
|
30
|
+
- Do not put it in a compact region and call it a touch target: the pills are --control-h-sm, 36px comfortable and 30px under data-density="compact", set 4px apart — well under the 44px WCAG 2.5.5 asks of a pointer target.
|
|
31
|
+
- Do not expect pageLabel to change what is printed. It names the control for a screen reader and nothing else; the button still shows the Western digit it was handed, so a locale that writes its numerals differently has to format them at the call site as well.
|
|
32
|
+
|
|
11
33
|
## Accessibility
|
|
12
34
|
|
|
13
35
|
- The current page is a button with aria-current, not a styled span — a reader jumping by control needs to find it.
|
|
14
36
|
- Renders nothing at one page. A pager for a single page is furniture.
|
|
37
|
+
- Every string a reader hears is a prop: the two chevrons by name, each numbered page through pageLabel — a function rather than a template, because “Page 3” is a phrase whose parts move around between languages.
|
|
15
38
|
|
|
16
39
|
## Keyboard
|
|
17
40
|
|
|
@@ -24,7 +47,7 @@ Builds the visible page list: always the first and last page, a window around th
|
|
|
24
47
|
|
|
25
48
|
## Pagination
|
|
26
49
|
|
|
27
|
-
Numbered pagination. The current page is marked by one filled pill that TRAVELS between the numbers rather than by a background switching off on one and on on another. Two backgrounds cross-fading reads as two things changing; a shape moving reads as the one thing that actually did. A `<nav>` wrapping a list, and the current page is a `<button aria-current>` rather than a styled `<span>` — a reader jumping by landmark needs to find the control, and a reader on the current page needs to be told they are already there. Renders nothing at one page or fewer. A pager for a single page is furniture.
|
|
50
|
+
Numbered pagination. The current page is marked by one filled pill that TRAVELS between the numbers rather than by a background switching off on one and on on another. Two backgrounds cross-fading reads as two things changing; a shape moving reads as the one thing that actually did. A `<nav>` wrapping a list, and the current page is a `<button aria-current>` rather than a styled `<span>` — a reader jumping by landmark needs to find the control, and a reader on the current page needs to be told they are already there. Renders nothing at one page or fewer. A pager for a single page is furniture. Every string a reader hears is a prop. The chevrons carry no text, so `previousLabel` and `nextLabel` are the whole of those two controls' names, and `pageLabel` is a function because "Page 3" is a phrase whose parts move around between languages.
|
|
28
51
|
|
|
29
52
|
### Props
|
|
30
53
|
|
|
@@ -33,6 +56,9 @@ Numbered pagination. The current page is marked by one filled pill that TRAVELS
|
|
|
33
56
|
- `onPageChange` (required) — `(page: number) => void`.
|
|
34
57
|
- `siblings` — `number` default `1`. How many numbered pages sit either side of the current one.
|
|
35
58
|
- `label` — `string` default `'Pagination'`.
|
|
59
|
+
- `previousLabel` — `string` default `'Previous page'`. Names the two step controls. Each is a chevron and nothing else, so these strings are its entire accessible name — the same reason `AppShell` exposes `openLabel` and `closeLabel` rather than baking them in.
|
|
60
|
+
- `nextLabel` — `string` default `'Next page'`.
|
|
61
|
+
- `pageLabel` — `(page: number) => string` default `(page) => `Page ${page}``. Names one numbered page. A function rather than a template, because the number does not sit in the same place in every language and neither does the noun around it — `"Page 3"`, `"第 3 页"`, `"Seite 3"`. The visible digit is the same either way; this is what a screen reader hears instead of a bare number.
|
|
36
62
|
|
|
37
63
|
Also accepts: `Omit<HTMLAttributes<HTMLElement>, 'onChange'>`.
|
|
38
64
|
|
package/dist/agent/PieChart.md
CHANGED
|
@@ -4,7 +4,7 @@ Parts of one whole.
|
|
|
4
4
|
|
|
5
5
|
- Group: Charts
|
|
6
6
|
- Import: `import { PieChart } from '@misoto22/design/charts'`
|
|
7
|
-
- Version: 0.
|
|
7
|
+
- Version: 0.8.0
|
|
8
8
|
- Docs: https://ui.misoto22.com/components/pie-chart/
|
|
9
9
|
- Related: radial-chart, bar-chart
|
|
10
10
|
|
|
@@ -12,6 +12,28 @@ Parts of one whole.
|
|
|
12
12
|
|
|
13
13
|
Roughly what share, and nothing more precise. Ranking or comparing wedges — especially across two pies — is a BarChart’s job.
|
|
14
14
|
|
|
15
|
+
## Anatomy
|
|
16
|
+
|
|
17
|
+
- **Figure frame** (required) — ChartFigure’s <figure>, with an empty state at zero rows. There are no axes here, so without one a pie at zero rows was a name over a blank box with the hidden table returning null — the picture and its text equivalent silent together. empty={false} restores that, for a chart whose emptiness is the reading.
|
|
18
|
+
- **Wedges** (required) — <PieChart.Pie>. Each sector is painted from a diagonal gradient keyed on the row’s nameKey value, so config keys must match those values exactly — a row whose name is absent from config points at a gradient that was never defined and comes out unpainted.
|
|
19
|
+
- **Legend** — <PieChart.Legend>, under the pie and centred by default. A pie has no category axis naming its sectors, so this is where the names live.
|
|
20
|
+
- **Wedge labels** — <PieChart.Label>, a LabelList reversed out in --chart-surface. Its dataKey defaults to the pie’s VALUE key, so composing it prints the numbers.
|
|
21
|
+
- **Tooltip** — <PieChart.Tooltip>, with the heading suppressed: the wedge’s own name is the row label, so a heading would print it twice.
|
|
22
|
+
|
|
23
|
+
## Best practices
|
|
24
|
+
|
|
25
|
+
### Do
|
|
26
|
+
|
|
27
|
+
- Keep it under about five wedges. Past that the reader is ranking angles, which is the comparison a pie is worst at — a BarChart puts the same shares on a length scale and the ranking falls out of the picture for free.
|
|
28
|
+
- Compose <PieChart.Label> whenever the exact share matters. It defaults to the value key, and a printed number removes the angle estimate entirely, which is this form’s only real weakness and its cheapest fix.
|
|
29
|
+
- Give it an innerRadius. A donut is read by arc LENGTH rather than by wedge area, which the eye does better, and the hole is somewhere to put the total.
|
|
30
|
+
|
|
31
|
+
### Don’t
|
|
32
|
+
|
|
33
|
+
- A negative value has no wedge. Parts of one whole cannot include a negative part, so a breakdown carrying a refund or churn against expansion is a WaterfallChart, which is built for signed contributions.
|
|
34
|
+
- Two pies side by side is not a comparison. Reading a wedge across two circles is harder than reading two wedges inside one, and the reader will try anyway — put the two periods in one grouped BarChart.
|
|
35
|
+
- Pass a POSITIVE paddingAngle if the chart has to survive forced colours. There is one fill variant here, so all eight --series-* tokens collapse to CanvasText and every wedge is the same solid shape; what separates them is geometry, and a gap of a degree or two is it. The stroke is not the mechanism — it is drawn only when paddingAngle is NEGATIVE, where the wedges overlap and the surface-coloured stroke re-separates them into stacked cards. 0 is the one value with neither, and a default pie in forced colours is one uniform disc with the legend and the labels carrying the whole reading.
|
|
36
|
+
|
|
15
37
|
## Accessibility
|
|
16
38
|
|
|
17
39
|
- title is required; the rows are also rendered as a visually hidden table.
|
|
@@ -35,10 +57,12 @@ Parts of one whole. Worth saying plainly: a pie answers "roughly what share" and
|
|
|
35
57
|
- `children` (required) — `ReactNode`. The composed parts — axes, grid, tooltip, legend, and the marks themselves.
|
|
36
58
|
- `className` — `string`. Merged onto the figure, last, so a call site can size or space it.
|
|
37
59
|
- `chartProps` — `ComponentProps<typeof RechartsPieChart>`. Escape hatch onto the raw Recharts chart element.
|
|
38
|
-
- `defaultSelectedSector` — `string | null` default `null`. The sector lit on first render.
|
|
60
|
+
- `defaultSelectedSector` — `string | null` default `null`. The sector lit on first render, when the chart keeps its own selection.
|
|
61
|
+
- `selectedSector` — `string | null`. The selected sector, driven from outside. Give this and the chart follows it; leave it undefined and the chart keeps its own, starting from `defaultSelectedSector`.
|
|
39
62
|
- `onSelectionChange` — `(selection: { name: string; value: number } | null) => void`. Fires when the selection changes, and with null when it is cleared.
|
|
40
63
|
- `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.
|
|
41
64
|
- `hideDataTable` — `boolean` default `false`. Drops the hidden table view. Only correct when the page prints the data itself.
|
|
65
|
+
- `empty` — `ChartEmptyProps | false`. What the chart shows when it has nothing to draw. `false` keeps the empty plot, for a chart whose emptiness is itself the reading.
|
|
42
66
|
|
|
43
67
|
## Types
|
|
44
68
|
|
package/dist/agent/Popover.md
CHANGED
|
@@ -4,7 +4,7 @@ A panel anchored to a control, holding content you can interact with.
|
|
|
4
4
|
|
|
5
5
|
- Group: Overlays
|
|
6
6
|
- Import: `import { Popover } from '@misoto22/design'`
|
|
7
|
-
- Version: 0.
|
|
7
|
+
- Version: 0.8.0
|
|
8
8
|
- Docs: https://ui.misoto22.com/components/popover/
|
|
9
9
|
- Related: tooltip, dropdown-menu
|
|
10
10
|
|
|
@@ -12,6 +12,28 @@ A panel anchored to a control, holding content you can interact with.
|
|
|
12
12
|
|
|
13
13
|
Anything with a link, a field or a button in it. A tooltip describes and cannot be entered — put a control inside one and it becomes unreachable.
|
|
14
14
|
|
|
15
|
+
## Anatomy
|
|
16
|
+
|
|
17
|
+
- **Trigger** (required) — PopoverTrigger, a passthrough. Pass asChild to keep your own control; Radix returns focus here when the panel closes on Escape.
|
|
18
|
+
- **Panel** (required) — The anchored dialog: a flat 18rem wide with 1rem of padding, 8px off the trigger, named by label. Focus moves into it on open, but it is not trapped there.
|
|
19
|
+
- **Anchor** — PopoverAnchor, for when the panel should be positioned against something other than the control that opened it — the row an overflow button acts on, a selection in text.
|
|
20
|
+
- **Close** — PopoverClose, and the 32px X that showClose renders in the top-end corner. Off by default, unlike Dialog’s.
|
|
21
|
+
|
|
22
|
+
## Best practices
|
|
23
|
+
|
|
24
|
+
### Do
|
|
25
|
+
|
|
26
|
+
- Make label say what the panel holds rather than echoing the trigger: it is announced on entry, so “Filter options” tells a reader where they have landed where a repeat of the button text tells them nothing new.
|
|
27
|
+
- Use PopoverAnchor when the visual anchor is not the trigger — a toolbar button acting on a selected row — otherwise the panel tracks the button and drifts away from the thing it is editing.
|
|
28
|
+
- Wrap the dismissing control in PopoverClose rather than flipping your own state, so the close runs through Radix and focus goes back to the trigger instead of to the top of the document.
|
|
29
|
+
- Turn showClose on when the panel holds a form. It is off by default, and a non-modal panel whose only exit is clicking away gives an in-progress edit no deliberate end.
|
|
30
|
+
|
|
31
|
+
### Don’t
|
|
32
|
+
|
|
33
|
+
- It is not modal — Radix defaults modal to false and nothing here changes that, so there is no focus trap and no scroll lock: tabbing past the last control inside moves focus into the page, which Radix reads as a focus-outside and closes the panel mid-task.
|
|
34
|
+
- A list of actions belongs in a DropdownMenu. A popover’s contents are ordinary tab stops, so ten actions is ten stops with no type-ahead, where a menu is one stop with arrow keys and a letter jump inside it.
|
|
35
|
+
- The panel sits at --z-dropdown, which resolves to 220 — above a Dialog’s 210, so that a popover opened FROM a dialog is reachable. A popover the page opened and your own state holds open therefore paints over a modal that arrives afterwards; Radix closes it on the interaction outside, and a controlled open that ignores that is the one way to see it.
|
|
36
|
+
|
|
15
37
|
## Accessibility
|
|
16
38
|
|
|
17
39
|
- 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.
|
package/dist/agent/Progress.md
CHANGED
|
@@ -4,14 +4,37 @@ A bar that fills, or sweeps when the end is unknown.
|
|
|
4
4
|
|
|
5
5
|
- Group: Feedback
|
|
6
6
|
- Import: `import { Progress } from '@misoto22/design'`
|
|
7
|
-
- Version: 0.
|
|
7
|
+
- Version: 0.8.0
|
|
8
8
|
- Docs: https://ui.misoto22.com/components/progress/
|
|
9
9
|
- Related: spinner
|
|
10
10
|
|
|
11
|
+
## Anatomy
|
|
12
|
+
|
|
13
|
+
- **Track** (required) — The Radix root: 4px of --stone at the pill radius, carrying role="progressbar" and aria-label from label. It is full width by default, so it takes the measure of whatever column it is dropped into.
|
|
14
|
+
- **Fill** — The indicator, in --accent, sized by width rather than a translate so it grows from the inline start in a right-to-left document too. Present only when value is a number.
|
|
15
|
+
- **Sweep** — What replaces the fill when value is null: a quarter-width --accent bar travelling the track on transform alone, mirrored under rtl so it never reads as progress running backwards. Under prefers-reduced-motion it stops where it is drawn rather than filling the track.
|
|
16
|
+
- **Value row** — label on the left, a tabular-nums percentage on the right, above the track. It renders only when showValue is set and value is a number, which makes it the only place label is ever visible.
|
|
17
|
+
- **Column** — The flex wrapper holding the row and the track. className lands here; every other prop is forwarded to the Radix root instead.
|
|
18
|
+
|
|
19
|
+
## Best practices
|
|
20
|
+
|
|
21
|
+
### Do
|
|
22
|
+
|
|
23
|
+
- Pass showValue on any determinate bar. It is the only thing that puts label on screen — without it the name exists solely as aria-label, and a sighted reader is left with an unlabelled 4px rule and no number.
|
|
24
|
+
- Switch value back to null the moment the estimate stops being real. The fill transitions its width over --duration-slow, so a number that revises downward animates backwards and the reader watches progress undo itself.
|
|
25
|
+
- Set max to the real total rather than converting to a percentage yourself. The width and aria-valuemax come off the same number, so the picture and the announcement cannot drift — but a value past the ceiling still clamps, and an underestimated total parks the bar at full for the rest of the operation rather than admitting the estimate was wrong.
|
|
26
|
+
|
|
27
|
+
### Don’t
|
|
28
|
+
|
|
29
|
+
- Do not pass a max that is not a positive number. Radix refuses it, prints its own warning and falls back to 100, and the width falls back with it — so value={40} paints and announces forty per cent of a ceiling nobody chose.
|
|
30
|
+
- Do not read the resting sweep as a position. Under prefers-reduced-motion it stops at a quarter of the track, which is what a determinate bar at 25% looks like — the announcement is the only thing that tells the two apart, and it is the reason omitting value matters.
|
|
31
|
+
- className styles the column, not the track, so a height utility passed that way stretches the wrapper and leaves the 4px bar exactly where it was.
|
|
32
|
+
|
|
11
33
|
## Accessibility
|
|
12
34
|
|
|
13
35
|
- Omitting value drops aria-valuenow, so a screen reader hears “indeterminate” rather than a number that is a guess.
|
|
14
36
|
- label is required — a bare bar announces nothing.
|
|
37
|
+
- The width is computed from value and max, the same pair Radix announces as aria-valuenow and aria-valuemax, so what is drawn and what is said cannot disagree.
|
|
15
38
|
|
|
16
39
|
## Progress
|
|
17
40
|
|
|
@@ -19,11 +42,12 @@ A bar that fills, or sweeps when the end is unknown. Flat: a track in `--stone`,
|
|
|
19
42
|
|
|
20
43
|
### Props
|
|
21
44
|
|
|
22
|
-
- `value` — `number | null` default `null`. 0
|
|
45
|
+
- `value` — `number | null` default `null`. 0 to `max`, which is 100 unless you say otherwise. Omit (or pass `null`) when the duration is genuinely unknown — the bar then sweeps instead of filling, and Radix drops `aria-valuenow` so a screen reader is told "indeterminate" rather than a number that is a guess.
|
|
46
|
+
- `max` — `number`. What `value` is measured against. 100 by default. The width is computed from it as well as announced from it. It used to be only announced: `max` reached Radix through `...rest` while the width was `value` clamped to 100, so `max={500}` with `value={100}` painted a full bar and told a screen reader "100 of 500". A max that is not a positive number is refused the way Radix refuses it — Radix warns, and both fall back to 100 rather than drawing one picture and announcing another.
|
|
23
47
|
- `label` (required) — `string`. Names what is progressing. Required: a bare bar announces nothing.
|
|
24
48
|
- `showValue` — `boolean` default `false`. Prints the percentage above the bar. Only meaningful when `value` is set.
|
|
25
49
|
|
|
26
|
-
Also accepts: `Omit<ComponentProps<typeof ProgressPrimitive.Root>, 'value'>`.
|
|
50
|
+
Also accepts: `Omit<ComponentProps<typeof ProgressPrimitive.Root>, 'value' | 'max'>`.
|
|
27
51
|
|
|
28
52
|
## Examples
|
|
29
53
|
|
package/dist/agent/RadarChart.md
CHANGED
|
@@ -4,7 +4,7 @@ A profile across several named dimensions.
|
|
|
4
4
|
|
|
5
5
|
- Group: Charts
|
|
6
6
|
- Import: `import { RadarChart } from '@misoto22/design/charts'`
|
|
7
|
-
- Version: 0.
|
|
7
|
+
- Version: 0.8.0
|
|
8
8
|
- Docs: https://ui.misoto22.com/components/radar-chart/
|
|
9
9
|
- Related: line-chart, pie-chart
|
|
10
10
|
|
|
@@ -12,6 +12,28 @@ A profile across several named dimensions.
|
|
|
12
12
|
|
|
13
13
|
Recognising a silhouette. The area a radar encloses depends on the order its spokes happen to be in, so it is the wrong chart for comparing magnitudes.
|
|
14
14
|
|
|
15
|
+
## Anatomy
|
|
16
|
+
|
|
17
|
+
- **Figure frame** (required) — ChartFigure’s <figure>, with the polar plot inside one ChartContainer.
|
|
18
|
+
- **Polygons** (required) — <RadarChart.Radar>. variant="filled" is the default and paints at 2.2 times --chart-fill, because a radar’s fill IS the mark rather than a wash under a line and has to hold its shape where two of them overlap.
|
|
19
|
+
- **Spoke labels** — <RadarChart.PolarAngleAxis>, the names around the perimeter. They are the only thing that says what a corner of the silhouette measures.
|
|
20
|
+
- **Radial scale** — <RadarChart.PolarRadiusAxis>, and it is opt-in. Leave it out and the rings carry no numbers at all: the reader has a shape and no idea what one ring is worth.
|
|
21
|
+
- **Grid** — <RadarChart.PolarGrid>, polygonal rather than circular by default, so the rings line up with the polygon the data draws over them.
|
|
22
|
+
- **Legend** — <RadarChart.Legend>. Two overlapping outlines two steps apart on the grey ramp name nothing, and there is no axis here to name them instead.
|
|
23
|
+
|
|
24
|
+
## Best practices
|
|
25
|
+
|
|
26
|
+
### Do
|
|
27
|
+
|
|
28
|
+
- Fix the spoke ORDER and keep it fixed across every radar on the page. The area a polygon encloses is a function of the order the dimensions happen to sit in, so re-ordering the spokes changes the silhouette without changing one number.
|
|
29
|
+
- Put every dimension on a comparable scale first — a percentile, a score out of ten, an index. One radius serves all the spokes, so a spoke in milliseconds beside one in percent draws a spike that means nothing.
|
|
30
|
+
- Switch to variant="lines" past two series. Filled polygons overlap, and judging areas through two layers of translucency is precisely what this form is worst at.
|
|
31
|
+
|
|
32
|
+
### Don’t
|
|
33
|
+
|
|
34
|
+
- Do not read magnitude off it. A radar is for recognising a silhouette — the same profile before and after — and which of two is bigger is a question a BarChart answers and this one only appears to.
|
|
35
|
+
- Do not skip <RadarChart.PolarRadiusAxis> and call the chart finished. It renders, the rings render, and nothing on screen says whether the outer ring is 100 or 1,000; the sr-only table still has the figures, the sighted reader does not.
|
|
36
|
+
|
|
15
37
|
## Accessibility
|
|
16
38
|
|
|
17
39
|
- title is required; the rows are also rendered as a visually hidden table.
|
|
@@ -31,12 +53,14 @@ A profile across several named dimensions — the shape for "what is this thing
|
|
|
31
53
|
- `children` (required) — `ReactNode`. The composed parts — axes, grid, tooltip, legend, and the marks themselves.
|
|
32
54
|
- `className` — `string`. Merged onto the figure, last, so a call site can size or space it.
|
|
33
55
|
- `chartProps` — `ComponentProps<typeof RechartsRadarChart>`. Escape hatch onto the raw Recharts chart element.
|
|
34
|
-
- `defaultSelectedDataKey` — `string | null` default `null`. The series lit on first render
|
|
56
|
+
- `defaultSelectedDataKey` — `string | null` default `null`. The series lit on first render, when the chart keeps its own selection.
|
|
57
|
+
- `selectedDataKey` — `string | null`. The selected series, driven from outside. Give this and the chart follows it; leave it undefined and the chart keeps its own, starting from `defaultSelectedDataKey`.
|
|
35
58
|
- `onSelectionChange` — `(selectedDataKey: string | null) => void`. Fires when the selection changes, and with null when it is cleared.
|
|
36
59
|
- `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.
|
|
37
60
|
- `loadingPoints` — `number`. How many points the skeleton draws.
|
|
38
61
|
- `angleDataKey` — `keyof TData & string`. The row field naming each spoke. Used by the table view.
|
|
39
62
|
- `hideDataTable` — `boolean` default `false`. Drops the hidden table view. Only correct when the page prints the data itself.
|
|
63
|
+
- `empty` — `ChartEmptyProps | false`. What the chart shows when it has nothing to draw. `false` keeps the empty plot, for a chart whose emptiness is itself the reading.
|
|
40
64
|
|
|
41
65
|
## Types
|
|
42
66
|
|
|
@@ -4,7 +4,7 @@ Values on an arc — a gauge, or a few totals against one scale.
|
|
|
4
4
|
|
|
5
5
|
- Group: Charts
|
|
6
6
|
- Import: `import { RadialChart } from '@misoto22/design/charts'`
|
|
7
|
-
- Version: 0.
|
|
7
|
+
- Version: 0.8.0
|
|
8
8
|
- Docs: https://ui.misoto22.com/components/radial-chart/
|
|
9
9
|
- Related: pie-chart, bar-chart
|
|
10
10
|
|
|
@@ -12,6 +12,27 @@ Values on an arc — a gauge, or a few totals against one scale.
|
|
|
12
12
|
|
|
13
13
|
A single value against a fixed total. Past about four bars a BarChart is the honest choice, because a radial bar’s radius is not its value.
|
|
14
14
|
|
|
15
|
+
## Anatomy
|
|
16
|
+
|
|
17
|
+
- **Figure frame** (required) — ChartFigure’s <figure>, with an empty state at zero rows. Its hidden table needs a value field, which it takes from valueKey or, failing that, from the dataKey of the composed <RadialChart.RadialBar> — so a chart that names neither still has no table.
|
|
18
|
+
- **Arcs** (required) — <RadialChart.RadialBar>, one per row, 14px thick with a 5px cap. variant="semi" drops the centre to 70% so a half arc sits in the middle of its own box rather than at the top of it.
|
|
19
|
+
- **Track** — showTrack, on by default, painting the unfilled remainder behind each arc in --chart-track. It is what makes a gauge a gauge: without it there is no visible whole for the fill to be a part of.
|
|
20
|
+
- **Scale** — The PolarAngleAxis the root inserts when max is set, with domain [0, max] and its ticks off. Leave max unset and the domain is taken from the data instead.
|
|
21
|
+
- **Legend** — <RadialChart.Legend>. An arc has no category axis, so above one bar this is the only thing naming them.
|
|
22
|
+
|
|
23
|
+
## Best practices
|
|
24
|
+
|
|
25
|
+
### Do
|
|
26
|
+
|
|
27
|
+
- Set max on anything that is a gauge. Without it the scale comes from the data, so the largest bar always fills the arc and 62% and 98% are drawn identically.
|
|
28
|
+
- Pass valueKey when the arc is not the only mark. It names the field the hidden table prints and the field the LEGEND reports a selection from; without either it or a composed <RadialChart.RadialBar> there is no value field, and the table is not empty but absent.
|
|
29
|
+
- Use variant="semi" for a single value. A half arc reads as a dial with a floor and a ceiling, where a full ring asks the reader to work out what a whole circle was worth.
|
|
30
|
+
|
|
31
|
+
### Don’t
|
|
32
|
+
|
|
33
|
+
- Do not compare bars across radii. A radial bar’s LENGTH is its value but its RADIUS is not, so an inner arc and an outer arc holding the same number are drawn different lengths — past about four bars a BarChart is the honest form.
|
|
34
|
+
- Do not let a reader take an arc as a share of the ring when max is unset. A full sweep then means the biggest thing here, which is a different sentence from all of it.
|
|
35
|
+
|
|
15
36
|
## Accessibility
|
|
16
37
|
|
|
17
38
|
- title is required; pass valueKey and the rows are also rendered as a visually hidden table.
|
|
@@ -37,11 +58,13 @@ Values on an arc — a gauge, or a small set of totals against one scale. The ca
|
|
|
37
58
|
- `max` — `number`. What a full sweep is worth. Without it the scale comes from the data, so the largest bar always fills the arc — which is right for a comparison and wrong for a gauge. Set it (typically 100) whenever a single value has to read against a fixed total, or "62%" and "98%" will look identical.
|
|
38
59
|
- `innerRadius` — `number | string` default `'30%'`. Where the arc starts, from the centre.
|
|
39
60
|
- `outerRadius` — `number | string` default `'100%'`. Where the arc ends.
|
|
40
|
-
- `defaultSelectedBar` — `string | null` default `null`. The bar lit on first render.
|
|
61
|
+
- `defaultSelectedBar` — `string | null` default `null`. The bar lit on first render, when the chart keeps its own selection.
|
|
62
|
+
- `selectedBar` — `string | null`. The selected bar, driven from outside. Give this and the chart follows it; leave it undefined and the chart keeps its own, starting from `defaultSelectedBar`.
|
|
41
63
|
- `onSelectionChange` — `(selection: { name: string; value: number } | null) => void`. Fires when the selection changes, and with null when it is cleared.
|
|
42
64
|
- `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.
|
|
43
|
-
- `valueKey` — `keyof TData & string`. The row field holding each bar's number
|
|
65
|
+
- `valueKey` — `keyof TData & string`. The row field holding each bar's number, for the table view and for the selection the legend reports. Falls back to the `dataKey` of the composed `<RadialChart.RadialBar>`, so the usual call site needs neither.
|
|
44
66
|
- `hideDataTable` — `boolean` default `false`. Drops the hidden table view. Only correct when the page prints the data itself.
|
|
67
|
+
- `empty` — `ChartEmptyProps | false`. What the chart shows when it has nothing to draw. `false` keeps the empty plot, for a chart whose emptiness is itself the reading.
|
|
45
68
|
|
|
46
69
|
## Types
|
|
47
70
|
|