@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,73 @@
|
|
|
1
|
+
# Skeleton
|
|
2
|
+
|
|
3
|
+
The shape of the page, before the page.
|
|
4
|
+
|
|
5
|
+
- Group: Feedback
|
|
6
|
+
- Import: `import { Skeleton } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/skeleton/
|
|
9
|
+
- Related: spinner, empty-state
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
A wait the reader would otherwise think was a broken page. A shape that describes what is coming beats a dot that describes nothing.
|
|
14
|
+
|
|
15
|
+
## Accessibility
|
|
16
|
+
|
|
17
|
+
- One live region on the wrapper; every shape inside it is aria-hidden.
|
|
18
|
+
- One pulse on the wrapper, not one per bar, so the page breathes together.
|
|
19
|
+
|
|
20
|
+
## Skeleton
|
|
21
|
+
|
|
22
|
+
The fill every skeleton part is drawn from: `--stone`, and nothing else. Deliberately NOT a shimmer. A shimmer sweeps a highlight across the shape, which implies a light source; the White Reset has none, so the sweep reads as a bug rather than as loading. The whole page breathes together instead — see `SkeletonPage`, which owns the single pulse.
|
|
23
|
+
|
|
24
|
+
Also accepts: `HTMLAttributes<HTMLDivElement>`.
|
|
25
|
+
|
|
26
|
+
## SkeletonLine
|
|
27
|
+
|
|
28
|
+
A line of type. Height is the line's; width is how far it runs.
|
|
29
|
+
|
|
30
|
+
Also accepts: `HTMLAttributes<HTMLDivElement>`.
|
|
31
|
+
|
|
32
|
+
## SkeletonBlock
|
|
33
|
+
|
|
34
|
+
A block: an image mount, a plate, a chart.
|
|
35
|
+
|
|
36
|
+
Also accepts: `HTMLAttributes<HTMLDivElement>`.
|
|
37
|
+
|
|
38
|
+
## SkeletonCircle
|
|
39
|
+
|
|
40
|
+
A circle: an avatar, a marker.
|
|
41
|
+
|
|
42
|
+
Also accepts: `HTMLAttributes<HTMLDivElement>`.
|
|
43
|
+
|
|
44
|
+
## SkeletonText
|
|
45
|
+
|
|
46
|
+
A paragraph. The last line is short, because real prose ends mid-measure. A block of equal full-width bars reads as a table, and the reader then flinches when a paragraph arrives instead.
|
|
47
|
+
|
|
48
|
+
### Props
|
|
49
|
+
|
|
50
|
+
- `lines` — `number` default `3`. How many lines of prose to stand in for.
|
|
51
|
+
|
|
52
|
+
Also accepts: `HTMLAttributes<HTMLDivElement>`.
|
|
53
|
+
|
|
54
|
+
## SkeletonPage
|
|
55
|
+
|
|
56
|
+
The frame a skeleton sits in: the live region, and the single pulse. One `animate-pulse` on the wrapper rather than one per part, so the page breathes together instead of shimmering out of phase — twenty independently animated bars is a visual noise floor, not a loading state. A skeleton whose shape does not match what replaces it is worse than none: it promises a layout and then the page jumps out from under the reader. Compose the parts to match the real thing, and change both together.
|
|
57
|
+
|
|
58
|
+
### Props
|
|
59
|
+
|
|
60
|
+
- `label` (required) — `string`. What is loading, in words. Announced once; the shapes themselves are `aria-hidden`, so this sentence is the entire experience for a screen reader and "Loading" alone tells it nothing.
|
|
61
|
+
- `children` (required) — `ReactNode`.
|
|
62
|
+
|
|
63
|
+
Also accepts: `HTMLAttributes<HTMLDivElement>`.
|
|
64
|
+
|
|
65
|
+
## Examples
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
<Skeleton className="h-3 w-40 rounded-(--radius-pill)" />
|
|
69
|
+
<SkeletonPage label="Loading projects">
|
|
70
|
+
<SkeletonLine className="h-2.5 w-28" />
|
|
71
|
+
<SkeletonBlock className="mt-6 h-40" />
|
|
72
|
+
</SkeletonPage>
|
|
73
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Slider
|
|
2
|
+
|
|
3
|
+
A value chosen along a range.
|
|
4
|
+
|
|
5
|
+
- Group: Forms
|
|
6
|
+
- Import: `import { Slider } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/slider/
|
|
9
|
+
- Related: progress
|
|
10
|
+
|
|
11
|
+
## Accessibility
|
|
12
|
+
|
|
13
|
+
- label is required. A thumb that announces "42" and nothing else leaves a screen reader user with a number and no idea what it measures.
|
|
14
|
+
- A 44px hit area sits invisibly around the 16px thumb.
|
|
15
|
+
- Arrows step, Page keys jump, Home and End reach the ends.
|
|
16
|
+
|
|
17
|
+
## Keyboard
|
|
18
|
+
|
|
19
|
+
- ← / → — Moves by one step.
|
|
20
|
+
- Page Up / Page Down — Moves by a larger step.
|
|
21
|
+
- Home / End — Jumps to the minimum or maximum.
|
|
22
|
+
|
|
23
|
+
## Slider
|
|
24
|
+
|
|
25
|
+
A value chosen along a range. Radix owns the keyboard contract — arrows step, Page keys jump, Home and End reach the ends — and the ARIA that reports the value. What is here is the look, and the labelling, which is the part a slider most often gets wrong: a thumb that announces "42" and nothing else leaves a screen reader user with a number and no idea what it measures. A 44px hit area sits invisibly around the 16px thumb, because a thumb sized for the design is well under any pointer-target guideline.
|
|
26
|
+
|
|
27
|
+
### Props
|
|
28
|
+
|
|
29
|
+
- `label` (required) — `string | [string, string]`. Names the control. Required: a slider with no name announces only a number, and a number with no noun is not information. A range slider (two thumbs) needs one name per thumb — pass an array.
|
|
30
|
+
- `showValue` — `boolean` default `false`. Prints the current value beside the label.
|
|
31
|
+
- `format` — `(value: number) => string` default `String`. Renders the value with a unit or a currency, e.g. `(n) => n + '%'`.
|
|
32
|
+
|
|
33
|
+
Also accepts: `ComponentProps<typeof SliderPrimitive.Root>`.
|
|
34
|
+
|
|
35
|
+
## Examples
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
<Slider label="Quality" defaultValue={[80]} max={100} step={5} showValue format={(n) => `${n}%`} />
|
|
39
|
+
```
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Sparkline
|
|
2
|
+
|
|
3
|
+
A run of numbers at the size of a word.
|
|
4
|
+
|
|
5
|
+
- Group: Data
|
|
6
|
+
- Import: `import { Sparkline } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/sparkline/
|
|
9
|
+
- Related: line-chart, table
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
In a table cell, beside a figure, at the end of a row. When the trend needs reading precisely it wants a LineChart and its own space.
|
|
14
|
+
|
|
15
|
+
## Accessibility
|
|
16
|
+
|
|
17
|
+
- label is required and is the whole accessible name: a sparkline has no axes and no legend, so nothing else describes it.
|
|
18
|
+
- Axis-less by design. Every piece of chrome that would let it answer “what value exactly” also makes it too big to sit inline, which was the only reason to reach for it.
|
|
19
|
+
- Pin domain for a column of them: on independent domains every row peaks and troughs identically, which is how a table of sparklines becomes actively misleading.
|
|
20
|
+
- One path, no rendering engine — so a hundred of them in a table cost nothing.
|
|
21
|
+
|
|
22
|
+
## Sparkline
|
|
23
|
+
|
|
24
|
+
A run of numbers at the size of a word — in a table cell, beside a figure, at the end of a row. Deliberately axis-less, gridless and label-less: a sparkline answers "what shape has this been", and every piece of chrome that would make it answer "what value exactly" also makes it too big to sit inline, which was the only reason to reach for it. When the exact value matters, print the number beside it — `value` does — and when the trend needs reading precisely, it wants a `<LineChart>` and its own space. No rendering engine: it is one `<path>` over a normalised viewBox, so it costs nothing to put a hundred of them in a table.
|
|
25
|
+
|
|
26
|
+
### Props
|
|
27
|
+
|
|
28
|
+
- `data` (required) — `number[]`. The numbers, in order. Anything shorter than two points draws nothing.
|
|
29
|
+
- `label` (required) — `string`. What the run is, in a sentence. Required, and it is the whole accessible name: a sparkline has no axes and no legend, so nothing else describes it.
|
|
30
|
+
- `variant` — `SparklineVariant` default `'line'`.
|
|
31
|
+
- `height` — `number` default `28`. Height in pixels. The width comes from the container.
|
|
32
|
+
- `domain` — `[number, number]`. The domain, as `[min, max]`. Derived from the data when omitted. Pin it whenever a column of sparklines is meant to be compared: on independent domains every row peaks and troughs identically, which is the one way a table of sparklines can be actively misleading.
|
|
33
|
+
- `showLast` — `boolean` default `true`. Marks the last point, which is usually the one being asked about.
|
|
34
|
+
- `value` — `ReactNode`. The value announced alongside the label — the current reading, formatted. Falls back to the last number.
|
|
35
|
+
- `className` — `string`.
|
|
36
|
+
|
|
37
|
+
## Types
|
|
38
|
+
|
|
39
|
+
- `SparklineVariant` = `'line' | 'area' | 'bars'`
|
|
40
|
+
|
|
41
|
+
## Examples
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
<Sparkline label="Weekly signups" data={[12, 18, 9, 24, 30, 22, 41]} value="41" />
|
|
45
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Spinner
|
|
2
|
+
|
|
3
|
+
The one “working” indicator — a ring, never a shimmer.
|
|
4
|
+
|
|
5
|
+
- Group: Feedback
|
|
6
|
+
- Import: `import { Spinner } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/spinner/
|
|
9
|
+
- Related: skeleton, progress
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
A wait short enough that the shape of what is coming does not matter. Longer than that, use a Skeleton.
|
|
14
|
+
|
|
15
|
+
## Accessibility
|
|
16
|
+
|
|
17
|
+
- label names the specific thing being waited on; three spinners all saying “Loading” tell a screen reader nothing.
|
|
18
|
+
- label={null} silences it for use inside a control that already announces the operation.
|
|
19
|
+
- Spins under motion-safe only; the static ring still reads as unfinished because the leading quarter is darker.
|
|
20
|
+
|
|
21
|
+
## Spinner
|
|
22
|
+
|
|
23
|
+
The system's one "working" indicator. A ring, not a blurred glow and not a shimmer: the White Reset has no light source, so depth and softness are not available to it. The leading quarter is the only thing that distinguishes the ring from a plain circle, which is why the track stays a hairline — a spinner is a hint that time is passing, not a feature of the page. It spins under `motion-safe` only. A reader who has asked for less motion gets a static ring, which still reads as "not finished" because the leading quarter is darker than the track. For a wait long enough that the reader would otherwise wonder whether the page is broken, prefer `Skeleton` — a shape that describes what is coming beats a dot that describes nothing.
|
|
24
|
+
|
|
25
|
+
### Props
|
|
26
|
+
|
|
27
|
+
- `size` — `'sm' | 'md' | 'lg'` default `'md'`. 14px / 18px / 26px. Match the size of the type it sits beside.
|
|
28
|
+
- `tone` — `'default' | 'current'` default `'default'`. `default` draws the ring against the page — a hairline track in the rule colour with the leading quarter in ink. `current` draws it in the inherited text colour, which is what a spinner inside a filled button needs: on an ink ground an ink ring is invisible.
|
|
29
|
+
- `label` — `string | null` default `'Loading'`. Announced to assistive tech. Pass the specific thing being waited on ("Loading projects"), not the generic word — a screen reader user hearing "Loading" three times cannot tell which three things. Pass `null` for a spinner that sits inside a control which already names the operation (a button whose own label changes to "Saving…"), so the two are not read out twice.
|
|
30
|
+
|
|
31
|
+
Also accepts: `HTMLAttributes<HTMLSpanElement>`.
|
|
32
|
+
|
|
33
|
+
## Examples
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
<Spinner size="lg" label="Loading projects" />
|
|
37
|
+
// Inside a filled button, where the ground is ink:
|
|
38
|
+
<Spinner size="sm" tone="current" label={null} />
|
|
39
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# StatusDot
|
|
2
|
+
|
|
3
|
+
The dot beside a status word.
|
|
4
|
+
|
|
5
|
+
- Group: Display
|
|
6
|
+
- Import: `import { StatusDot } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/status-dot/
|
|
9
|
+
- Related: status-pill
|
|
10
|
+
|
|
11
|
+
## Accessibility
|
|
12
|
+
|
|
13
|
+
- aria-hidden without exception: it repeats a state the adjacent label already names.
|
|
14
|
+
- The halo is motion-safe, so a reader who asked for less motion gets a still dot.
|
|
15
|
+
|
|
16
|
+
## StatusDot
|
|
17
|
+
|
|
18
|
+
The dot beside a status word. `aria-hidden` without exception: the dot repeats a state the adjacent label already names, and a screen reader announcing "available" twice is worse than not announcing the decoration at all. If a call site has no visible label, the fix is a label, not an `aria-label` on the dot. The halo is a separate absolutely-positioned ring rather than a box-shadow, because Law 2 of this system is that a shadow is never blurred — and it is motion-safe, so a reader who asked for less motion gets a static dot.
|
|
19
|
+
|
|
20
|
+
### Props
|
|
21
|
+
|
|
22
|
+
- `size` — `'sm' | 'md'` default `'md'`. 7px / 8px. `md` is the default.
|
|
23
|
+
- `tone` — `StatusTone` default `'success'`.
|
|
24
|
+
- `pulse` — `boolean` default `true`. A halo that grows and dissolves, for "live right now". Off for a settled state.
|
|
25
|
+
|
|
26
|
+
Also accepts: `HTMLAttributes<HTMLSpanElement>`.
|
|
27
|
+
|
|
28
|
+
## Types
|
|
29
|
+
|
|
30
|
+
- `StatusTone` = `'success' | 'warning' | 'danger' | 'neutral'`
|
|
31
|
+
|
|
32
|
+
## Examples
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
<span className="inline-flex items-center gap-2"><StatusDot /> Available</span>
|
|
36
|
+
```
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# StatusPill
|
|
2
|
+
|
|
3
|
+
A live state, named: a dot plus an uppercase mono label.
|
|
4
|
+
|
|
5
|
+
- Group: Display
|
|
6
|
+
- Import: `import { StatusPill } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/status-pill/
|
|
9
|
+
- Related: status-dot, badge
|
|
10
|
+
|
|
11
|
+
## StatusPill
|
|
12
|
+
|
|
13
|
+
A live state, named: a dot plus an uppercase mono label in an outlined pill. One component rather than a dot and a pill assembled per call site, which is how the same "available for work" chip ended up with three different dot sizes and two different pulse timings on one site.
|
|
14
|
+
|
|
15
|
+
### Props
|
|
16
|
+
|
|
17
|
+
- `children` (required) — `ReactNode`.
|
|
18
|
+
- `tone` — `StatusTone` default `'success'`.
|
|
19
|
+
- `pulse` — `boolean` default `true`. Pulsing live dot (default) vs a settled one.
|
|
20
|
+
|
|
21
|
+
Also accepts: `HTMLAttributes<HTMLSpanElement>`.
|
|
22
|
+
|
|
23
|
+
## Examples
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
<StatusPill>Available for work</StatusPill>
|
|
27
|
+
<StatusPill tone="warning" pulse={false}>Degraded</StatusPill>
|
|
28
|
+
```
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Steps
|
|
2
|
+
|
|
3
|
+
A numbered sequence, as a rail — one thing after another, with a rule through them.
|
|
4
|
+
|
|
5
|
+
- Group: Display
|
|
6
|
+
- Import: `import { Steps } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/steps/
|
|
9
|
+
- Related: diagram, article
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
A pipeline, a migration, a recipe: an order with no branches. The moment something forks or points at something else it is a Diagram, and drawing a fork as a list hides it.
|
|
14
|
+
|
|
15
|
+
## Accessibility
|
|
16
|
+
|
|
17
|
+
- An <ol>, because the order IS the content — a stack of divs says nothing about sequence.
|
|
18
|
+
- aria-current="step" marks the filled one, which is the only thing here a reader could not infer from the reading order.
|
|
19
|
+
- The markers and the connector are aria-hidden: the number is the list position, and screen readers already announce that.
|
|
20
|
+
|
|
21
|
+
## Steps
|
|
22
|
+
|
|
23
|
+
A numbered sequence, as a rail. The shape a pipeline actually has: one thing after another, each with a name and a line of detail, and a rule running through them so the eye reads them as one process rather than as five unrelated rows. It is the figure a technical post reaches for most often after a diagram, and it is NOT a diagram — nothing branches, nothing points at anything, and drawing it with boxes and arrows says otherwise. The connector is drawn on the ITEM rather than as a full-height line behind the markers, so it starts under one and stops above the next instead of running through both — and so the last step has no tail hanging off it. That is the detail that separates a rail from a list with a border on it. An `<ol>`, because the order is the content. `aria-current="step"` marks the filled one, which is the only thing here a screen reader could not otherwise infer from the order it is read in.
|
|
24
|
+
|
|
25
|
+
### Props
|
|
26
|
+
|
|
27
|
+
- `steps` (required) — `Step[]`.
|
|
28
|
+
- `label` — `string`. Names the sequence for assistive tech when no heading does.
|
|
29
|
+
- `marker` — `'number' | 'rule'` default `'number'`. How the marker is drawn. `number` counts from one and is right for a pipeline, a recipe, a migration. `rule` drops the digit for a plain hairline node, which is what a sequence of states wants — "queued, running, done" is an order, not a numbered list.
|
|
30
|
+
|
|
31
|
+
Also accepts: `Omit<HTMLAttributes<HTMLOListElement>, 'children'>`.
|
|
32
|
+
|
|
33
|
+
## Examples
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
<Steps
|
|
37
|
+
label="How an answer is built"
|
|
38
|
+
steps={[
|
|
39
|
+
{ title: 'Corpus', note: 'Blog MDX · project database' },
|
|
40
|
+
{ title: 'Chunking', note: 'By heading · 300–800 tokens' },
|
|
41
|
+
{ title: 'Answer', note: 'Live citation panel', current: true },
|
|
42
|
+
]}
|
|
43
|
+
/>
|
|
44
|
+
```
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Switch
|
|
2
|
+
|
|
3
|
+
A setting that takes effect immediately.
|
|
4
|
+
|
|
5
|
+
- Group: Forms
|
|
6
|
+
- Import: `import { Switch } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/switch/
|
|
9
|
+
- Related: checkbox
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
Inside a form with a Save button, a switch is a lie about when the change happened. Use a Checkbox.
|
|
14
|
+
|
|
15
|
+
## Keyboard
|
|
16
|
+
|
|
17
|
+
- Space / Enter — Toggles it, and the change applies immediately.
|
|
18
|
+
|
|
19
|
+
## Switch
|
|
20
|
+
|
|
21
|
+
A setting that takes effect immediately. Distinct from `Checkbox`, and the distinction is not cosmetic: a switch applies on flip, a checkbox applies on submit. A switch inside a form with a Save button is a lie about when the change happened. The track fills with ink when on and the thumb is paper with a hairline — rather than a white thumb floating on a drop shadow, which this system does not have. The off state is a filled rule-coloured track, so the control still reads as a control on a white page.
|
|
22
|
+
|
|
23
|
+
Also accepts: `ComponentProps<typeof SwitchPrimitive.Root>`.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
<Field label="Email notifications"><Switch defaultChecked /></Field>
|
|
29
|
+
```
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Table
|
|
2
|
+
|
|
3
|
+
A ruled data table — alignment, sorting and rules all per column.
|
|
4
|
+
|
|
5
|
+
- Group: Data
|
|
6
|
+
- Import: `import { Table } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/table/
|
|
9
|
+
- Related: card, figure-band
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
Alignment is per column and numbers belong at the end edge, so digits line up. Sorting is opt-in per column: a table where every header is a button invites sorting a column the data cannot be ordered by.
|
|
14
|
+
|
|
15
|
+
## Accessibility
|
|
16
|
+
|
|
17
|
+
- caption is required: an unnamed table on a page with three tables is unnavigable.
|
|
18
|
+
- Column labels are <th scope="col">, so a cell can be traced back to its heading.
|
|
19
|
+
- A sortable header is a button INSIDE the th, not a click handler on the cell — a cell with an onClick is not focusable and not announced, so the sort would exist only for a mouse.
|
|
20
|
+
- aria-sort is set from sortDirection, which is the only way a screen reader learns the table is ordered at all.
|
|
21
|
+
- No zebra striping at any border setting: in a monochrome system a striped row is a second surface competing with the page ground.
|
|
22
|
+
|
|
23
|
+
## Keyboard
|
|
24
|
+
|
|
25
|
+
- Tab — Reaches the scroll region, and each sortable column header.
|
|
26
|
+
- ← / → — Scrolls the table sideways once the region has focus.
|
|
27
|
+
|
|
28
|
+
## Table
|
|
29
|
+
|
|
30
|
+
A ruled data table. Wrapped in its own horizontally scrolling container, because a table is the one block that legitimately exceeds the measure — and a page that scrolls sideways as a whole is a layout bug, while a table that does is a table. That container is focusable, and it has to be. A scrollable region whose contents are not themselves focusable is unreachable by keyboard: there is no element to Tab to and therefore no way to press an arrow key at it, so the columns past the fold simply do not exist for anyone not using a mouse. No zebra striping at any border setting. In a monochrome system a striped row is a second surface competing with the page ground, and the hairline between rows is already enough to track a line across.
|
|
31
|
+
|
|
32
|
+
### Props
|
|
33
|
+
|
|
34
|
+
- `caption` (required) — `string`. Describes the table for a screen reader, which cannot see the heading above it. Rendered as a visually-hidden `<caption>` — required, because an unnamed table in a page with three tables is unnavigable.
|
|
35
|
+
- `showCaption` — `boolean` default `false`. Prints the caption instead of hiding it.
|
|
36
|
+
- `stickyHeader` — `boolean` default `false`. Pins the header row while the body scrolls. Needs a bounded height on the container — otherwise the page scrolls, not the table, and nothing sticks.
|
|
37
|
+
- `borders` — `TableBorders` default `'rows'`. Which rules to draw. See .
|
|
38
|
+
- `density` — `'comfortable' | 'compact'` default `'comfortable'`. Tightens the row padding, for a table that is mostly numbers.
|
|
39
|
+
|
|
40
|
+
Also accepts: `TableHTMLAttributes<HTMLTableElement>`.
|
|
41
|
+
|
|
42
|
+
## THead
|
|
43
|
+
|
|
44
|
+
Header group. The rule under it is drawn by the table's border setting.
|
|
45
|
+
|
|
46
|
+
## TBody
|
|
47
|
+
|
|
48
|
+
## TR
|
|
49
|
+
|
|
50
|
+
## TH
|
|
51
|
+
|
|
52
|
+
A column label. Mono and uppercase, so it never reads as data. When sortable, the label becomes a `<button>` INSIDE the `<th>` rather than the `<th>` becoming clickable: a cell with a click handler is not focusable and not announced as a control, so the sort exists only for a mouse. Sorting is per column and opt-in. A table where every header is a button invites the reader to try sorting a column the data cannot be ordered by.
|
|
53
|
+
|
|
54
|
+
### Props
|
|
55
|
+
|
|
56
|
+
- `align` — `TableAlign` default `'start'`. Which edge the column's contents sit against. Numbers belong at `end`.
|
|
57
|
+
- `sortable` — `boolean` default `false`. Makes the label a button and shows the sort marker.
|
|
58
|
+
- `sortDirection` — `SortDirection` default `'none'`. Which way this column is sorted. Also set as `aria-sort`, which is the only way a screen reader learns a table is ordered at all — a caret drawn in the header tells it nothing.
|
|
59
|
+
- `onSort` — `() => void`.
|
|
60
|
+
|
|
61
|
+
Also accepts: `Omit<ThHTMLAttributes<HTMLTableCellElement>, 'align'>`.
|
|
62
|
+
|
|
63
|
+
## TD
|
|
64
|
+
|
|
65
|
+
### Props
|
|
66
|
+
|
|
67
|
+
- `align` — `TableAlign` default `'start'`. Which edge the cell's contents sit against. Match the column's header.
|
|
68
|
+
|
|
69
|
+
Also accepts: `Omit<TdHTMLAttributes<HTMLTableCellElement>, 'align'>`.
|
|
70
|
+
|
|
71
|
+
## Types
|
|
72
|
+
|
|
73
|
+
- `TableAlign` = `'start' | 'center' | 'end'`
|
|
74
|
+
- `TableBorders` = `'rows' | 'grid' | 'bordered' | 'bordered-grid' | 'none'`
|
|
75
|
+
- `SortDirection` = `'ascending' | 'descending' | 'none'`
|
|
76
|
+
|
|
77
|
+
## Examples
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
<Table caption="Deploy history">
|
|
81
|
+
<THead><TR><TH>Commit</TH><TH align="end" sortable sortDirection={dir} onSort={sort}>Duration</TH></TR></THead>
|
|
82
|
+
<TBody><TR><TD>a1b2c3d</TD><TD align="end">2m 14s</TD></TR></TBody>
|
|
83
|
+
</Table>
|
|
84
|
+
<Table caption="Inventory" borders="bordered-grid" density="compact">…</Table>
|
|
85
|
+
```
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Tabs
|
|
2
|
+
|
|
3
|
+
One strip, several panels.
|
|
4
|
+
|
|
5
|
+
- Group: Navigation
|
|
6
|
+
- Import: `import { Tabs } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/tabs/
|
|
9
|
+
- Related: accordion
|
|
10
|
+
|
|
11
|
+
## Accessibility
|
|
12
|
+
|
|
13
|
+
- The strip scrolls rather than wrapping: a wrapped second row moves every tab below it and the reader loses the one they were about to click.
|
|
14
|
+
- 44px tall, because a tab is a pointer target like any other.
|
|
15
|
+
|
|
16
|
+
## Keyboard
|
|
17
|
+
|
|
18
|
+
- Tab — Moves into the strip, and out of it — the whole strip is one stop.
|
|
19
|
+
- ← / → — Moves between tabs and switches the panel with them.
|
|
20
|
+
- Home / End — Jumps to the first or last tab.
|
|
21
|
+
|
|
22
|
+
## Tabs
|
|
23
|
+
|
|
24
|
+
Radix Tabs root, re-exported as a typed passthrough.
|
|
25
|
+
|
|
26
|
+
## TabsList
|
|
27
|
+
|
|
28
|
+
The tab strip. Scrolls horizontally rather than wrapping. A wrapped second row of tabs moves every tab below it when the strip grows, and the reader loses the one they were about to click.
|
|
29
|
+
|
|
30
|
+
## TabsTrigger
|
|
31
|
+
|
|
32
|
+
One tab. The active marker is a 2px ink rule pulled onto the strip's own border with `-mb-px`, so the two occupy the same line instead of stacking into a 3px edge. 44px tall, because a tab is a pointer target like any other.
|
|
33
|
+
|
|
34
|
+
## TabsContent
|
|
35
|
+
|
|
36
|
+
The panel paired to a by matching `value`.
|
|
37
|
+
|
|
38
|
+
## Examples
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
<Tabs defaultValue="preview">
|
|
42
|
+
<TabsList>
|
|
43
|
+
<TabsTrigger value="preview">Preview</TabsTrigger>
|
|
44
|
+
<TabsTrigger value="code">Code</TabsTrigger>
|
|
45
|
+
</TabsList>
|
|
46
|
+
<TabsContent value="preview">…</TabsContent>
|
|
47
|
+
</Tabs>
|
|
48
|
+
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Tag
|
|
2
|
+
|
|
3
|
+
A subject label — a topic, a technology, a filter facet.
|
|
4
|
+
|
|
5
|
+
- Group: Display
|
|
6
|
+
- Import: `import { Tag } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/tag/
|
|
9
|
+
- Related: badge
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
Several sit together and the reader scans them. One fact about one record is a Badge.
|
|
14
|
+
|
|
15
|
+
## Accessibility
|
|
16
|
+
|
|
17
|
+
- Presentational. To filter with it, wrap it in a button and pass active, so the focus ring and the pressed state stay with the element that owns them.
|
|
18
|
+
|
|
19
|
+
## Tag
|
|
20
|
+
|
|
21
|
+
A subject label — a topic, a technology, a filter facet. Distinct from `Badge`, which carries a state or a count. A tag names what something is ABOUT, so several sit together in a row and the reader scans them; a badge is one fact about one record. Presentational on purpose. To make a tag filter a list, wrap it in a button or a link at the call site and pass `active` — that keeps the focus ring, the pressed state and the keyboard handling with the element that actually owns them.
|
|
22
|
+
|
|
23
|
+
### Props
|
|
24
|
+
|
|
25
|
+
- `children` (required) — `ReactNode`.
|
|
26
|
+
- `active` — `boolean` default `false`. Renders the pressed/selected look. Pair with `aria-pressed` on a wrapper button.
|
|
27
|
+
|
|
28
|
+
Also accepts: `HTMLAttributes<HTMLSpanElement>`.
|
|
29
|
+
|
|
30
|
+
## Examples
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
<Tag>TypeScript</Tag>
|
|
34
|
+
<button type="button" aria-pressed={on} onClick={toggle}><Tag active={on}>Rust</Tag></button>
|
|
35
|
+
```
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Textarea
|
|
2
|
+
|
|
3
|
+
Multi-line text entry, resizable vertically only.
|
|
4
|
+
|
|
5
|
+
- Group: Forms
|
|
6
|
+
- Import: `import { Textarea } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/textarea/
|
|
9
|
+
- Related: input, field
|
|
10
|
+
|
|
11
|
+
## Textarea
|
|
12
|
+
|
|
13
|
+
Multi-line text entry. Resizes vertically only: horizontal resize lets a reader drag the control past the measure and past the page's own gutter.
|
|
14
|
+
|
|
15
|
+
### Props
|
|
16
|
+
|
|
17
|
+
- `invalid` — `boolean`. Paints the resting border with `--danger` and reflects `aria-invalid`.
|
|
18
|
+
- `ref` — `Ref<HTMLTextAreaElement>`.
|
|
19
|
+
|
|
20
|
+
Also accepts: `TextareaHTMLAttributes<HTMLTextAreaElement>`.
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
<Field label="Notes" htmlFor="notes"><Textarea id="notes" rows={4} /></Field>
|
|
26
|
+
```
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Toast
|
|
2
|
+
|
|
3
|
+
A transient confirmation, mounted once near the app root.
|
|
4
|
+
|
|
5
|
+
- Group: Feedback
|
|
6
|
+
- Import: `import { Toast } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/toast/
|
|
9
|
+
- Related: alert
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
Something succeeded and needs no response. A toast is dismissed by time, and time is not an acknowledgement.
|
|
14
|
+
|
|
15
|
+
## Toaster
|
|
16
|
+
|
|
17
|
+
Transient confirmations, mounted once near the app root. A toast is for something that succeeded and needs no response. Anything the reader must act on belongs in the page — a toast is dismissed by time, and time is not an acknowledgement. `richColors` stays off by default: sonner's rich palette is not this system's status scale, and turning it on reintroduces chroma the White Reset spends only on state.
|
|
18
|
+
|
|
19
|
+
## Examples
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
// app root
|
|
23
|
+
<Toaster />
|
|
24
|
+
// anywhere
|
|
25
|
+
toast.success('Saved')
|
|
26
|
+
```
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# ToggleGroup
|
|
2
|
+
|
|
3
|
+
A segmented control: several options, one strip.
|
|
4
|
+
|
|
5
|
+
- Group: Forms
|
|
6
|
+
- Import: `import { ToggleGroup } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/toggle-group/
|
|
9
|
+
- Related: tabs, radio-group
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
It changes a VALUE. Something that switches panels is Tabs.
|
|
14
|
+
|
|
15
|
+
## Accessibility
|
|
16
|
+
|
|
17
|
+
- type="single" gets radio semantics; type="multiple" gets independent toggles. Choosing wrong tells a screen reader that picking one option unpicks the others.
|
|
18
|
+
|
|
19
|
+
## Keyboard
|
|
20
|
+
|
|
21
|
+
- Tab — Moves into the strip — one stop for the group.
|
|
22
|
+
- ← / → — Moves between segments.
|
|
23
|
+
- Enter / Space — Toggles the focused segment.
|
|
24
|
+
|
|
25
|
+
## ToggleGroup
|
|
26
|
+
|
|
27
|
+
A segmented control: several options, one strip. `type="single"` is a choice — Radix gives it radio semantics, and it is the right shape for a view switcher or a density setting. `type="multiple"` is a set of independent toggles, which is a different thing announced differently; choosing the wrong one is how a "filter by tag" control ends up telling a screen reader that picking one tag unpicks the others. The two look different on purpose. A single-value strip moves ONE filled pill between its options, so the eye follows a thing travelling; a multiple-value strip fills each pressed option separately, because there is no single selection to travel. Two people looking at a screenshot should be able to tell which kind they are looking at, and before this they could not. Distinct from `Tabs`, which switches PANELS and owns a tabpanel relationship. A toggle group changes a value.
|
|
28
|
+
|
|
29
|
+
Also accepts: `ComponentProps<typeof ToggleGroupPrimitive.Root>`.
|
|
30
|
+
|
|
31
|
+
## ToggleGroupItem
|
|
32
|
+
|
|
33
|
+
One segment. In a single-value group the item draws no background of its own — the travelling pill behind it does — so it only changes ink. In a multiple-value group it fills, because there is nothing travelling.
|
|
34
|
+
|
|
35
|
+
Also accepts: `ComponentProps<typeof ToggleGroupPrimitive.Item>`.
|
|
36
|
+
|
|
37
|
+
## Examples
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
<ToggleGroup type="single" defaultValue="grid" aria-label="Layout">
|
|
41
|
+
<ToggleGroupItem value="grid">Grid</ToggleGroupItem>
|
|
42
|
+
<ToggleGroupItem value="list">List</ToggleGroupItem>
|
|
43
|
+
</ToggleGroup>
|
|
44
|
+
```
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Tooltip
|
|
2
|
+
|
|
3
|
+
A short label on hover and on focus.
|
|
4
|
+
|
|
5
|
+
- Group: Overlays
|
|
6
|
+
- Import: `import { Tooltip } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.6.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/tooltip/
|
|
9
|
+
- Related: dialog
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
Never for anything the reader NEEDS: a tooltip is unreachable on touch and invisible while scanning.
|
|
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
|
+
- The trigger is asChild, so the child must be focusable — a div trigger simply has no keyboard tooltip, which this API shape makes obvious rather than silent.
|
|
19
|
+
- Not an accessible name. An icon-only button still needs its own aria-label.
|
|
20
|
+
|
|
21
|
+
## Keyboard
|
|
22
|
+
|
|
23
|
+
- Tab — Shows the tip — focus reveals it, not only hover.
|
|
24
|
+
- Escape — Dismisses it.
|
|
25
|
+
|
|
26
|
+
## TooltipProvider
|
|
27
|
+
|
|
28
|
+
Wrap the app — or the smallest subtree that has tooltips — once. Radix needs it to share the open/close timing between neighbouring triggers, which is what stops a row of icon buttons flashing a tooltip per hover.
|
|
29
|
+
|
|
30
|
+
## Tooltip
|
|
31
|
+
|
|
32
|
+
A short label on hover and on focus. `asChild` on the trigger by design: the tooltip must not add a wrapper that swallows the trigger's own focus ring or breaks a flex row. It also means the child has to be focusable — a `<div>` trigger gets no keyboard tooltip, which is the failure this API shape makes obvious rather than silent. Not a replacement for an accessible name. An icon-only button still needs its own `aria-label`; the tooltip repeats that name for sighted pointer users.
|
|
33
|
+
|
|
34
|
+
### Props
|
|
35
|
+
|
|
36
|
+
- `children` (required) — `ReactNode`. The element the tooltip describes. Must be focusable.
|
|
37
|
+
- `content` (required) — `ReactNode`. The tip. Keep it to a phrase — a tooltip is unreachable on touch and invisible to a reader who is scanning, so anything a user NEEDS belongs on the page instead.
|
|
38
|
+
- `side` — `ComponentProps<typeof TooltipPrimitive.Content>['side']` default `'top'`.
|
|
39
|
+
- `sideOffset` — `number` default `6`.
|
|
40
|
+
|
|
41
|
+
Also accepts: `Pick<ComponentProps<typeof TooltipPrimitive.Root>, 'open' | 'defaultOpen' | 'onOpenChange' | 'delayDuration'>`.
|
|
42
|
+
|
|
43
|
+
## Examples
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
<TooltipProvider>
|
|
47
|
+
<Tooltip content="Copy to clipboard">
|
|
48
|
+
<Button iconOnly aria-label="Copy"><Copy size={16} /></Button>
|
|
49
|
+
</Tooltip>
|
|
50
|
+
</TooltipProvider>
|
|
51
|
+
```
|