@sableui/react 0.15.0 → 0.16.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/CHANGELOG.md +73 -0
- package/bin/sable-lint.mjs +5 -1
- package/dist/{_contract-CkqXDVww.d.ts → _contract-CDa9-NdB.d.ts} +47 -1
- package/dist/blocks/wallet-block.js +2 -2
- package/dist/components/app-shell/app-shell-frame.js +16 -0
- package/dist/components/app-shell/app-shell-main.js +12 -0
- package/dist/components/app-shell/app-shell.js +28 -4
- package/dist/components/app-shell/app-shell.meta.js +88 -4
- package/dist/components/area-chart/area-chart.meta.js +6 -1
- package/dist/components/attachment/attachment.meta.js +2 -1
- package/dist/components/attachment/attachment.variants.js +1 -1
- package/dist/components/badge/badge.meta.js +8 -1
- package/dist/components/badge/badge.variants.js +7 -7
- package/dist/components/banner/banner.meta.js +6 -1
- package/dist/components/banner/banner.variants.js +5 -5
- package/dist/components/bar-chart/bar-chart.meta.js +6 -1
- package/dist/components/caret-menu/caret-menu.js +5 -6
- package/dist/components/chat-composer/chat-composer.meta.js +2 -2
- package/dist/components/chat-composer/chat-composer.variants.js +1 -1
- package/dist/components/color-field/color-field.js +6 -8
- package/dist/components/combobox/combobox.js +27 -5
- package/dist/components/combobox/combobox.meta.js +10 -2
- package/dist/components/command-menu/command-menu.js +14 -3
- package/dist/components/command-menu/command-menu.meta.js +9 -1
- package/dist/components/date-picker/date-picker.meta.js +2 -2
- package/dist/components/feedback/feedback.js +1 -1
- package/dist/components/feedback/feedback.meta.js +2 -1
- package/dist/components/gradient-art/gradient-art.js +8 -5
- package/dist/components/gradient-art/gradient-art.meta.js +35 -2
- package/dist/components/input/input.meta.js +11 -3
- package/dist/components/input-group/input-group.js +1 -1
- package/dist/components/input-group/input-group.meta.js +1 -1
- package/dist/components/line-chart/line-chart.meta.js +6 -1
- package/dist/components/menu/menu.js +1 -1
- package/dist/components/meter/meter.js +53 -7
- package/dist/components/meter/meter.meta.js +51 -4
- package/dist/components/meter/meter.variants.js +43 -7
- package/dist/components/note/note.meta.js +5 -1
- package/dist/components/note/note.variants.js +4 -4
- package/dist/components/number-field/number-field.meta.js +2 -2
- package/dist/components/otp-field/otp-field.meta.js +2 -2
- package/dist/components/panel-group/panel-group.js +5 -8
- package/dist/components/pie-chart/pie-chart.meta.js +6 -1
- package/dist/components/radar-chart/radar-chart.meta.js +6 -1
- package/dist/components/radial-chart/radial-chart.meta.js +6 -1
- package/dist/components/search-input/search-input.meta.js +11 -3
- package/dist/components/segmented-bar/segmented-bar.meta.js +8 -1
- package/dist/components/segmented-bar/segmented-bar.variants.js +7 -7
- package/dist/components/select/select.js +1 -1
- package/dist/components/select/select.meta.js +2 -2
- package/dist/components/sheet/sheet.js +5 -4
- package/dist/components/sidebar/sidebar.js +16 -1
- package/dist/components/sidebar/sidebar.meta.js +7 -2
- package/dist/components/sparkline/sparkline.meta.js +8 -1
- package/dist/components/status-dot/status-dot.meta.js +8 -1
- package/dist/components/status-dot/status-dot.variants.js +7 -7
- package/dist/components/stepper/stepper.meta.js +2 -1
- package/dist/components/stepper/stepper.variants.js +1 -1
- package/dist/components/table/table.meta.js +4 -4
- package/dist/components/textarea/textarea.js +5 -0
- package/dist/components/textarea/textarea.meta.js +3 -3
- package/dist/file-hashes.json +91 -88
- package/dist/foundations/accessibility.js +5 -0
- package/dist/index.d.ts +132 -24
- package/dist/index.js +9 -1
- package/dist/lib/chart/types.js +8 -8
- package/dist/lib/chart/use-arrival.js +5 -4
- package/dist/lib/field-shell.js +1 -1
- package/dist/lib/highlight-glide.js +6 -6
- package/dist/lib/scrub-gesture.js +6 -6
- package/dist/lib/use-caret-trigger.js +11 -18
- package/dist/lib/use-match-highlight.js +69 -0
- package/dist/lib/use-smooth-wheel.js +10 -8
- package/dist/presets/index.d.ts +13 -2
- package/dist/presets/index.js +17 -1
- package/dist/styles.css +100 -0
- package/dist/{theme-provider-CdSicAad.d.ts → theme-provider-BydfM5Z0.d.ts} +1 -1
- package/dist/themes/_contract.js +14 -0
- package/dist/themes/atelier/atelier.css +18 -0
- package/dist/themes/atelier/index.d.ts +1 -1
- package/dist/themes/contrast.js +48 -1
- package/dist/themes/ember/ember.css +18 -0
- package/dist/themes/ember/index.d.ts +1 -1
- package/dist/themes/index.d.ts +2 -2
- package/dist/themes/meridian/index.d.ts +1 -1
- package/dist/themes/meridian/meridian.css +18 -0
- package/dist/themes/poppy/index.d.ts +1 -1
- package/dist/themes/poppy/poppy.css +18 -0
- package/dist/themes/prism/index.d.ts +1 -1
- package/dist/themes/prism/prism.css +18 -0
- package/dist/themes/sable/index.d.ts +1 -1
- package/dist/themes/sable/sable.css +18 -0
- package/dist/themes/verdant/index.d.ts +1 -1
- package/dist/themes/verdant/verdant.css +18 -0
- package/llms/blocks/wallet-block.md +5 -4
- package/llms/components/app-shell.md +72 -3
- package/llms/components/area-chart.md +1 -1
- package/llms/components/attachment.md +1 -1
- package/llms/components/badge.md +1 -1
- package/llms/components/banner.md +1 -1
- package/llms/components/bar-chart.md +1 -1
- package/llms/components/chat-composer.md +1 -1
- package/llms/components/combobox.md +2 -1
- package/llms/components/command-menu.md +3 -2
- package/llms/components/date-picker.md +1 -1
- package/llms/components/feedback.md +1 -1
- package/llms/components/gradient-art.md +28 -1
- package/llms/components/input-group.md +1 -1
- package/llms/components/input.md +4 -2
- package/llms/components/line-chart.md +1 -1
- package/llms/components/meter.md +33 -4
- package/llms/components/note.md +1 -1
- package/llms/components/number-field.md +1 -1
- package/llms/components/otp-field.md +1 -1
- package/llms/components/pie-chart.md +1 -1
- package/llms/components/radar-chart.md +1 -1
- package/llms/components/radial-chart.md +1 -1
- package/llms/components/search-input.md +20 -2
- package/llms/components/segmented-bar.md +1 -1
- package/llms/components/select.md +1 -1
- package/llms/components/sidebar.md +3 -2
- package/llms/components/sparkline.md +1 -1
- package/llms/components/status-dot.md +1 -1
- package/llms/components/stepper.md +1 -1
- package/llms/components/table.md +2 -2
- package/llms/components/textarea.md +2 -2
- package/llms/foundations/accessibility.md +1 -0
- package/llms/reference/token-intent.md +22 -2
- package/llms/reference/utilities.md +5 -2
- package/llms-full.txt +222 -49
- package/llms.txt +2 -2
- package/package.json +1 -1
- package/registry.json +396 -57
- package/scripts/lint-rules.mjs +6 -3
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Status:** stable
|
|
4
4
|
|
|
5
|
-
Styled search field with a leading magnifier and a clearable X. Soft-square (rounded-sm),
|
|
5
|
+
Styled search field with a leading magnifier and a clearable X. Soft-square (rounded-sm), the theme's field surface, 2px focus ring; the clear button appears only when there is a value.
|
|
6
6
|
|
|
7
7
|
**Keywords:** search, input, filter, query
|
|
8
8
|
|
|
@@ -15,6 +15,7 @@ Use SearchInput for text queries that filter or search a known content set.
|
|
|
15
15
|
- Do: Use a clear placeholder that names the content being searched.
|
|
16
16
|
- Do: Provide a visible clear affordance when query state persists.
|
|
17
17
|
- Do: When a button stands in for search (a header trigger that opens CommandMenu with ⌘K), use CommandMenuTrigger. It wears this field's shell from the same source, so the two cannot drift; a hand-styled button already did once, into a borderless chip that matched neither the field nor a button.
|
|
18
|
+
- Do: Light the query in the results it filters with `useMatchHighlight(query)` — a callback ref for the results container, with `selector` to keep it to titles. It paints on the `highlight` pair without wrapping matches in `<mark>`, the same paint Combobox and CommandMenu use for their rows.
|
|
18
19
|
- Don't: Do not use SearchInput as a command palette; use CommandMenu for global commands, opened from the header by CommandMenuTrigger. A SearchInput that opens a dialog on focus is a text box you cannot type in.
|
|
19
20
|
- Don't: Do not search on every keystroke against an expensive backend without debouncing. The user sees results flicker and reorder under them, and you send a request per character.
|
|
20
21
|
|
|
@@ -34,7 +35,7 @@ Use SearchInput for text queries that filter or search a known content set.
|
|
|
34
35
|
|
|
35
36
|
## Tokens used
|
|
36
37
|
|
|
37
|
-
`
|
|
38
|
+
`field-border`, `field`, `foreground`, `muted-foreground`, `ring`, `destructive`
|
|
38
39
|
|
|
39
40
|
## Motion
|
|
40
41
|
|
|
@@ -82,6 +83,23 @@ import { Field, SearchInput } from "@sableui/react"
|
|
|
82
83
|
<Field label="Search posts"><SearchInput defaultValue="roadmap" className="max-w-80" /></Field>
|
|
83
84
|
```
|
|
84
85
|
|
|
86
|
+
### Highlighting matches in the results
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
import { SearchInput, useMatchHighlight } from "@sableui/react"
|
|
90
|
+
|
|
91
|
+
const [q, setQ] = useState("")
|
|
92
|
+
const results = useMatchHighlight<HTMLUListElement>(q, { selector: "[data-title]" })
|
|
93
|
+
const shown = posts.filter((post) => post.title.toLowerCase().includes(q.trim().toLowerCase()))
|
|
94
|
+
|
|
95
|
+
<SearchInput value={q} onValueChange={setQ} placeholder="Search posts" />
|
|
96
|
+
<ul ref={results}>
|
|
97
|
+
{shown.map((post) => (
|
|
98
|
+
<li key={post.id}><span data-title>{post.title}</span></li>
|
|
99
|
+
))}
|
|
100
|
+
</ul>
|
|
101
|
+
```
|
|
102
|
+
|
|
85
103
|
### Disabled
|
|
86
104
|
|
|
87
105
|
```tsx
|
|
@@ -40,7 +40,7 @@ Use SegmentedBar when a stat card or row needs to show how a total divides into
|
|
|
40
40
|
|
|
41
41
|
## Tokens used
|
|
42
42
|
|
|
43
|
-
`tone-1`, `tone-2`, `tone-3`, `tone-info`, `primary`, `muted-foreground`, `success`, `tone-warning`, `destructive`
|
|
43
|
+
`tone-1`, `tone-2`, `tone-3`, `tone-info`, `primary`, `muted-foreground`, `success`, `tone-warning`, `destructive`, `destructive-mark`, `success-mark`, `tone-warning-mark`, `tone-info-mark`, `tone-1-mark`, `tone-2-mark`, `tone-3-mark`
|
|
44
44
|
|
|
45
45
|
## Motion
|
|
46
46
|
|
|
@@ -50,7 +50,7 @@ Use Select when users choose one value from a known, finite set. Use Combobox fo
|
|
|
50
50
|
|
|
51
51
|
## Tokens used
|
|
52
52
|
|
|
53
|
-
`
|
|
53
|
+
`field-border`, `field`, `foreground`, `ring`, `border`, `popover`, `popover-foreground`, `accent`, `accent-foreground`, `muted-foreground`
|
|
54
54
|
|
|
55
55
|
## Motion
|
|
56
56
|
|
|
@@ -15,6 +15,7 @@ Use Sidebar for persistent desktop navigation or application chrome outside the
|
|
|
15
15
|
- Do: Use it for stable app destinations that should remain visible while content changes.
|
|
16
16
|
- Do: Keep item labels predictable and active state obvious.
|
|
17
17
|
- Do: Set surface="page" when a full-width top bar sits above the rail. A theme's tinted or dark rail is for a full-height rail that frames the app.
|
|
18
|
+
- Do: Keep surface="rail" inside AppShell frame="inset": the rail's tint becomes the ground the main panel floats on. Do not add a border-r class back — the gap is the divider.
|
|
18
19
|
- Don't: Do not use Sidebar for page-local settings, filters, or temporary action groups.
|
|
19
20
|
- Don't: Do not put page content in it. It is fixed-width chrome OUTSIDE the content grid, so anything in it is exempt from the page's measure and rhythm.
|
|
20
21
|
|
|
@@ -40,7 +41,7 @@ Use Sidebar for persistent desktop navigation or application chrome outside the
|
|
|
40
41
|
| collapsed | boolean | false | Collapse the rail to an icon-only width (--sidebar-width-collapsed). Items hide their label + badge and reveal the label in a hover tooltip; the content area reflows. Controlled — wire a toggle from app state. Read the state in custom header/footer content via useSidebar(). |
|
|
41
42
|
| icons | boolean | true | Render the leading icon on each SidebarItem. Set false for a text-only rail. Ignored while collapsed (icon-only by definition). |
|
|
42
43
|
| variant | "app" \| "inline" | "app" | Where the rail lives. "app" is the page's chrome column — sticky, full viewport height, hidden below lg where AppHeader + BottomNav take over. "inline" is always visible and fills its parent's height, for a rail inside a bounded frame (a nested shell, an embedded preview). Use it instead of overriding the layout with !important classes. |
|
|
43
|
-
| surface | "rail" \| "page" | "rail" | Which surface the rail is painted on. "rail" is its own --sidebar-* surface with a border — right for a full-height rail that frames the app, which a theme may tint or paint dark. "page" uses the page's surface and ink with no border — use it when a full-width header sits above the rail, where a tinted column starting under a page-coloured bar reads as pasted on. Use it instead of overriding bg-/text- classes, which the rail's re-pointed tokens defeat. |
|
|
44
|
+
| surface | "rail" \| "page" | "rail" | Which surface the rail is painted on. "rail" is its own --sidebar-* surface with a border — right for a full-height rail that frames the app, which a theme may tint or paint dark. "page" uses the page's surface and ink with no border — use it when a full-width header sits above the rail, where a tinted column starting under a page-coloured bar reads as pasted on. Use it instead of overriding bg-/text- classes, which the rail's re-pointed tokens defeat. In AppShell's sidebar slot with frame="inset", the rail's surface is also the shell's ground: from lg a "rail" rail drops its border (the gap around the main panel divides them) and either surface stretches to the shell's body row instead of sizing to the viewport. AppShell signals this to its sidebar slot only, so a Sidebar elsewhere in the page is unaffected. |
|
|
44
45
|
| motion | "full" \| "subtle" \| "off" | "full" | How much motion this component uses: `full` inherits the app's policy, `subtle` keeps feedback and drops the collapse ease and the current-page glide, `off` stills it. It can only turn motion down — it never overrides a reader's reduce-motion setting. |
|
|
45
46
|
|
|
46
47
|
## Variants
|
|
@@ -49,7 +50,7 @@ Use Sidebar for persistent desktop navigation or application chrome outside the
|
|
|
49
50
|
|
|
50
51
|
## Tokens used
|
|
51
52
|
|
|
52
|
-
`sidebar`, `sidebar-foreground`, `sidebar-border`, `sidebar-accent`, `sidebar-accent-foreground`, `sidebar-ring`
|
|
53
|
+
`sidebar`, `sidebar-foreground`, `sidebar-border`, `sidebar-accent`, `sidebar-accent-foreground`, `sidebar-ring`, `shell-ground`
|
|
53
54
|
|
|
54
55
|
## Motion
|
|
55
56
|
|
|
@@ -36,7 +36,7 @@ Use Sparkline next to a number to show where it has been — a KPI's last 30 day
|
|
|
36
36
|
|
|
37
37
|
## Tokens used
|
|
38
38
|
|
|
39
|
-
`primary`, `tone-1`, `tone-2`, `tone-3`, `tone-info`, `tone-warning`, `muted-foreground`, `success`, `destructive`
|
|
39
|
+
`primary`, `tone-1`, `tone-2`, `tone-3`, `tone-info`, `tone-warning`, `muted-foreground`, `success`, `destructive`, `destructive-mark`, `success-mark`, `tone-warning-mark`, `tone-info-mark`, `tone-1-mark`, `tone-2-mark`, `tone-3-mark`
|
|
40
40
|
|
|
41
41
|
## Motion
|
|
42
42
|
|
|
@@ -39,7 +39,7 @@ Use StatusDot as a compact visual state cue next to text, avatars, rows, or labe
|
|
|
39
39
|
|
|
40
40
|
## Tokens used
|
|
41
41
|
|
|
42
|
-
`palette-dot`, `muted-foreground`, `tone-3`, `success`, `tone-warning`, `tone-info`, `tone-1`, `tone-2`, `destructive`
|
|
42
|
+
`palette-dot`, `muted-foreground`, `tone-3`, `success`, `tone-warning`, `tone-info`, `tone-1`, `tone-2`, `destructive`, `destructive-mark`, `success-mark`, `tone-warning-mark`, `tone-info-mark`, `tone-1-mark`, `tone-2-mark`, `tone-3-mark`
|
|
43
43
|
|
|
44
44
|
## Accessibility
|
|
45
45
|
|
|
@@ -51,7 +51,7 @@ Use Stepper above or beside a flow that is split into a known, small number of n
|
|
|
51
51
|
|
|
52
52
|
## Tokens used
|
|
53
53
|
|
|
54
|
-
`primary`, `primary-foreground`, `background`, `foreground`, `muted-foreground`, `border-strong`, `destructive`, `destructive-foreground`, `ring`
|
|
54
|
+
`primary`, `primary-foreground`, `background`, `foreground`, `muted-foreground`, `border-strong`, `destructive`, `destructive-foreground`, `ring`, `destructive-mark`
|
|
55
55
|
|
|
56
56
|
## Motion
|
|
57
57
|
|
package/llms/components/table.md
CHANGED
|
@@ -36,8 +36,8 @@ Use Table for structured data with consistent columns and rows. Use DataTable wh
|
|
|
36
36
|
| TableBody | ComponentPropsWithRef<"tbody"> | The data row group (tbody). |
|
|
37
37
|
| TableFooter | ComponentPropsWithRef<"tfoot"> | Summary row group (tfoot) with a muted fill. |
|
|
38
38
|
| TableRow | ComponentPropsWithRef<"tr"> | A row (tr) — hairline bottom border, hover lift, and a selected state via the data-selected attribute. |
|
|
39
|
-
| TableHead | ComponentPropsWithRef<"th"> | A column header cell (th) in muted label styling. |
|
|
40
|
-
| TableCell | ComponentPropsWithRef<"td"> | A data cell (td). |
|
|
39
|
+
| TableHead | ComponentPropsWithRef<"th"> & { numeric?: boolean } | A column header cell (th) in muted label styling. `numeric` marks a number column: end-aligned, tabular figures — set it on the column's cells too. |
|
|
40
|
+
| TableCell | ComponentPropsWithRef<"td"> & { numeric?: boolean } | A data cell (td). `numeric` end-aligns it with tabular figures, matching its column's header. |
|
|
41
41
|
| TableCaption | ComponentPropsWithRef<"caption"> | Accessible description of the table (caption), muted. |
|
|
42
42
|
|
|
43
43
|
## Props
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Status:** stable
|
|
4
4
|
|
|
5
|
-
Styled native multi-line text control. Soft-square,
|
|
5
|
+
Styled native multi-line text control. Soft-square, the theme's field surface, --ring focus, and an aria-invalid destructive error state.
|
|
6
6
|
|
|
7
7
|
**Keywords:** textarea, multi line input, form, text
|
|
8
8
|
|
|
@@ -31,7 +31,7 @@ Use Textarea for multi-line freeform text entry such as notes, descriptions, or
|
|
|
31
31
|
|
|
32
32
|
## Tokens used
|
|
33
33
|
|
|
34
|
-
`
|
|
34
|
+
`field-border`, `field`, `foreground`, `muted-foreground`, `ring`, `destructive`
|
|
35
35
|
|
|
36
36
|
## Accessibility
|
|
37
37
|
|
|
@@ -30,6 +30,7 @@ Sable's components ship accessible behavior from Base UI. These rules cover what
|
|
|
30
30
|
- **Never:** Color as the only signal (a red border with no message). **Instead:** Color plus text or an icon. Roughly 1 in 12 men cannot tell red from green.
|
|
31
31
|
- **Never:** Opacity on the focus ring. **Instead:** ring-ring at full opacity; tune the token in the theme. A faded ring loses the contrast the theme tested. *Enforced by sable-lint: faded-focus-ring.*
|
|
32
32
|
- **Never:** A brand or status fill retuned under its old label — dark ink on a bright red that passes 4.5:1 at APCA Lc 42. **Instead:** A label that clears 4.5:1 and APCA Lc 60 in both modes. Move the fill's lightness, not its hue, keeping the ink its colour takes. A status colour on a surface is its own token (`--destructive-text`), so the fill can move freely. The ratio alone passes labels that read muddy. A deliberate brand pair is allowed with a recorded reason (lint disable or preset exceptions). *Enforced by sable-lint: label-contrast.*
|
|
33
|
+
- **Never:** A label fill painted on a mark that carries no text — a meter, a segmented bar, a status dot, a chart series, a soft tint. **Instead:** The colour's `-mark` token (`bg-success-mark`, `bg-tone-warning-mark/15`): the same hue lifted and saturated, held to 2:1 on the page. Text contrast is for text; a graphic owes visibility, and 3:1 (WCAG 1.4.11) only when it is the sole carrier of its meaning. A fill is pinned dark enough for a white label. On a bar or dot with nothing to label, that darkness only reads as mud: a brown warning, a forest-green success.
|
|
33
34
|
- **Never:** Blocking paste, or type="number" for codes and card numbers. **Instead:** type="text" inputMode="numeric" with the right autocomplete. Blocking paste breaks password managers; number inputs scroll-change identifiers.
|
|
34
35
|
- **Never:** forced-color-adjust: none to 'fix' high-contrast mode. **Instead:** Let the system colors apply; verify the result. It removes the user's chosen colors exactly where they need them.
|
|
35
36
|
- **Never:** outline: none without a replacement. **Instead:** focus-visible:ring-2 ring-ring. Keyboard users lose their place.
|
|
@@ -24,7 +24,7 @@ Which token to reach for, and what it is most often confused with. Generated fro
|
|
|
24
24
|
- **Not** `border-strong`. Reach for `border-strong` when the line carries *structure* (a grid rule, a table divider, a section separator) and for `border` when it merely bounds a control.
|
|
25
25
|
- **`border-strong`** — A structural divider. Visibly stronger than `border`. *Use for:* Grid lines, table rules, separators between major sections.
|
|
26
26
|
- **Not** `border`. If removing the line would make the layout ambiguous, it is structural and belongs here.
|
|
27
|
-
- **`input`** — The outline of a form control specifically. *Use for:* Text inputs, textareas and selects. Not the edge of a checkbox, radio or switch — that is `control-border`.
|
|
27
|
+
- **`input`** — The outline of a form control specifically. *Use for:* Text inputs, textareas and selects (through `field-border`, which derives from it). Not the edge of a checkbox, radio or switch — that is `control-border`.
|
|
28
28
|
- **Not** `border`. They are often the same value, but a theme is entitled to make form controls read differently from other chrome, and only this token gives it the hook.
|
|
29
29
|
- **`control-border`** — The resting edge of a control whose outline is the whole control. Held to 3:1 (WCAG 1.4.11) on every surface. *Use for:* An unchecked checkbox, an unselected radio, an off switch track, a selection card's check or radio mark — anywhere removing the edge would make the control disappear.
|
|
30
30
|
- **Not** `input`. A text field is also found by its fill, caret and placeholder, so its outline may stay quiet; a checkbox has nothing else, and at `input`'s strength it measures about 1.4:1.
|
|
@@ -314,7 +314,7 @@ Which token to reach for, and what it is most often confused with. Generated fro
|
|
|
314
314
|
- **`type-mono-sm-tracking`** — The monospace family: mono-xl through mono-sm, plus mono-caption. *Use for:* Code, identifiers, hashes, keyboard keys, and any figure where digits must align in a column.
|
|
315
315
|
- **Not** the sans tiers for numeric data. Proportional digits make a column of numbers ragged; that is what `text-ui-num` solves in chrome and mono solves on a page.
|
|
316
316
|
|
|
317
|
-
### derived (
|
|
317
|
+
### derived (20)
|
|
318
318
|
|
|
319
319
|
- **`canvas`** — The WORK surface — the artboard, the document being edited. *Use for:* Behind the thing the tool operates on. `WorkspaceCanvas` uses it.
|
|
320
320
|
- **Not** `background`. The thing being edited is not the page behind the UI, and collapsing the two makes the document indistinguishable from its chrome.
|
|
@@ -336,6 +336,26 @@ Which token to reach for, and what it is most often confused with. Generated fro
|
|
|
336
336
|
- **Not** `hairline`, when the line would otherwise disappear against what it bounds.
|
|
337
337
|
- **`border-floating`** — The edge of a floating surface. Fainter than `border`: the shadow carries the elevation. *Use for:* Every floating surface — popover, menu, select, tooltip, dialog, sheet, toast, a floating panel — as `border-border-floating` or `ring-border-floating`, together with `bg-popover` and a `shadow-md`+ shadow. Derived for every theme (a faint alpha of the foreground); a theme may tune it with `--theme-border-floating`.
|
|
338
338
|
- **Not** `border`. A full hairline plus a shadow stacks into a heavy outline around anything that floats. `border` is for resting edges: inputs, cards, badges.
|
|
339
|
+
- **`field`** — The fill of a text field: Input, Textarea, Select, Combobox, SearchInput, InputGroup, ChatComposer. *Use for:* Read by every field through its shell, so you rarely name it. Derived for every theme (`card`, an outlined field on the card); a theme fills its fields instead with `--theme-field: var(--muted)` and `--theme-field-border: transparent`, and every field changes at once. Name it only for a field-shaped surface of your own that must match.
|
|
340
|
+
- **Not** `card` or `muted` on a hand-built field. A field that paints `card` keeps its outline when the theme fills the rest, and one that paints `muted` stays filled when the theme outlines them.
|
|
341
|
+
- **`field-border`** — The outline of a text field. Derived from `input`; `transparent` in a theme with filled fields. *Use for:* With `field`, on the same field-shaped surfaces. Tune it with `--theme-field-border`.
|
|
342
|
+
- **Not** `input` on a text field. `input` stays the theme's outline colour for form chrome; this is the field's outline, which a filled theme turns off.
|
|
343
|
+
- **`shell-ground`** — The ground of an inset app frame: the rail and the gap around the raised main panel. *Use for:* Painted by `<AppShell frame="inset">` and the Sidebar in its slot; you rarely name it. Derived for every theme as one step off `sidebar` toward its ink, so the panel reads as lifted even where the rail is the page colour. Tune it with `--theme-shell-ground`.
|
|
344
|
+
- **Not** `sidebar` or `canvas` behind an inset panel. `sidebar` is the page colour in most themes, so the panel would sit on itself; `canvas` is a workspace's artboard, not app chrome.
|
|
345
|
+
- **`destructive-mark`** — `destructive` at graphic strength: the same hue lifted and saturated, for a mark that carries no text. *Use for:* A meter's or progress fill, a segmented bar, a status dot, a chart series, and the soft tint behind a badge or note (`bg-destructive-mark/15`). Held to 2:1 on the page — visibility, not a text ratio — because each of these sits beside text that says the same thing. Every bundled theme tunes its own; a preset sets `--theme-destructive-mark` or gets one derived from `destructive`.
|
|
346
|
+
- **Not** `bg-destructive` on a mark. The fill is pinned dark enough to carry a white label, so a meter or dot painted with it reads brown, forest or plum. And not for text — that is `text-destructive` — nor for a graphic that is the only carrier of its meaning, which owes 3:1 (WCAG 1.4.11): use the fill or add the text.
|
|
347
|
+
- **`success-mark`** — `success` at graphic strength: the same hue lifted and saturated, for a mark that carries no text. *Use for:* A meter's or progress fill, a segmented bar, a status dot, a chart series, and the soft tint behind a badge or note (`bg-success-mark/15`). Held to 2:1 on the page — visibility, not a text ratio — because each of these sits beside text that says the same thing. Every bundled theme tunes its own; a preset sets `--theme-success-mark` or gets one derived from `success`.
|
|
348
|
+
- **Not** `bg-success` on a mark. The fill is pinned dark enough to carry a white label, so a meter or dot painted with it reads brown, forest or plum. And not for text — that is `text-success` — nor for a graphic that is the only carrier of its meaning, which owes 3:1 (WCAG 1.4.11): use the fill or add the text.
|
|
349
|
+
- **`tone-warning-mark`** — `tone-warning` at graphic strength: the same hue lifted and saturated, for a mark that carries no text. *Use for:* A meter's or progress fill, a segmented bar, a status dot, a chart series, and the soft tint behind a badge or note (`bg-tone-warning-mark/15`). Held to 2:1 on the page — visibility, not a text ratio — because each of these sits beside text that says the same thing. Every bundled theme tunes its own; a preset sets `--theme-tone-warning-mark` or gets one derived from `tone-warning`.
|
|
350
|
+
- **Not** `bg-tone-warning` on a mark. The fill is pinned dark enough to carry a white label, so a meter or dot painted with it reads brown, forest or plum. And not for text — that is `text-tone-warning` — nor for a graphic that is the only carrier of its meaning, which owes 3:1 (WCAG 1.4.11): use the fill or add the text.
|
|
351
|
+
- **`tone-info-mark`** — `tone-info` at graphic strength: the same hue lifted and saturated, for a mark that carries no text. *Use for:* A meter's or progress fill, a segmented bar, a status dot, a chart series, and the soft tint behind a badge or note (`bg-tone-info-mark/15`). Held to 2:1 on the page — visibility, not a text ratio — because each of these sits beside text that says the same thing. Every bundled theme tunes its own; a preset sets `--theme-tone-info-mark` or gets one derived from `tone-info`.
|
|
352
|
+
- **Not** `bg-tone-info` on a mark. The fill is pinned dark enough to carry a white label, so a meter or dot painted with it reads brown, forest or plum. And not for text — that is `text-tone-info` — nor for a graphic that is the only carrier of its meaning, which owes 3:1 (WCAG 1.4.11): use the fill or add the text.
|
|
353
|
+
- **`tone-1-mark`** — `tone-1` at graphic strength: the same hue lifted and saturated, for a mark that carries no text. *Use for:* A meter's or progress fill, a segmented bar, a status dot, a chart series, and the soft tint behind a badge or note (`bg-tone-1-mark/15`). Held to 2:1 on the page — visibility, not a text ratio — because each of these sits beside text that says the same thing. Every bundled theme tunes its own; a preset sets `--theme-tone-1-mark` or gets one derived from `tone-1`.
|
|
354
|
+
- **Not** `bg-tone-1` on a mark. The fill is pinned dark enough to carry a white label, so a meter or dot painted with it reads brown, forest or plum. And not for text — that is `text-tone-1` — nor for a graphic that is the only carrier of its meaning, which owes 3:1 (WCAG 1.4.11): use the fill or add the text.
|
|
355
|
+
- **`tone-2-mark`** — `tone-2` at graphic strength: the same hue lifted and saturated, for a mark that carries no text. *Use for:* A meter's or progress fill, a segmented bar, a status dot, a chart series, and the soft tint behind a badge or note (`bg-tone-2-mark/15`). Held to 2:1 on the page — visibility, not a text ratio — because each of these sits beside text that says the same thing. Every bundled theme tunes its own; a preset sets `--theme-tone-2-mark` or gets one derived from `tone-2`.
|
|
356
|
+
- **Not** `bg-tone-2` on a mark. The fill is pinned dark enough to carry a white label, so a meter or dot painted with it reads brown, forest or plum. And not for text — that is `text-tone-2` — nor for a graphic that is the only carrier of its meaning, which owes 3:1 (WCAG 1.4.11): use the fill or add the text.
|
|
357
|
+
- **`tone-3-mark`** — `tone-3` at graphic strength: the same hue lifted and saturated, for a mark that carries no text. *Use for:* A meter's or progress fill, a segmented bar, a status dot, a chart series, and the soft tint behind a badge or note (`bg-tone-3-mark/15`). Held to 2:1 on the page — visibility, not a text ratio — because each of these sits beside text that says the same thing. Every bundled theme tunes its own; a preset sets `--theme-tone-3-mark` or gets one derived from `tone-3`.
|
|
358
|
+
- **Not** `bg-tone-3` on a mark. The fill is pinned dark enough to carry a white label, so a meter or dot painted with it reads brown, forest or plum. And not for text — that is `text-tone-3` — nor for a graphic that is the only carrier of its meaning, which owes 3:1 (WCAG 1.4.11): use the fill or add the text.
|
|
339
359
|
|
|
340
360
|
### Generated palette
|
|
341
361
|
|
|
@@ -230,7 +230,7 @@ The `@utility` and `@custom-variant` layer in `styles.css`: what each one is, wh
|
|
|
230
230
|
- **Instead of** A hand-written dash-offset animation with literal timing, which keeps animating, or keeps its delay, under reduced motion.
|
|
231
231
|
- `<Reveal><svg viewBox="0 0 100 100"><path className="motion-draw" pathLength="1" d="M10 50 L90 50" /></svg></Reveal>`
|
|
232
232
|
|
|
233
|
-
### helper (
|
|
233
|
+
### helper (6)
|
|
234
234
|
|
|
235
235
|
- **`hit-target`** — Grows an element's tap target to 44px with a transparent `::after`, without moving its layout by a pixel. `--hit-target-size` overrides the size. *Use for:* A deliberately small mark — a tag's remove ×, a tiny disclosure, a toast close — that must still meet the WCAG touch floor. Shrink it (`[--hit-target-size:32px]`) where targets sit side by side, or the later one steals the taps.
|
|
236
236
|
- **Instead of** Padding the glyph up (moves it off the row's grid and pushes siblings) or a bigger icon. Never on an `<input>` or other replaced element — pseudo-elements silently do nothing there; wrap it in a label.
|
|
@@ -246,4 +246,7 @@ The `@utility` and `@custom-variant` layer in `styles.css`: what each one is, wh
|
|
|
246
246
|
- `<a href="/terms" className="link-underline motion-interactive text-primary">terms</a>`
|
|
247
247
|
- **`checkerboard`** — The transparency checkerboard, painted from `--panel` and a derived darker step so it reads in both modes. `--checkerboard-size` (default 16px) and `--checkerboard-alt` tune it. *Use for:* Behind anything that can be translucent: a colour swatch with alpha, an image or artboard preview, an alpha slider track.
|
|
248
248
|
- **Instead of** A hand-rolled `repeating-conic-gradient` with two hardcoded greys. Deliberately not named `bg-checkerboard`, so `cn()` never merges it away against a real `bg-*` colour — you can layer a colour over it.
|
|
249
|
-
- `<div className="checkerboard [--checkerboard-size:8px] size-6 rounded-sm" />`
|
|
249
|
+
- `<div className="checkerboard [--checkerboard-size:8px] size-6 rounded-sm" />`
|
|
250
|
+
- **`texture-dither`** — A faint pixel / halftone dither field that dissolves: a small pseudo-random tile of squares painted in `--border-strong` and faded out by a gradient mask. Static, pure CSS, follows every theme and mode. Hooks: `--dither-fade` (direction, any linear-gradient side or angle, default `to bottom`), `--dither-size` (tile, default 48px = 2px squares) and `--dither-color` (default `var(--border-strong)`). *Use for:* Decoration at the top of a content area, a panel or a card, or behind an empty-state heading. Put it on its own `aria-hidden` element, `absolute -z-10` as the first child of a `relative isolate` parent, so the content after it paints on top with no z-index of its own. It sets `pointer-events: none` and no position, so it never takes layout or catches clicks.
|
|
251
|
+
- **Instead of** A hand-written `radial-gradient` dot grid (reads as graph paper, not dither), a PNG noise texture, a canvas, or hardcoded greys. Deliberately not named `bg-dither`, so `cn()` never merges it away against a real `bg-*` colour class.
|
|
252
|
+
- `<div className="relative isolate"><div aria-hidden className="texture-dither absolute inset-x-0 top-0 -z-10 h-40" /></div>`
|