@momoi-labs/kiso 0.1.0 → 0.2.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/kiso/AGENTS.md +6 -1
- package/kiso/README.md +5 -3
- package/kiso/docs/accessibility.md +18 -2
- package/kiso/docs/brand.md +3 -1
- package/kiso/docs/components/README.md +1 -0
- package/kiso/docs/components/alert.md +4 -1
- package/kiso/docs/components/button.md +25 -15
- package/kiso/docs/components/card.md +42 -6
- package/kiso/docs/components/command-palette.md +6 -3
- package/kiso/docs/components/drawer.md +3 -1
- package/kiso/docs/components/dropdown-menu.md +4 -2
- package/kiso/docs/components/empty-state.md +3 -1
- package/kiso/docs/components/modal-dialog.md +4 -1
- package/kiso/docs/components/popover.md +3 -1
- package/kiso/docs/components/skeleton.md +1 -1
- package/kiso/docs/components/table.md +6 -2
- package/kiso/docs/components/theme-selector.md +114 -0
- package/kiso/docs/components/toast.md +2 -1
- package/kiso/docs/data-interfaces.md +2 -1
- package/kiso/docs/patterns/command-palette.md +2 -1
- package/kiso/docs/patterns/onboarding.md +1 -1
- package/kiso/docs/patterns/settings.md +25 -2
- package/kiso/docs/tokens.md +208 -8
- package/package.json +2 -1
- package/tokens/build/tokens.css +100 -40
- package/tokens/build/tokens.d.ts +149 -13
- package/tokens/build/tokens.json +86 -18
- package/tokens/build/tokens.scss +87 -19
package/kiso/AGENTS.md
CHANGED
|
@@ -45,6 +45,11 @@ documented; it does not become Kiso by repetition or copy-paste.
|
|
|
45
45
|
6. If no contract fits, describe the gap and propose an addition. Do not
|
|
46
46
|
create a parallel local system.
|
|
47
47
|
|
|
48
|
-
Kiso is spec-first
|
|
48
|
+
Kiso is spec-first, with one exception: everywhere except
|
|
49
|
+
[`blocks/`](blocks/README.md), its Markdown files are contracts and carry no
|
|
50
|
+
implementation code. `blocks/` is the exception — reference screens built from
|
|
51
|
+
the contracts, meant to be copied. Blocks are illustrations, not rules: when a
|
|
52
|
+
block and a contract disagree, the contract is right and the block is the bug.
|
|
53
|
+
|
|
49
54
|
Deliberate omissions and the evidence-based growth model are recorded in
|
|
50
55
|
[`docs/evolution.md`](docs/evolution.md).
|
package/kiso/README.md
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Kiso is the Momoi Labs product design system. It combines product identity,
|
|
4
4
|
semantic tokens, component contracts, and reusable screen patterns so products
|
|
5
|
-
with different purposes still belong to the same family. Kiso
|
|
6
|
-
it documents what to build and how it behaves
|
|
7
|
-
implementation code.
|
|
5
|
+
with different purposes still belong to the same family. Kiso is spec-first:
|
|
6
|
+
it documents what to build and how it behaves, and it does not ship component
|
|
7
|
+
implementation code — with one exception, [`blocks/`](blocks/README.md), which
|
|
8
|
+
holds reference screens to copy from. If a block and a contract disagree, the
|
|
9
|
+
contract is right.
|
|
8
10
|
|
|
9
11
|
## For agents
|
|
10
12
|
|
|
@@ -29,8 +29,24 @@ a keyboard, screen reader, touch input, or reduced-motion preference.
|
|
|
29
29
|
- Every interactive element must be reachable and operable by keyboard, with a
|
|
30
30
|
visible focus indicator. Keep focus order aligned with reading and visual
|
|
31
31
|
order; do not use positive `tabindex` values.
|
|
32
|
-
-
|
|
33
|
-
|
|
32
|
+
- <a id="target-size"></a>**Target size applies to coarse pointers.** On a
|
|
33
|
+
coarse pointer, interactive targets must be at least 44 by 44 CSS pixels
|
|
34
|
+
(`--size-touch-min`). Apply it as a `min-height` inside
|
|
35
|
+
`@media (pointer: coarse)`, on top of the control's own
|
|
36
|
+
own control-size height:
|
|
37
|
+
|
|
38
|
+
```css
|
|
39
|
+
.btn { height: var(--size-control-md); } /* 36px */
|
|
40
|
+
|
|
41
|
+
@media (pointer: coarse) {
|
|
42
|
+
.btn { min-height: var(--size-touch-min); } /* 44px */
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Do not use 44px as the control height on a fine pointer. It is an
|
|
47
|
+
accessibility floor for fingers, not a design value, and applying it on the
|
|
48
|
+
desktop is what makes a dense interface look like a toy. A visible control
|
|
49
|
+
may be smaller than its hit area, provided the hit area reaches the minimum
|
|
34
50
|
without overlapping another target.
|
|
35
51
|
- Give icon-only controls an accessible name. Decorative icons must be hidden
|
|
36
52
|
from assistive technology.
|
package/kiso/docs/brand.md
CHANGED
|
@@ -68,7 +68,9 @@ afterthought — starts here.
|
|
|
68
68
|
Kiso's palette is dark-first, with a light alternate, mirroring the marketing
|
|
69
69
|
site's spirit:
|
|
70
70
|
|
|
71
|
-
- **Dark theme** is the
|
|
71
|
+
- **Dark theme** is the reference surface: the one the palette is designed
|
|
72
|
+
against. It is not the default *setting* — the default is to follow the
|
|
73
|
+
operating system. See [ThemeSelector](components/theme-selector.md).
|
|
72
74
|
- **Light theme** ("slate") is a first-class alternate, not an afterthought.
|
|
73
75
|
- **Neutrals** carry the interface; one **accent** carries attention.
|
|
74
76
|
- **Inter** for interface text, **JetBrains Mono** for code and data values.
|
|
@@ -22,6 +22,7 @@ token consumption, and a Radix/shadcn behavioral reference where one exists.
|
|
|
22
22
|
- [Spinner](spinner.md) — Signals indeterminate work when the final layout is not represented.
|
|
23
23
|
- [Switch](switch.md) — Changes one immediately applied boolean setting.
|
|
24
24
|
- [Textarea](textarea.md) — Collects multi-line free-form text.
|
|
25
|
+
- [ThemeSelector](theme-selector.md) — Chooses between following the system colour scheme, forcing light, or forcing dark.
|
|
25
26
|
- [Tooltip](tooltip.md) — Adds nonessential pointer or keyboard context as progressive enhancement.
|
|
26
27
|
- [ValidationMessage](validation-message.md) — Explains a field-level validation error and how to fix it.
|
|
27
28
|
|
|
@@ -60,7 +60,10 @@ Four severities. There is no extra "destructive" variant — that is `error`.
|
|
|
60
60
|
| `warning` | `role="status"` (polite) unless the person must stop; then `role="alert"` | `--color-warning`. |
|
|
61
61
|
| `error` | `role="alert"` (assertive) | `--color-danger` (the danger role *is* error). |
|
|
62
62
|
|
|
63
|
-
Radius `--radius-
|
|
63
|
+
Radius `--radius-lg`; an Alert is a callout inside content, not a panel, so it
|
|
64
|
+
carries no corner marks. Tinted variants use `--color-success-surface` /
|
|
65
|
+
`--color-warning-surface` / `--color-danger-surface` / `--color-info-surface`
|
|
66
|
+
with the matching `*-border`. Padding `--spacing-md`. Gap `--spacing-sm`. Title
|
|
64
67
|
uses the five `--type-role-label-font-family`, `--type-role-label-font-size`,
|
|
65
68
|
`--type-role-label-font-weight`, `--type-role-label-letter-spacing`, and
|
|
66
69
|
`--type-role-label-line-height` properties. Description uses the corresponding
|
|
@@ -50,29 +50,39 @@ Four variants. Do not add a "link" variant; navigation is [Link](link.md).
|
|
|
50
50
|
|
|
51
51
|
| Variant | When | Tokens |
|
|
52
52
|
| --- | --- | --- |
|
|
53
|
-
| `default` | Secondary action on the current task. Most buttons. | Background `--color-
|
|
54
|
-
| `primary` | The one action that advances the current task. At most one primary Button per region. | Background `--color-
|
|
55
|
-
| `destructive` | Irreversible or destructive action (delete, drop, disconnect). User story #4. | Background `--color-
|
|
56
|
-
| `ghost` | Low-emphasis action in chrome, toolbars, or inside a Card. | Transparent background and border. Text `--color-foreground`. Hover background `--color-surface`. |
|
|
53
|
+
| `default` | Secondary action on the current task. Most buttons. | Background `--color-card`, border `--color-input`, text `--color-foreground`, `--shadow-xs`. Hover background `--color-accent-surface`. |
|
|
54
|
+
| `primary` | The one action that advances the current task. At most one primary Button per region. | Background `--color-primary`, text `--color-primary-foreground`, transparent border, `--shadow-xs`. Hover background `--color-primary-hover`. |
|
|
55
|
+
| `destructive` | Irreversible or destructive action (delete, drop, disconnect). User story #4. | Background `--color-danger`, text `--color-danger-foreground`, transparent border, `--shadow-xs`. Match confirmation weight to stakes; see voice-and-tone. |
|
|
56
|
+
| `ghost` | Low-emphasis action in chrome, toolbars, or inside a Card. | Transparent background and border. Text `--color-muted-foreground`. Hover background `--color-accent-surface-hover`, text `--color-foreground`. |
|
|
57
57
|
|
|
58
|
-
`primary` and `
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
`primary` and `destructive` are **solid fills**. The accent is the fill; the
|
|
59
|
+
label is `--color-primary-foreground` or `--color-danger-foreground`, which
|
|
60
|
+
inverts with the fill and is gated at 4.5:1 against it.
|
|
61
|
+
|
|
62
|
+
Do not render `primary` as an outline — accent text on a surface with an accent
|
|
63
|
+
border. That treatment reads as a secondary control, and in a violet system it
|
|
64
|
+
is what makes the primary action look grey.
|
|
63
65
|
|
|
64
66
|
If a destructive action is not irreversible (archive, disable, hide), use
|
|
65
67
|
`default` or `ghost`, not `destructive`.
|
|
66
68
|
|
|
67
69
|
## Sizes
|
|
68
70
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
|
73
|
-
|
|
|
71
|
+
Height comes from a control-size token, not from padding. Padding sets the inline
|
|
72
|
+
measure only.
|
|
73
|
+
|
|
74
|
+
| Size | Height | Type role | Inline padding | Radius | Use |
|
|
75
|
+
| --- | --- | --- | --- | --- | --- |
|
|
76
|
+
| `xs` | `--size-control-xs` | Label properties | `--spacing-sm` | `--radius-sm` | Inline row actions in dense tables. |
|
|
77
|
+
| `sm` | `--size-control-sm` | Label properties (`--type-role-label-font-family`, `--type-role-label-font-size`, `--type-role-label-font-weight`, `--type-role-label-letter-spacing`, `--type-role-label-line-height`) | `--spacing-md` | `--radius-md` | Toolbars, Card footers, compact filters. |
|
|
78
|
+
| `md` (default) | `--size-control-md` | Body properties | `--spacing-md` | `--radius-md` | Forms, page actions, dialogs. |
|
|
79
|
+
| `lg` | `--size-control-lg` | Body properties | `--spacing-lg` | `--radius-md` | Rare; empty-state or onboarding primary actions. |
|
|
80
|
+
|
|
81
|
+
`md` is 36px. It is **not** `--size-touch-min`: on a coarse pointer, add
|
|
82
|
+
`min-height: var(--size-touch-min)` inside `@media (pointer: coarse)` and leave
|
|
83
|
+
the desktop height alone. See [Accessibility](../accessibility.md#target-size).
|
|
74
84
|
|
|
75
|
-
Do not invent a
|
|
85
|
+
Do not invent a fifth size. Page-level calls to action still use `md` or
|
|
76
86
|
`lg`. PageHeader (navigation slice) composes Buttons; it is not a Button
|
|
77
87
|
size.
|
|
78
88
|
|
|
@@ -53,17 +53,53 @@ shape.
|
|
|
53
53
|
|
|
54
54
|
| Variant | When | Tokens |
|
|
55
55
|
| --- | --- | --- |
|
|
56
|
-
| `plain` (default) | Grouping on the page canvas. | Background `--color-
|
|
57
|
-
| `elevated` | The grouping must lift above nearby surfaces (a floating picker, a featured summary). | Background `--color-
|
|
56
|
+
| `plain` (default) | Grouping on the page canvas. | Background `--color-card`, border `--color-border`, radius `--radius-surface`, padding `--spacing-lg`, `--shadow-xs`. |
|
|
57
|
+
| `elevated` | The grouping must lift above nearby surfaces (a floating picker, a featured summary). | Background `--color-popover`, border `--color-border`, shadow `--shadow-sm`. Same radius and padding. |
|
|
58
58
|
|
|
59
|
-
Default is `plain`.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
Default is `plain`. `--color-card` is the panel fill and `--color-popover` the
|
|
60
|
+
elevated one. Use `elevated` only when the Card is competing with other
|
|
61
|
+
surfaces and needs that lift — not on every tile. A recessed band inside a Card
|
|
62
|
+
— header strip, footer, table head — uses `--color-muted`.
|
|
63
63
|
|
|
64
64
|
Do not add outline/ghost Card variants. If the grouping needs no surface,
|
|
65
65
|
it is a section with a heading, not a Card.
|
|
66
66
|
|
|
67
|
+
## Corner marks
|
|
68
|
+
|
|
69
|
+
This is the shared panel contract. Card, [Table](table.md) wrapper,
|
|
70
|
+
[ModalDialog](modal-dialog.md), [Drawer](drawer.md),
|
|
71
|
+
[CommandPalette](command-palette.md), and code or log blocks are **panels**:
|
|
72
|
+
square (`--radius-surface`) with corner marks. Popover, DropdownMenu, Toast,
|
|
73
|
+
Alert, and Tooltip are transient chrome, not panels: they keep a small radius
|
|
74
|
+
and carry no marks.
|
|
75
|
+
|
|
76
|
+
A corner mark is an open registration mark: **two 1px ticks per corner**, each
|
|
77
|
+
lying along the frame line it extends and stopping `--corner-mark-gap` short of
|
|
78
|
+
it, so the mark points at the corner without touching it.
|
|
79
|
+
|
|
80
|
+
| Token | Value | Meaning |
|
|
81
|
+
| --- | --- | --- |
|
|
82
|
+
| `--color-corner-mark` | `--color-border-strong` | Tick colour. |
|
|
83
|
+
| `--corner-mark` | `1` | Opacity: marks on (`1`) or off (`0`). |
|
|
84
|
+
| `--corner-mark-tick` | 4px | Length of one tick. |
|
|
85
|
+
| `--corner-mark-gap` | 2px | Distance from tick end to the frame. |
|
|
86
|
+
|
|
87
|
+
Two ticks, not four. A full cross puts its other two arms directly on top of
|
|
88
|
+
the panel's 1px border, where they are invisible — the mark reads as a bracket
|
|
89
|
+
regardless. Drawing four is wasted paint and makes the hollow centre look
|
|
90
|
+
accidental.
|
|
91
|
+
|
|
92
|
+
The gap is the mark. Close it and this is just a thicker border.
|
|
93
|
+
|
|
94
|
+
Marks go on every panel, without exception. There is no rounded mode and no
|
|
95
|
+
`data-corners` attribute; the corner language was decided once and is not a
|
|
96
|
+
per-product setting.
|
|
97
|
+
|
|
98
|
+
Draw them on one pseudo-element inset by `calc(-1 * (var(--corner-mark-tick) +
|
|
99
|
+
var(--corner-mark-gap)))`, so no markup and no images are needed. If the panel
|
|
100
|
+
scrolls, move `overflow` to an inner element — the marks sit just outside the
|
|
101
|
+
frame and a scrolling wrapper clips them away.
|
|
102
|
+
|
|
67
103
|
## Sizes
|
|
68
104
|
|
|
69
105
|
Size changes padding and gap, not type roles.
|
|
@@ -63,7 +63,8 @@ Do not ship separate palettes per page unless the product truly scopes
|
|
|
63
63
|
commands; default is one app-level palette.
|
|
64
64
|
|
|
65
65
|
Surface: `--color-elevated-surface`, border `--color-border`, shadow
|
|
66
|
-
`--shadow-
|
|
66
|
+
`--shadow-lg`, radius `--radius-surface`, with corner marks — the palette is a
|
|
67
|
+
panel. Input and items use foreground /
|
|
67
68
|
muted-foreground roles. Active (highlighted) item uses `--color-surface` or
|
|
68
69
|
a quiet `--color-primary` indicator without filling the row in primary ink.
|
|
69
70
|
|
|
@@ -145,8 +146,10 @@ properties for group headings.
|
|
|
145
146
|
`--color-elevated-surface`, `--color-surface`, `--color-foreground`,
|
|
146
147
|
`--color-muted-foreground`, `--color-subtle-foreground`, `--color-border`,
|
|
147
148
|
`--color-primary` (highlight affordance only), `--color-focus`,
|
|
148
|
-
`--color-disabled`, `--shadow-
|
|
149
|
-
`--radius-
|
|
149
|
+
`--color-disabled`, `--shadow-lg`, `--spacing-sm` / `--spacing-md`,
|
|
150
|
+
`--radius-surface`, `--color-popover`, `--color-selected`,
|
|
151
|
+
`--color-corner-mark`, `--corner-mark`, `--corner-mark-tick`,
|
|
152
|
+
`--corner-mark-gap`, `--motion-duration-fast`, and `--motion-easing-standard`.
|
|
150
153
|
Items use `--type-role-body-font-family`, `--type-role-body-font-size`,
|
|
151
154
|
`--type-role-body-font-weight`, `--type-role-body-letter-spacing`, and
|
|
152
155
|
`--type-role-body-line-height`; group headings use the equivalent five
|
|
@@ -26,7 +26,9 @@ Drawer Root
|
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
Content uses `--color-elevated-surface`, `--color-foreground`,
|
|
29
|
-
`--color-border`, `--spacing-lg` padding, `--radius-
|
|
29
|
+
`--color-border`, `--spacing-lg` padding, `--radius-surface`, and
|
|
30
|
+
`--shadow-lg`. The scrim uses `--color-overlay`. Panels are square (`--radius-surface`) and carry corner marks. See
|
|
31
|
+
[Card](card.md#corner-marks) for the shared panel contract.
|
|
30
32
|
Entry/exit uses `--motion-duration-normal` and `--motion-easing-standard`, with
|
|
31
33
|
no travel under reduced motion.
|
|
32
34
|
|
|
@@ -75,7 +75,8 @@ Content tokens: background `--color-elevated-surface`, border
|
|
|
75
75
|
`--color-border`, text `--color-foreground`, muted hints
|
|
76
76
|
`--color-muted-foreground`, destructive `--color-danger`, focus/highlight
|
|
77
77
|
`--color-focus` / quiet `--color-surface` for the highlighted item. Radius
|
|
78
|
-
`--radius-
|
|
78
|
+
`--radius-lg` on the menu, `--radius-md` on each item; transient chrome, so no
|
|
79
|
+
corner marks. Padding `--spacing-xs` around the list; item padding
|
|
79
80
|
`--spacing-sm` / `--spacing-md`.
|
|
80
81
|
|
|
81
82
|
## Sizes
|
|
@@ -156,7 +157,8 @@ Content tokens: background `--color-elevated-surface`, border
|
|
|
156
157
|
`--color-elevated-surface`, `--color-surface`, `--color-foreground`,
|
|
157
158
|
`--color-muted-foreground`, `--color-border`, `--color-danger`,
|
|
158
159
|
`--color-focus`, `--color-disabled`, `--spacing-xs` list padding,
|
|
159
|
-
`--spacing-sm` / `--spacing-md` item padding, `--radius-
|
|
160
|
+
`--spacing-sm` / `--spacing-md` item padding, `--radius-lg`, `--radius-md`,
|
|
161
|
+
`--color-popover`, `--color-selected`, `--shadow-md`,
|
|
160
162
|
the five property-qualified body typography tokens for items, the five label
|
|
161
163
|
typography tokens for group labels, `--motion-duration-fast`, and
|
|
162
164
|
`--motion-easing-standard`. Trigger consumes Button/IconButton tokens. No raw
|
|
@@ -123,7 +123,9 @@ PageHeader.
|
|
|
123
123
|
|
|
124
124
|
`--color-foreground`, `--color-muted-foreground`, `--color-surface` /
|
|
125
125
|
`--color-background`, optional icon `--color-muted-foreground`, `--spacing-lg`
|
|
126
|
-
padding (`--spacing-md` for `sm`), `--spacing-sm` gap, `--radius-
|
|
126
|
+
padding (`--spacing-md` for `sm`), `--spacing-sm` gap, `--radius-lg` on the
|
|
127
|
+
icon frame, the hatch tokens (`--color-hatch`, `--hatch-line`,
|
|
128
|
+
`--hatch-period`, `--hatch-angle`), and
|
|
127
129
|
`--motion-duration-fast` / `--motion-easing-standard`. Typography uses every
|
|
128
130
|
property of the selected heading, label, and body roles named above. Action consumes Button/Link
|
|
129
131
|
tokens. No raw hex/px.
|
|
@@ -24,7 +24,10 @@ Dialog Root
|
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
Content uses `--color-elevated-surface`, `--color-foreground`,
|
|
27
|
-
`--color-border`, `--radius-
|
|
27
|
+
`--color-border`, `--radius-surface`, `--spacing-lg` padding, and
|
|
28
|
+
`--shadow-lg`. A Dialog is a panel: it carries corner marks. The scrim uses
|
|
29
|
+
`--color-overlay`. Panels are square (`--radius-surface`) and carry corner marks. See
|
|
30
|
+
[Card](card.md#corner-marks) for the shared panel contract.
|
|
28
31
|
Overlay transitions use `--motion-duration-normal` and
|
|
29
32
|
`--motion-easing-standard`.
|
|
30
33
|
|
|
@@ -21,7 +21,9 @@ Popover
|
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
Content uses `--color-elevated-surface`, `--color-foreground`,
|
|
24
|
-
`--color-border`, `--radius-
|
|
24
|
+
`--color-popover`, `--color-border`, `--radius-lg`, `--spacing-md` padding,
|
|
25
|
+
and `--shadow-md`. A Popover is transient chrome, not a panel: it keeps a small
|
|
26
|
+
radius and carries no corner marks.
|
|
25
27
|
Placement offset uses `--spacing-xs`, collision padding uses `--spacing-md`,
|
|
26
28
|
and motion uses `--motion-duration-fast` with `--motion-easing-standard`.
|
|
27
29
|
|
|
@@ -41,7 +41,7 @@ Variants are shapes, not colors.
|
|
|
41
41
|
| Variant | Shape tokens | Stands in for |
|
|
42
42
|
| --- | --- | --- |
|
|
43
43
|
| `text` | Height of the target role's `--type-role-body-line-height`, `--type-role-label-line-height`, or `--type-role-heading-line-height`; width a fraction of the column; radius `--radius-sm` | Titles, labels, table cells, descriptions. |
|
|
44
|
-
| `block` | Radius `--radius-md` (or `--radius-
|
|
44
|
+
| `block` | Radius `--radius-md` (or `--radius-surface` when replacing a Card or panel) | Cards, images, chart frames, table bodies as a whole. |
|
|
45
45
|
| `circle` | Radius `--radius-full`, equal width and height | Avatars and circular IconButtons. |
|
|
46
46
|
|
|
47
47
|
Fill is `--color-border` on the surrounding `--color-surface` or
|
|
@@ -111,7 +111,7 @@ Table has no `sm` / `md` / `lg` control scale like Button. Size comes from:
|
|
|
111
111
|
| --- | --- |
|
|
112
112
|
| Type | All five property-qualified body typography tokens for cells; all five property-qualified label typography tokens for headers. |
|
|
113
113
|
| Cell padding | Density table above (`--spacing-xs`, `--spacing-sm`, and `--spacing-md`). |
|
|
114
|
-
| Radius | Outer wrapper `--radius-
|
|
114
|
+
| Radius | Outer wrapper `--radius-surface`; internal cells are square. The wrapper is a panel and carries corner marks. Scrolling moves to an inner element so the marks, which sit just outside the frame, are not clipped. |
|
|
115
115
|
| Checkbox / IconButton in cells | `sm` controls so row height stays dense. |
|
|
116
116
|
|
|
117
117
|
Do not invent a fourth density. Do not set row height in raw pixels.
|
|
@@ -231,7 +231,11 @@ Consume only semantic roles: `--color-background`, `--color-surface`,
|
|
|
231
231
|
`--color-border`, `--color-primary`, `--color-focus`, `--color-disabled`,
|
|
232
232
|
`--color-danger` (via Alert on error); the five property-qualified body and
|
|
233
233
|
label typography tokens; `--spacing-xs`, `--spacing-sm`, `--spacing-md`;
|
|
234
|
-
`--radius-
|
|
234
|
+
`--radius-surface`; `--color-muted` for the header and footer bands;
|
|
235
|
+
`--color-selected` for a selected row; `--color-accent-surface` for row hover;
|
|
236
|
+
`--size-control-lg` for row height; `--color-corner-mark`, `--corner-mark`,
|
|
237
|
+
`--corner-mark-tick`, `--corner-mark-gap`; `--motion-duration-fast`; and
|
|
238
|
+
`--motion-easing-standard`. No
|
|
235
239
|
palette primitives, no raw hex/px.
|
|
236
240
|
|
|
237
241
|
## Radix/shadcn mapping
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# ThemeSelector
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
ThemeSelector chooses which colour scheme the interface uses: follow the
|
|
6
|
+
operating system, force light, or force dark. It is the only sanctioned control
|
|
7
|
+
for that choice.
|
|
8
|
+
|
|
9
|
+
## The three values
|
|
10
|
+
|
|
11
|
+
| Value | Meaning | `data-theme` on `<html>` |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| `system` (default) | Follow the operating system, and keep following it when it changes. | **No attribute at all.** |
|
|
14
|
+
| `light` | Force light regardless of the OS. | `data-theme="light"` |
|
|
15
|
+
| `dark` | Force dark regardless of the OS. | `data-theme="dark"` |
|
|
16
|
+
|
|
17
|
+
`system` is the absence of the attribute, not `data-theme="system"`. The tokens
|
|
18
|
+
declare `color-scheme: light dark` on `:root`, so with no attribute present
|
|
19
|
+
every `light-dark()` value already resolves against the OS preference — no
|
|
20
|
+
media query, no JavaScript, no flash. An explicit choice only has to narrow
|
|
21
|
+
`color-scheme` to one keyword. See [tokens](../tokens.md).
|
|
22
|
+
|
|
23
|
+
Do not implement `system` by reading `prefers-color-scheme` and writing
|
|
24
|
+
`data-theme`. That freezes the choice at page load and stops following the OS.
|
|
25
|
+
|
|
26
|
+
## Persistence
|
|
27
|
+
|
|
28
|
+
- An explicit choice persists under the key `kiso-theme`, with the value
|
|
29
|
+
`light` or `dark`.
|
|
30
|
+
- Choosing `system` persists the literal `system` **and removes** the
|
|
31
|
+
attribute.
|
|
32
|
+
- Read the stored value in a blocking inline script in `<head>`, before first
|
|
33
|
+
paint, and apply it only when it is not `system`. Anything later flashes.
|
|
34
|
+
- Storage may be unavailable (private mode, disabled cookies). Wrap reads and
|
|
35
|
+
writes so a failure degrades to `system` rather than throwing.
|
|
36
|
+
|
|
37
|
+
## Anatomy
|
|
38
|
+
|
|
39
|
+
1. **Row label** — the word "Theme", on the left.
|
|
40
|
+
2. **Segmented control** — the three values, on the right, as a group.
|
|
41
|
+
3. **Options** — one per value, each an icon with an accessible name.
|
|
42
|
+
|
|
43
|
+
| Value | Icon | Accessible name |
|
|
44
|
+
| --- | --- | --- |
|
|
45
|
+
| `system` | monitor | "Follow system" |
|
|
46
|
+
| `light` | sun | "Light theme" |
|
|
47
|
+
| `dark` | moon | "Dark theme" |
|
|
48
|
+
|
|
49
|
+
Icon-only. The three concepts are conventional enough that icons carry them,
|
|
50
|
+
and visible text would make the row wider than the setting deserves. The
|
|
51
|
+
accessible name is required, not optional — see
|
|
52
|
+
[IconButton](icon-button.md).
|
|
53
|
+
|
|
54
|
+
## Layout
|
|
55
|
+
|
|
56
|
+
A single configuration row: label left, control right, aligned to the baseline
|
|
57
|
+
of the label. This is the standard settings row, not a Card of its own. See
|
|
58
|
+
[Settings](../patterns/settings.md#theme).
|
|
59
|
+
|
|
60
|
+
```text
|
|
61
|
+
Theme [ ▣ ][ ☀ ][ ☾ ]
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Tokens
|
|
65
|
+
|
|
66
|
+
Track `--color-muted`, border `--color-border`, radius `--radius-lg`, padding
|
|
67
|
+
`--spacing-2xs`, gap `--spacing-2xs`. Each option is `--size-control-sm` high,
|
|
68
|
+
radius `--radius-md`, text `--color-muted-foreground`, icon `--size-icon-sm`.
|
|
69
|
+
|
|
70
|
+
The selected option takes `--color-card`, `--color-foreground`, and
|
|
71
|
+
`--shadow-xs` — a raised chip inside a recessed track. Transition on
|
|
72
|
+
`--motion-duration-fast` / `--motion-easing-standard`.
|
|
73
|
+
|
|
74
|
+
Do not fill the selected option with `--color-primary`. This control does not
|
|
75
|
+
advance a task; it is a preference, and a violet chip here competes with the
|
|
76
|
+
page's actual primary action.
|
|
77
|
+
|
|
78
|
+
## States
|
|
79
|
+
|
|
80
|
+
| State | Behavior |
|
|
81
|
+
| --- | --- |
|
|
82
|
+
| default | Three options, exactly one selected. |
|
|
83
|
+
| hover | Unselected option raises text to `--color-foreground`. |
|
|
84
|
+
| focus | Visible ring using `--color-ring`. Never remove it. |
|
|
85
|
+
| selected | Raised chip as above, plus the accessible selected state. |
|
|
86
|
+
| disabled | Not a state. The theme is always changeable. |
|
|
87
|
+
|
|
88
|
+
There is no loading state. The change is local and instant; do not wait on a
|
|
89
|
+
server round-trip to repaint, and do not show a Toast for it.
|
|
90
|
+
|
|
91
|
+
## Accessibility
|
|
92
|
+
|
|
93
|
+
- Use a radio group or a tablist — a set of three mutually exclusive options
|
|
94
|
+
with exactly one selected. Do not use three independent toggle buttons.
|
|
95
|
+
- Each option carries a visible-to-AT name from the table above.
|
|
96
|
+
- Arrow keys move between options; the group is one tab stop.
|
|
97
|
+
- Announce the selection, not the resulting colours.
|
|
98
|
+
- The control must remain operable at the current theme's contrast in both
|
|
99
|
+
themes; it is chrome, so it is gated like any other control.
|
|
100
|
+
|
|
101
|
+
## When NOT to use
|
|
102
|
+
|
|
103
|
+
- A single "dark mode" Switch. A boolean cannot express "follow the system",
|
|
104
|
+
which is the default and the most common choice.
|
|
105
|
+
- A theme entry buried inside a DropdownMenu as the only access point. A menu
|
|
106
|
+
may mirror the control, but the setting lives in a settings row.
|
|
107
|
+
- Any control that offers colour options beyond these three. Kiso has two
|
|
108
|
+
themes.
|
|
109
|
+
|
|
110
|
+
## Related
|
|
111
|
+
|
|
112
|
+
- [tokens](../tokens.md) — how `light-dark()` and `color-scheme` resolve.
|
|
113
|
+
- [Settings](../patterns/settings.md#theme) — where the row lives.
|
|
114
|
+
- [Switch](switch.md) — for actual booleans.
|
|
@@ -24,7 +24,8 @@ Toast Provider
|
|
|
24
24
|
Use `--color-elevated-surface`, `--color-foreground`,
|
|
25
25
|
`--color-muted-foreground`, `--color-border`, `--color-info`, `--color-success`,
|
|
26
26
|
`--color-warning`, or `--color-danger` where severity must be shown;
|
|
27
|
-
`--spacing-md` padding; `--spacing-sm` gap; `--radius-
|
|
27
|
+
`--spacing-md` padding; `--spacing-sm` gap; `--radius-lg`; and `--shadow-md`.
|
|
28
|
+
Transient chrome, not a panel: no corner marks.
|
|
28
29
|
|
|
29
30
|
## Variants
|
|
30
31
|
|
|
@@ -153,7 +153,8 @@ and the detail view contains the same explanation.
|
|
|
153
153
|
- Use inline code for a value that fits in the surrounding sentence or cell.
|
|
154
154
|
Use a code block for multi-line SQL, logs, config, or any value where line
|
|
155
155
|
breaks and indentation matter.
|
|
156
|
-
- Code blocks
|
|
156
|
+
- Code blocks are panels: `--color-surface`, `--color-border`,
|
|
157
|
+
`--radius-surface` with corner marks,
|
|
157
158
|
`--spacing-md`, and `--type-role-code`. Inline code uses
|
|
158
159
|
`--color-elevated-surface`, `--radius-sm`, horizontal `--spacing-xs`, and
|
|
159
160
|
`--type-role-code`.
|
|
@@ -82,7 +82,8 @@ is acceleration, not a bypass for the gate.
|
|
|
82
82
|
```
|
|
83
83
|
|
|
84
84
|
The palette is centered or top-anchored, elevated (`--color-elevated-surface`,
|
|
85
|
-
`--shadow-
|
|
85
|
+
`--shadow-lg`, `--radius-surface`, with corner marks). The active (highlighted)
|
|
86
|
+
item uses a quiet
|
|
86
87
|
`--color-surface` or `--color-primary` indicator — not a filled primary row.
|
|
87
88
|
|
|
88
89
|
## Rules
|
|
@@ -22,7 +22,7 @@ The issue calls the progress composition “Steps”, but Kiso has no Steps
|
|
|
22
22
|
component. Represent progress as a semantic ordered list with current and
|
|
23
23
|
completed text states; do not invent a new component in this pattern.
|
|
24
24
|
|
|
25
|
-
Cards use `--color-
|
|
25
|
+
Cards use `--color-card`, `--color-border`, `--radius-surface`, and semantic
|
|
26
26
|
spacing. Current-step emphasis uses `--color-primary`; completed status may use
|
|
27
27
|
`--color-success`; primary and secondary copy use `--color-foreground` and
|
|
28
28
|
`--color-muted-foreground`. Keyboard focus uses `--color-focus`.
|
|
@@ -24,9 +24,32 @@ immediate vs deferred persistence, and unambiguous save feedback.
|
|
|
24
24
|
| Feedback | [Toast](../components/toast.md), [Alert](../components/alert.md), [ValidationMessage](../components/validation-message.md) | Saved confirmation; section errors; field errors |
|
|
25
25
|
| Shell | [Application shell](application-shell.md) | Authenticated framing |
|
|
26
26
|
|
|
27
|
-
Tokens: `--color-background` canvas, `--color-
|
|
27
|
+
Tokens: `--color-background` canvas, `--color-card` Cards, `--color-border`
|
|
28
28
|
separators, `--color-foreground` / `--color-muted-foreground` copy,
|
|
29
|
-
`--color-primary` for current section/nav, `--color-
|
|
29
|
+
`--color-primary` for current section/nav, `--color-ring` on controls.
|
|
30
|
+
|
|
31
|
+
## Theme
|
|
32
|
+
|
|
33
|
+
Appearance is a settings row like any other: label left, control right, inside
|
|
34
|
+
a Card with the rest of the preferences. Use
|
|
35
|
+
[ThemeSelector](../components/theme-selector.md); that contract owns the
|
|
36
|
+
values, persistence, and markup.
|
|
37
|
+
|
|
38
|
+
Three points bind here rather than there:
|
|
39
|
+
|
|
40
|
+
- The default is `system` — no `data-theme` attribute on `<html>` — and it
|
|
41
|
+
keeps following the OS while the page is open.
|
|
42
|
+
- The choice is local and instant. It persists to `localStorage` under
|
|
43
|
+
`kiso-theme`; it does not go through the section's Save button, and it does
|
|
44
|
+
not raise a "Settings saved" Toast.
|
|
45
|
+
- It is exempt from the explicit-save rule above for the same reason a Switch
|
|
46
|
+
is: the person sees the result immediately, so a confirmation would only
|
|
47
|
+
restate what already happened.
|
|
48
|
+
|
|
49
|
+
```text
|
|
50
|
+
Card: Appearance
|
|
51
|
+
Theme [ ▣ ][ ☀ ][ ☾ ]
|
|
52
|
+
```
|
|
30
53
|
|
|
31
54
|
## Flow
|
|
32
55
|
|