@signal9/era-ui 30.8.0 → 31.0.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 +14 -0
- package/dist/ai/conversations/conversations-item.svelte +1 -1
- package/dist/ai/plan/plan-header.svelte +1 -1
- package/dist/ai/prompt-input/prompt-input-attachments.svelte +2 -6
- package/dist/ai/swarm/swarm-node.svelte +1 -1
- package/dist/ai/todo/todo-header.svelte +1 -1
- package/dist/ai/todo/todo-item.svelte +1 -1
- package/dist/ai/tool/tool-chip.svelte +1 -1
- package/dist/ai/web-preview/web-preview.svelte +1 -1
- package/dist/dev/audit/audits/wall-is-isotropic.js +1 -1
- package/dist/docs/css-utilities.js +7 -3
- package/dist/era-ui.css +1 -1
- package/dist/generated-docs/badge.md +1 -1
- package/dist/generated-docs/bar.md +22 -4
- package/dist/generated-docs/button.md +38 -4
- package/dist/generated-docs/card.md +35 -5
- package/dist/generated-docs/chip.md +16 -0
- package/dist/generated-docs/llms-full.txt +310 -49
- package/dist/generated-docs/llms.txt +4 -3
- package/dist/generated-docs/manifest.json +45 -21
- package/dist/generated-docs/meter.md +79 -1
- package/dist/generated-docs/nav.md +8 -1
- package/dist/generated-docs/separator.md +18 -0
- package/dist/generated-docs/utilities.json +32 -9
- package/dist/generated-docs/utilities.md +89 -30
- package/dist/styles/density.css +15 -25
- package/dist/styles/index.css +32 -27
- package/dist/ui/accordion/accordion-trigger.svelte +1 -1
- package/dist/ui/badge/badge.svelte +8 -2
- package/dist/ui/badge/badge.svelte.d.ts +1 -1
- package/dist/ui/bar/bar.svelte +95 -26
- package/dist/ui/bar/bar.svelte.d.ts +71 -31
- package/dist/ui/button/button.svelte +5 -0
- package/dist/ui/button/button.svelte.d.ts +2 -0
- package/dist/ui/button/variants.js +4 -9
- package/dist/ui/calendar/calendar-day.svelte +1 -1
- package/dist/ui/card/card.svelte +22 -9
- package/dist/ui/card/card.svelte.d.ts +19 -7
- package/dist/ui/chip/chip.svelte +5 -2
- package/dist/ui/chip/chip.svelte.d.ts +6 -6
- package/dist/ui/collapsible/collapsible-trigger.svelte +1 -1
- package/dist/ui/combobox/combobox-trigger.svelte +1 -1
- package/dist/ui/command/command-item.svelte +1 -1
- package/dist/ui/command/command-link-item.svelte +1 -1
- package/dist/ui/command/command-root.svelte +3 -5
- package/dist/ui/date-field/date-field-segment.svelte +1 -1
- package/dist/ui/date-picker/date-picker-day.svelte +1 -1
- package/dist/ui/date-picker/date-picker-segment.svelte +1 -1
- package/dist/ui/date-picker/date-picker-trigger.svelte +1 -1
- package/dist/ui/date-range-field/date-range-field-segment.svelte +1 -1
- package/dist/ui/date-range-picker/date-range-picker-day.svelte +1 -1
- package/dist/ui/date-range-picker/date-range-picker-segment.svelte +1 -1
- package/dist/ui/date-range-picker/date-range-picker-trigger.svelte +1 -1
- package/dist/ui/dialog/dialog-content.svelte +19 -1
- package/dist/ui/dropdown-menu/dropdown-menu-trigger.svelte +1 -1
- package/dist/ui/file-upload/file-upload.svelte +1 -1
- package/dist/ui/input/variants.d.ts +6 -6
- package/dist/ui/input/variants.js +2 -2
- package/dist/ui/kv/kv.svelte +1 -1
- package/dist/ui/menubar/menubar-root.svelte +1 -1
- package/dist/ui/menubar/menubar-trigger.svelte +1 -1
- package/dist/ui/nav/nav-bar.svelte +9 -4
- package/dist/ui/nav/nav-bar.svelte.d.ts +2 -1
- package/dist/ui/pane/pane-root.svelte +3 -12
- package/dist/ui/pane/pane-tab.svelte +1 -1
- package/dist/ui/select/select-trigger.svelte +1 -1
- package/dist/ui/slider/slider-thumb.svelte +1 -1
- package/dist/ui/step/step-summary.svelte +1 -1
- package/dist/ui/switch/switch.svelte +2 -2
- package/dist/ui/time-field/time-field-segment.svelte +1 -1
- package/dist/ui/time-range-field/time-range-field-segment.svelte +1 -1
- package/dist/ui/timeline/timeline-step.svelte +1 -1
- package/dist/ui/toggle-group/toggle-group-item.svelte +2 -2
- package/dist/ui/toggle-group/toggle-group-item.svelte.d.ts +6 -6
- package/dist/ui/toggle-group/toggle-group-root.svelte +1 -2
- package/dist/ui/toggle-group/toggle-group-root.svelte.d.ts +3 -3
- package/dist/ui/tooltip/tooltip-content.svelte +1 -1
- package/dist/ui/tree/tree-item.svelte +1 -1
- package/dist/ui/video-player/video-player.svelte +1 -1
- package/dist/utils/tw-merge-config.d.ts +3 -0
- package/dist/utils/tw-merge-config.js +4 -0
- package/package.json +4 -3
- package/skill/SKILL.md +17 -17
|
@@ -64,8 +64,9 @@ Classes, not components — they need no import beyond the stylesheet. Reach for
|
|
|
64
64
|
- `era-token-ink` — the ink centring for a token pill — a badge, a KV value, any short caps-or-digits label in a fixed-height box, CENTRED horizontally and with no icon sibling. For a left-aligned sentence-case label use era-label-ink; when an icon really must sit beside the text, see the note there.
|
|
65
65
|
- `era-label-ink` — the ink centring for a fixed-height control holding ONE line of sentence-case text and no icon — a menu item, a nav trigger, a button label. Never alongside `truncate` (the trimmed box becomes the clip).
|
|
66
66
|
- `glass-blur` — the backdrop blur for a floating panel (popover, dialog, taskbar) — it applies only inside a data-surface="glass" subtree and is inert elsewhere, so it is safe to leave on a panel that renders under every surface.
|
|
67
|
-
- `
|
|
67
|
+
- `tier-icon · tier-pill · tier-chip · tier-control · tier-bar` — BOUNDED GEOMETRY — height and radius are one decision.
|
|
68
68
|
- `h-line` — the height of one line of the element's own text — a skeleton standing in for a line, a spacer that must match a line box.
|
|
69
|
+
- `era-track-well` — instead of `shadow-well` on a track whose value is painted by a child that covers the box — a progress/meter/slider track, a custom gauge. For a well holding ordinary content, `shadow-well` is still right.
|
|
69
70
|
- `era-skeleton-pulse` — Skeleton's pulse, on the MOTION AXIS.
|
|
70
71
|
- `era-shimmer` — the in-progress text treatment — put it on a "working…" / "thinking…" label while a task streams, instead of a spinner beside the text.
|
|
71
72
|
- `era-collapse` — the height sweep for a bits-ui Collapsible.Content — put it on the Content element itself (it carries its own overflow: hidden).
|
|
@@ -86,12 +87,12 @@ Classes, not components — they need no import beyond the stylesheet. Reach for
|
|
|
86
87
|
- `bg-well · text-well · border-well · bg-elevated · text-elevated · border-elevated · bg-highlight · text-highlight · … (12 in all)` — Surface fills — bg-well is the surface's own resting fill (pairs with
|
|
87
88
|
- `p-gutter · px-gutter · py-gutter · gap-gutter · p-panel · px-panel · py-panel · gap-panel · … (24 in all)` — THE SPACING SCALE — one entry per token, from which Tailwind derives the
|
|
88
89
|
- `p-inset-pill · px-inset-pill · py-inset-pill · gap-inset-pill · p-inset-chip · px-inset-chip · py-inset-chip · gap-inset-chip · … (12 in all)` — text-symmetric content padding — (tier − text)/2, the inset that vertically centres body text in its tier; px-inset-control is a text button's side padding, p-inset-control a code block's.
|
|
89
|
-
- `p-icon-inset-pill · px-icon-inset-pill · py-icon-inset-pill · gap-icon-inset-pill · p-icon-inset-chip · px-icon-inset-chip · py-icon-inset-chip · gap-icon-inset-chip · … (
|
|
90
|
+
- `p-icon-inset-pill · px-icon-inset-pill · py-icon-inset-pill · gap-icon-inset-pill · p-icon-inset-chip · px-icon-inset-chip · py-icon-inset-chip · gap-icon-inset-chip · … (40 in all)` — the concentric inset for a nested pair — (h-container − h-child)/2, the gap that makes a child control sit evenly inside its container, and the radius step that keeps their corners concentric. Named for the pair it joins: gap-icon-inset-control seats an icon in a control.
|
|
90
91
|
- `p-glyph-icon · px-glyph-icon · py-glyph-icon · gap-glyph-icon · p-glyph-pill · px-glyph-pill · py-glyph-pill · gap-glyph-pill` — the glyph size for a tier — the INK inside the box, not the box (size-glyph-pill is the dismiss × in a pill, size-pill is the pill).
|
|
91
92
|
- `bg-field · text-field · border-field · bg-field-highlight · text-field-highlight · border-field-highlight` — the recessed field fill — bg-field is a text input's resting well, bg-field-highlight its focused/hovered face.
|
|
92
93
|
- `ease-base` — Motion — bare transition utilities default to the motion axis, so
|
|
93
94
|
- `bg-divider · text-divider · border-divider · bg-divider-faded · text-divider-faded · border-divider-faded · bg-background · text-background · … (66 in all)` — Surface divider colors: border-divider, bg-divider-faded, …
|
|
94
|
-
- `bg-fill · text-fill · border-fill · bg-link · text-link · border-link · bg-primary · text-primary · … (
|
|
95
|
+
- `bg-fill · text-fill · border-fill · bg-link · text-link · border-link · bg-primary · text-primary · … (39 in all)` — The standing pill fill — --era-fill, the latched counterpart of the
|
|
95
96
|
|
|
96
97
|
Full reference (what each emits, when to use it): `/utilities.md`. Machine-readable list: `/utilities.json`.
|
|
97
98
|
|
|
@@ -153,7 +154,7 @@ The CSS classes era ships alongside the components — links, ink-centred text,
|
|
|
153
154
|
|
|
154
155
|
## Overview
|
|
155
156
|
|
|
156
|
-
era's styling API is pure class names — write `
|
|
157
|
+
era's styling API is pure class names — write `tier-control px-gutter shadow`,
|
|
157
158
|
never the `h-(--era-h-control)` var-class spelling. Everything below rides along
|
|
158
159
|
with the stylesheet and needs no import:
|
|
159
160
|
|
|
@@ -162,7 +163,7 @@ import "@signal9/era-ui/css";
|
|
|
162
163
|
```
|
|
163
164
|
|
|
164
165
|
```svelte
|
|
165
|
-
<button class="
|
|
166
|
+
<button class="tier-control px-inset-control shadow text-body">era styled</button>
|
|
166
167
|
```
|
|
167
168
|
|
|
168
169
|
Alongside the `@utility` classes referenced below, era registers named theme
|
|
@@ -172,6 +173,7 @@ motion):
|
|
|
172
173
|
|
|
173
174
|
| Stock-looking class | What it resolves to |
|
|
174
175
|
|---|---|
|
|
176
|
+
| `tier-icon/pill/chip/control/bar` | indivisible bounded height + concentric radius |
|
|
175
177
|
| `rounded-icon/pill/chip/control/bar` | the concentric radius ladder (collapses on `data-corners="square"`) |
|
|
176
178
|
| `rounded-menu-item` | menu-row radius, concentric inside a `rounded-control` panel |
|
|
177
179
|
| `shadow` / `shadow-lg` | resting control edge / floating panel chrome, per surface |
|
|
@@ -197,10 +199,13 @@ The spacing names (`gutter`, `card`, `panel`, `content`, `menu`, `field`, the
|
|
|
197
199
|
`inset-*` and concentric `*-inset-*` insets, `glyph-*`) are registered as a
|
|
198
200
|
Tailwind spacing scale, so every prefix derives automatically: `p-`, `px-`,
|
|
199
201
|
`pt-`, `mt-`, `gap-`, `gap-x-`, `inset-`, `translate-`, and the rest. The TIER
|
|
200
|
-
names (`icon`, `pill`, `chip`, `control`, `bar`) are
|
|
202
|
+
names (`icon`, `pill`, `chip`, `control`, `bar`) are dimensions, not spacing, so
|
|
201
203
|
they are registered per prefix instead — `h-`, `w-`, `min-h-`, `min-w-` and
|
|
202
204
|
`size-` — and the two vocabularies deliberately share no word. Putting a tier
|
|
203
205
|
in the spacing scale would silently make `px-control` mean 24px of padding.
|
|
206
|
+
For chrome, use `tier-T`, which binds `h-T` and `rounded-T`; use the separate
|
|
207
|
+
dimension/radius names only for width, minimums, unbounded surfaces, or
|
|
208
|
+
asymmetric/docked corners.
|
|
204
209
|
|
|
205
210
|
The var form (`h-(--era-h-control)`) still works and is the escape hatch for a
|
|
206
211
|
token with no registered name — `--era-sp`, the press-sink offsets, anything
|
|
@@ -219,8 +224,9 @@ source uses it where a name exists.
|
|
|
219
224
|
| `era-token-ink` | the ink centring for a token pill — a badge, a KV value, any short caps-or-digits label in a fixed-height box, CENTRED horizontally and with no icon sibling. For a left-aligned sentence-case label use era-label-ink; when an icon really must sit beside the text, see the note there. |
|
|
220
225
|
| `era-label-ink` | the ink centring for a fixed-height control holding ONE line of sentence-case text and no icon — a menu item, a nav trigger, a button label. Never alongside `truncate` (the trimmed box becomes the clip). |
|
|
221
226
|
| `glass-blur` | the backdrop blur for a floating panel (popover, dialog, taskbar) — it applies only inside a data-surface="glass" subtree and is inert elsewhere, so it is safe to leave on a panel that renders under every surface. |
|
|
222
|
-
| `
|
|
227
|
+
| `tier-icon` `tier-pill` `tier-chip` `tier-control` `tier-bar` | — |
|
|
223
228
|
| `h-line` | the height of one line of the element's own text — a skeleton standing in for a line, a spacer that must match a line box. |
|
|
229
|
+
| `era-track-well` | instead of `shadow-well` on a track whose value is painted by a child that covers the box — a progress/meter/slider track, a custom gauge. For a well holding ordinary content, `shadow-well` is still right. |
|
|
224
230
|
| `era-skeleton-pulse` | — |
|
|
225
231
|
| `era-shimmer` | the in-progress text treatment — put it on a "working…" / "thinking…" label while a task streams, instead of a spinner beside the text. |
|
|
226
232
|
| `era-collapse` | the height sweep for a bits-ui Collapsible.Content — put it on the Content element itself (it carries its own overflow: hidden). |
|
|
@@ -241,12 +247,12 @@ source uses it where a name exists.
|
|
|
241
247
|
| `bg-well` `text-well` `border-well` `bg-elevated` `text-elevated` `border-elevated` `bg-highlight` `text-highlight` `border-highlight` `bg-overlay` `text-overlay` `border-overlay` | — |
|
|
242
248
|
| `p-gutter` `px-gutter` `py-gutter` `gap-gutter` `p-panel` `px-panel` `py-panel` `gap-panel` `p-card` `px-card` `py-card` `gap-card` `p-content` `px-content` `py-content` `gap-content` `p-menu` `px-menu` `py-menu` `gap-menu` `p-field` `px-field` `py-field` `gap-field` | — |
|
|
243
249
|
| `p-inset-pill` `px-inset-pill` `py-inset-pill` `gap-inset-pill` `p-inset-chip` `px-inset-chip` `py-inset-chip` `gap-inset-chip` `p-inset-control` `px-inset-control` `py-inset-control` `gap-inset-control` | text-symmetric content padding — (tier − text)/2, the inset that vertically centres body text in its tier; px-inset-control is a text button's side padding, p-inset-control a code block's. |
|
|
244
|
-
| `p-icon-inset-pill` `px-icon-inset-pill` `py-icon-inset-pill` `gap-icon-inset-pill` `p-icon-inset-chip` `px-icon-inset-chip` `py-icon-inset-chip` `gap-icon-inset-chip` `p-icon-inset-control` `px-icon-inset-control` `py-icon-inset-control` `gap-icon-inset-control` `p-icon-inset-bar` `px-icon-inset-bar` `py-icon-inset-bar` `gap-icon-inset-bar` `p-pill-inset-chip` `px-pill-inset-chip` `py-pill-inset-chip` `gap-pill-inset-chip` `p-pill-inset-control` `px-pill-inset-control` `py-pill-inset-control` `gap-pill-inset-control` `p-pill-inset-bar` `px-pill-inset-bar` `py-pill-inset-bar` `gap-pill-inset-bar` `p-chip-inset-control` `px-chip-inset-control` `py-chip-inset-control` `gap-chip-inset-control` `p-chip-inset-bar` `px-chip-inset-bar` `py-chip-inset-bar` `gap-chip-inset-bar` | the concentric inset for a nested pair — (h-container − h-child)/2, the gap that makes a child control sit evenly inside its container, and the radius step that keeps their corners concentric. Named for the pair it joins: gap-icon-inset-control seats an icon in a control. |
|
|
250
|
+
| `p-icon-inset-pill` `px-icon-inset-pill` `py-icon-inset-pill` `gap-icon-inset-pill` `p-icon-inset-chip` `px-icon-inset-chip` `py-icon-inset-chip` `gap-icon-inset-chip` `p-icon-inset-control` `px-icon-inset-control` `py-icon-inset-control` `gap-icon-inset-control` `p-icon-inset-bar` `px-icon-inset-bar` `py-icon-inset-bar` `gap-icon-inset-bar` `p-pill-inset-chip` `px-pill-inset-chip` `py-pill-inset-chip` `gap-pill-inset-chip` `p-pill-inset-control` `px-pill-inset-control` `py-pill-inset-control` `gap-pill-inset-control` `p-pill-inset-bar` `px-pill-inset-bar` `py-pill-inset-bar` `gap-pill-inset-bar` `p-chip-inset-control` `px-chip-inset-control` `py-chip-inset-control` `gap-chip-inset-control` `p-chip-inset-bar` `px-chip-inset-bar` `py-chip-inset-bar` `gap-chip-inset-bar` `p-control-inset-bar` `px-control-inset-bar` `py-control-inset-bar` `gap-control-inset-bar` | the concentric inset for a nested pair — (h-container − h-child)/2, the gap that makes a child control sit evenly inside its container, and the radius step that keeps their corners concentric. Named for the pair it joins: gap-icon-inset-control seats an icon in a control. |
|
|
245
251
|
| `p-glyph-icon` `px-glyph-icon` `py-glyph-icon` `gap-glyph-icon` `p-glyph-pill` `px-glyph-pill` `py-glyph-pill` `gap-glyph-pill` | the glyph size for a tier — the INK inside the box, not the box (size-glyph-pill is the dismiss × in a pill, size-pill is the pill). |
|
|
246
252
|
| `bg-field` `text-field` `border-field` `bg-field-highlight` `text-field-highlight` `border-field-highlight` | the recessed field fill — bg-field is a text input's resting well, bg-field-highlight its focused/hovered face. |
|
|
247
253
|
| `ease-base` | — |
|
|
248
254
|
| `bg-divider` `text-divider` `border-divider` `bg-divider-faded` `text-divider-faded` `border-divider-faded` `bg-background` `text-background` `border-background` `bg-foreground` `text-foreground` `border-foreground` `bg-1` `text-1` `border-1` `bg-2` `text-2` `border-2` `bg-3` `text-3` `border-3` `bg-4` `text-4` `border-4` `bg-5` `text-5` `border-5` `bg-6` `text-6` `border-6` `bg-7` `text-7` `border-7` `bg-8` `text-8` `border-8` `bg-9` `text-9` `border-9` `bg-10` `text-10` `border-10` `bg-11` `text-11` `border-11` `bg-12` `text-12` `border-12` `bg-border` `text-border` `border-border` `bg-surface` `text-surface` `border-surface` `bg-hover` `text-hover` `border-hover` `bg-fg` `text-fg` `border-fg` `bg-bright` `text-bright` `border-bright` `bg-muted` `text-muted` `border-muted` | — |
|
|
249
|
-
| `bg-fill` `text-fill` `border-fill` `bg-link` `text-link` `border-link` `bg-primary` `text-primary` `border-primary` `bg-primary-fg` `text-primary-fg` `border-primary-fg` `bg-primary-hover` `text-primary-hover` `border-primary-hover` `bg-destructive` `text-destructive` `border-destructive` `bg-destructive-fg` `text-destructive-fg` `border-destructive-fg` `bg-success` `text-success` `border-success` `bg-success-fg` `text-success-fg` `border-success-fg` `bg-warning` `text-warning` `border-warning` `bg-warning-fg` `text-warning-fg` `border-warning-fg` | — |
|
|
255
|
+
| `bg-fill` `text-fill` `border-fill` `bg-link` `text-link` `border-link` `bg-primary` `text-primary` `border-primary` `bg-primary-fg` `text-primary-fg` `border-primary-fg` `bg-primary-hover` `text-primary-hover` `border-primary-hover` `bg-destructive` `text-destructive` `border-destructive` `bg-destructive-fg` `text-destructive-fg` `border-destructive-fg` `bg-success` `text-success` `border-success` `bg-success-fg` `text-success-fg` `border-success-fg` `bg-warning` `text-warning` `border-warning` `bg-warning-fg` `text-warning-fg` `border-warning-fg` `bg-info` `text-info` `border-info` `bg-info-fg` `text-info-fg` `border-info-fg` | — |
|
|
250
256
|
|
|
251
257
|
## era-interactive
|
|
252
258
|
|
|
@@ -628,35 +634,42 @@ Declared in `index.css`.
|
|
|
628
634
|
}
|
|
629
635
|
```
|
|
630
636
|
|
|
631
|
-
##
|
|
637
|
+
## tier-icon · tier-pill · tier-chip · tier-control · tier-bar
|
|
632
638
|
|
|
633
|
-
|
|
639
|
+
BOUNDED GEOMETRY — height and radius are one decision.
|
|
634
640
|
|
|
635
|
-
|
|
641
|
+
A tier is a geometric type, not two classes a caller must remember to keep in
|
|
642
|
+
sync. `tier-control` establishes h-control AND rd-control; the radius ladder
|
|
643
|
+
then guarantees rd_outer − rd_inner = (h_outer − h_inner)/2 for every pair.
|
|
644
|
+
Width remains the component's decision: a row stretches, a button adds
|
|
645
|
+
min-w-control, and a square control adds w-control.
|
|
636
646
|
|
|
637
|
-
|
|
638
|
-
the gutter therefore takes the container's radius MINUS the gutter — and no
|
|
639
|
-
tier radius equals that at more than one density, which is why reaching for
|
|
640
|
-
`rounded-control` and hoping looks wrong: in a control-radius pane the row and
|
|
641
|
-
the pane end up with identical curvature separated by 5px of gap, two arcs at
|
|
642
|
-
one corner with no relationship.
|
|
647
|
+
Declared in `index.css`.
|
|
643
648
|
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
649
|
+
```css
|
|
650
|
+
@utility tier-icon {
|
|
651
|
+
height: var(--era-h-icon);
|
|
652
|
+
border-radius: var(--era-rd-icon);
|
|
653
|
+
}
|
|
647
654
|
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
rd-bar − gap, which IS rd-control (control-inset-bar is the gutter), and the
|
|
653
|
-
palette's geometry is unchanged by this.
|
|
655
|
+
@utility tier-pill {
|
|
656
|
+
height: var(--era-h-pill);
|
|
657
|
+
border-radius: var(--era-rd-pill);
|
|
658
|
+
}
|
|
654
659
|
|
|
655
|
-
|
|
660
|
+
@utility tier-chip {
|
|
661
|
+
height: var(--era-h-chip);
|
|
662
|
+
border-radius: var(--era-rd-chip);
|
|
663
|
+
}
|
|
656
664
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
border-radius:
|
|
665
|
+
@utility tier-control {
|
|
666
|
+
height: var(--era-h-control);
|
|
667
|
+
border-radius: var(--era-rd-control);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
@utility tier-bar {
|
|
671
|
+
height: var(--era-h-bar);
|
|
672
|
+
border-radius: var(--era-rd-bar);
|
|
660
673
|
}
|
|
661
674
|
```
|
|
662
675
|
|
|
@@ -681,6 +694,50 @@ Declared in `index.css`.
|
|
|
681
694
|
}
|
|
682
695
|
```
|
|
683
696
|
|
|
697
|
+
## era-track-well
|
|
698
|
+
|
|
699
|
+
**Use it for:** instead of `shadow-well` on a track whose value is painted by a child that covers the box — a progress/meter/slider track, a custom gauge. For a well holding ordinary content, `shadow-well` is still right.
|
|
700
|
+
|
|
701
|
+
A WELL THAT SURVIVES BEING FILLED.
|
|
702
|
+
|
|
703
|
+
`shadow-well` is an INSET shadow, and an inset shadow belongs to the
|
|
704
|
+
element's background layer — it paints under the element's own descendants.
|
|
705
|
+
That is invisible on a well holding text (a checkbox, a code block: the
|
|
706
|
+
chrome runs around the content) and wrong the moment something paints the
|
|
707
|
+
whole box. Meter, Progress and the Slider track all do exactly that: an
|
|
708
|
+
opaque child, `translateX`-ed to the value. So the well survived only where
|
|
709
|
+
the track was EMPTY — a half-full meter on bevel had a chisel to the right
|
|
710
|
+
of the value and none to the left, which reads as a hole with a sticker
|
|
711
|
+
over it rather than a level inside a well.
|
|
712
|
+
|
|
713
|
+
The fix is painting order, not geometry: the same `--era-shadow-well` on a
|
|
714
|
+
pseudo-element that is the element's LAST child, so it lands above the fill.
|
|
715
|
+
The fill still spans the full box — nothing is inset, no radius is
|
|
716
|
+
re-derived, and 0% and 100% keep their exact ends. The `position: relative`
|
|
717
|
+
is load-bearing (the overlay resolves against this box) and `inherit` on the
|
|
718
|
+
radius keeps it honest under `data-corners="square"`.
|
|
719
|
+
|
|
720
|
+
Surface-agnostic on purpose. It reads the same token every well reads, so
|
|
721
|
+
glass's hairline rim is restored by the same line that restores bevel's
|
|
722
|
+
chisel, and flat — where the token is `none` — renders exactly as before.
|
|
723
|
+
Reported against bevel by a consumer; it was never a bevel bug.
|
|
724
|
+
|
|
725
|
+
Declared in `index.css`.
|
|
726
|
+
|
|
727
|
+
```css
|
|
728
|
+
@utility era-track-well {
|
|
729
|
+
position: relative;
|
|
730
|
+
&::after {
|
|
731
|
+
content: '';
|
|
732
|
+
position: absolute;
|
|
733
|
+
inset: 0;
|
|
734
|
+
border-radius: inherit;
|
|
735
|
+
box-shadow: var(--era-shadow-well);
|
|
736
|
+
pointer-events: none;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
```
|
|
740
|
+
|
|
684
741
|
## era-skeleton-pulse
|
|
685
742
|
|
|
686
743
|
Skeleton's pulse, on the MOTION AXIS.
|
|
@@ -1170,7 +1227,7 @@ Declared in `index.css`.
|
|
|
1170
1227
|
}
|
|
1171
1228
|
```
|
|
1172
1229
|
|
|
1173
|
-
## p-icon-inset-pill · px-icon-inset-pill · py-icon-inset-pill · gap-icon-inset-pill · p-icon-inset-chip · px-icon-inset-chip · py-icon-inset-chip · gap-icon-inset-chip · … (
|
|
1230
|
+
## p-icon-inset-pill · px-icon-inset-pill · py-icon-inset-pill · gap-icon-inset-pill · p-icon-inset-chip · px-icon-inset-chip · py-icon-inset-chip · gap-icon-inset-chip · … (40 in all)
|
|
1174
1231
|
|
|
1175
1232
|
**Use it for:** the concentric inset for a nested pair — (h-container − h-child)/2, the gap that makes a child control sit evenly inside its container, and the radius step that keeps their corners concentric. Named for the pair it joins: gap-icon-inset-control seats an icon in a control.
|
|
1176
1233
|
|
|
@@ -1187,6 +1244,7 @@ Declared in `index.css`.
|
|
|
1187
1244
|
--spacing-pill-inset-bar: var(--era-pill-inset-bar);
|
|
1188
1245
|
--spacing-chip-inset-control: var(--era-chip-inset-control);
|
|
1189
1246
|
--spacing-chip-inset-bar: var(--era-chip-inset-bar);
|
|
1247
|
+
--spacing-control-inset-bar: var(--era-control-inset-bar);
|
|
1190
1248
|
}
|
|
1191
1249
|
```
|
|
1192
1250
|
|
|
@@ -1265,7 +1323,7 @@ Declared in `index.css`.
|
|
|
1265
1323
|
}
|
|
1266
1324
|
```
|
|
1267
1325
|
|
|
1268
|
-
## bg-fill · text-fill · border-fill · bg-link · text-link · border-link · bg-primary · text-primary · … (
|
|
1326
|
+
## bg-fill · text-fill · border-fill · bg-link · text-link · border-link · bg-primary · text-primary · … (39 in all)
|
|
1269
1327
|
|
|
1270
1328
|
The standing pill fill — --era-fill, the latched counterpart of the
|
|
1271
1329
|
transient highlight. Surface-owned: a composing wash on flat/bevel, the
|
|
@@ -1286,6 +1344,8 @@ Declared in `index.css`.
|
|
|
1286
1344
|
--color-success-fg: var(--color-success-fg);
|
|
1287
1345
|
--color-warning: var(--color-warning);
|
|
1288
1346
|
--color-warning-fg: var(--color-warning-fg);
|
|
1347
|
+
--color-info: var(--color-info);
|
|
1348
|
+
--color-info-fg: var(--color-info-fg);
|
|
1289
1349
|
}
|
|
1290
1350
|
```
|
|
1291
1351
|
|
|
@@ -1456,7 +1516,7 @@ Inherits all props from `HTMLAttributes<HTMLSpanElement>`.
|
|
|
1456
1516
|
| Prop | Type | Default | Notes |
|
|
1457
1517
|
|------|------|---------|-------|
|
|
1458
1518
|
| `ref?` | `HTMLSpanElement \| null` | `null` | bindable |
|
|
1459
|
-
| `tone?` | `'default' \| 'accent' \| 'destructive' \| 'success' \| 'warning'` | `'default'` | — |
|
|
1519
|
+
| `tone?` | `'default' \| 'accent' \| 'destructive' \| 'success' \| 'warning' \| 'info'` | `'default'` | — |
|
|
1460
1520
|
| `lead?` | `Snippet` | — | Icon rendered BEFORE the label, outside it. Use this rather than putting
|
|
1461
1521
|
an icon in `children`: the label then gets its own box, which is the only
|
|
1462
1522
|
place era's ink centring can reach. |
|
|
@@ -1547,10 +1607,28 @@ Inherits all props from `HTMLAttributes<HTMLDivElement>`.
|
|
|
1547
1607
|
|------|------|---------|-------|
|
|
1548
1608
|
| `ref?` | `HTMLDivElement \| null` | `null` | bindable |
|
|
1549
1609
|
| `size?` | `'chip' \| 'control' \| 'bar'` | `'bar'` | Height tier (scales with density). Default `lg` — a full toolbar. |
|
|
1550
|
-
| `content?` | `
|
|
1551
|
-
stay concentric to them.
|
|
1552
|
-
the
|
|
1553
|
-
| `divider?` | `boolean` | `false` | The flush cap-a-panel chrome: outset
|
|
1610
|
+
| `content?` | `BarContent` | — | Tier of the controls inside — drives the bar's padding and gap so they
|
|
1611
|
+
stay concentric to them. Omit this for the next canonical rung, or name
|
|
1612
|
+
the actual tier when the contents are smaller. |
|
|
1613
|
+
| `divider?` | `boolean` | `false` | The flush cap-a-panel chrome: an outset rule below, and a rounded
|
|
1614
|
+
BOTTOM only — the top defers to the panel's own radius.
|
|
1615
|
+
THE BOTTOM RADIUS IS LOAD-BEARING FOR THE RULE. The divider is an
|
|
1616
|
+
outset `box-shadow`, so it follows the box's corners: the rounded
|
|
1617
|
+
bottom is what curves the line up at the ends and makes the bar read
|
|
1618
|
+
as a long pill. Overriding the radius therefore changes the RULE, not
|
|
1619
|
+
just the corners. Measured against `cn`:
|
|
1620
|
+
- `rounded-none` drops both — a square bar with a dead-straight rule.
|
|
1621
|
+
That is the intended square mode (an in-app Notes bar passes it).
|
|
1622
|
+
- `rounded-b-*` or `rounded-b-none` replaces the curve — this is the
|
|
1623
|
+
one that surprises, because the rule changes shape when the caller
|
|
1624
|
+
thought they were only squaring a corner.
|
|
1625
|
+
- `rounded-t-*` is SAFE: it wins against `rounded-t-none` and leaves
|
|
1626
|
+
`rounded-b-control` standing, so the curve survives.
|
|
1627
|
+
A consumer lost the curve this way. The coupling was already written
|
|
1628
|
+
down — on the variant, inside `<script module>`, where someone
|
|
1629
|
+
hovering this prop never reaches it. Docs are only as good as the
|
|
1630
|
+
place the reader is standing. |
|
|
1631
|
+
| `topology?` | `'nested' \| 'docked'` | `'nested'` | `docked` removes one or more exposed curves; strict radius nesting does not apply. |
|
|
1554
1632
|
| `children?` | `Snippet` | — | — |
|
|
1555
1633
|
|
|
1556
1634
|
<!-- end: bar -->
|
|
@@ -1580,7 +1658,7 @@ Inherits all props from `HTMLAttributes<HTMLElement>`.
|
|
|
1580
1658
|
|------|------|---------|-------|
|
|
1581
1659
|
| `ref?` | `HTMLElement \| null` | `null` | bindable |
|
|
1582
1660
|
| `size?` | `'chip' \| 'control' \| 'bar'` | `'bar'` | Height tier, exactly as Bar's — the geometry is Bar's, not a second copy. |
|
|
1583
|
-
| `content?` | `
|
|
1661
|
+
| `content?` | `BarContent` | — | Tier of the items inside, so the wall stays concentric to them. |
|
|
1584
1662
|
| `divider?` | `boolean` | `false` | Draw Bar's flush cap-a-panel rule beneath the bar. Off by default,
|
|
1585
1663
|
because a nav that sits in a page already has whatever separation the
|
|
1586
1664
|
layout gives it — and a link-variant nav in particular reads as text,
|
|
@@ -1605,6 +1683,13 @@ Inherits all props from `HTMLAnchorAttributes`.
|
|
|
1605
1683
|
drops the chrome entirely and renders running text, for a primary nav
|
|
1606
1684
|
that should read as links rather than a row of raised keycaps. Existing
|
|
1607
1685
|
bars are byte-identical. |
|
|
1686
|
+
| `currentCue?` | `'thickness' \| 'ink' \| 'none'` | `'thickness'` | WHAT MARKS THE CURRENT ITEM. `thickness` (default) is the three-state
|
|
1687
|
+
decoration — portable across every theme and font because it is one
|
|
1688
|
+
ink at three strengths. `ink` brightens the current item instead, and
|
|
1689
|
+
is theme-dependent by construction: era's default themes point
|
|
1690
|
+
--color-link at --color-bright, so its delta there is zero. `none`
|
|
1691
|
+
silences era's cue entirely, for a consumer painting their own.
|
|
1692
|
+
See navItemVariants above for the measurements behind each. |
|
|
1608
1693
|
| `current?` | `boolean` | `false` | Whether this item points at the page you are on.
|
|
1609
1694
|
There is deliberately no `active` prop beside this one. `active` would
|
|
1610
1695
|
be a second source of truth for one fact, and the two drift the moment
|
|
@@ -1644,14 +1729,47 @@ Inherits all props from `Button.RootProps`.
|
|
|
1644
1729
|
|
|
1645
1730
|
| Prop | Type | Default | Notes |
|
|
1646
1731
|
|------|------|---------|-------|
|
|
1647
|
-
| `tone?` | `'default' \| 'accent' \| 'destructive' \| 'success' \| 'warning'` | `'default'` | — |
|
|
1732
|
+
| `tone?` | `'default' \| 'accent' \| 'destructive' \| 'success' \| 'warning' \| 'info'` | `'default'` | — |
|
|
1648
1733
|
| `size?` | `'control' \| 'chip' \| 'pill' \| 'icon'` | `'control'` | — |
|
|
1649
1734
|
| `variant?` | `'filled' \| 'link'` | `'filled'` | — |
|
|
1650
1735
|
| `active?` | `boolean` | `false` | — |
|
|
1651
1736
|
| `icon?` | `boolean` | `false` | — |
|
|
1652
|
-
| `loading?` | `boolean` | `false` |
|
|
1653
|
-
|
|
1654
|
-
|
|
1737
|
+
| `loading?` | `boolean` | `false` | In flight: disables the button, sets `aria-busy`, and puts a spinner
|
|
1738
|
+
over the label.
|
|
1739
|
+
THE GEOMETRY DOES NOT MOVE. That is the requirement, not a detail. A
|
|
1740
|
+
button is loading because it was just CLICKED, so anything `loading`
|
|
1741
|
+
changes about the box moves the page under the pointer that is still
|
|
1742
|
+
on it — and a spinner PREPENDED to the label (what this used to do)
|
|
1743
|
+
costs an icon's width plus a gap, measured on a wrapping header row
|
|
1744
|
+
that reflowed everything beside it. A consumer hit exactly that and
|
|
1745
|
+
stopped using the prop, hand-rolling `disabled` + `aria-busy`
|
|
1746
|
+
instead, which is the report that produced this note.
|
|
1747
|
+
So the spinner is absolutely positioned and takes no part in the
|
|
1748
|
+
flex layout, and the label goes to `opacity-0` rather than being
|
|
1749
|
+
unmounted: the box that holds the width stays, and the text stays in
|
|
1750
|
+
the accessibility tree as the button's accessible name.
|
|
1751
|
+
The visible label is therefore HIDDEN in flight — the one thing this
|
|
1752
|
+
trades away, and the reason `loadingLabel` exists.
|
|
1753
|
+
IF YOU DO NOT WANT A SPINNER, use `busy`. Not showing one is a
|
|
1754
|
+
supported posture, not a legacy one — see that prop. |
|
|
1755
|
+
| `busy?` | `boolean` | `false` | In flight, WITHOUT a spinner: disables the button and sets `aria-busy`,
|
|
1756
|
+
and changes nothing else. The label stays visible and legible.
|
|
1757
|
+
This exists because "show a spinner" is a taste, not a requirement,
|
|
1758
|
+
and era had only one answer. A consumer whose house style is that
|
|
1759
|
+
spinners should not appear had to spell the posture out themselves —
|
|
1760
|
+
`disabled` plus a restated `aria-busy` — and rely on knowing that
|
|
1761
|
+
`restProps` spreads last, which is a real fact about this component
|
|
1762
|
+
that no reader should have to depend on. Two words for two postures
|
|
1763
|
+
is clearer than one word plus a workaround.
|
|
1764
|
+
`loading` implies this: it is `busy` plus the spinner and the hidden
|
|
1765
|
+
label. What you get from `busy` alone is a control that is visibly
|
|
1766
|
+
disabled (the era-interactive opacity) and announced as busy, with
|
|
1767
|
+
its geometry and its ink untouched — which is also why it needs no
|
|
1768
|
+
`loadingLabel`: nothing about the button changed except that you
|
|
1769
|
+
cannot press it.
|
|
1770
|
+
Reported by a consumer whose user asked for no spinners anywhere.
|
|
1771
|
+
They were right that a fix for the width shift did not answer it: a
|
|
1772
|
+
spinner that no longer moves its neighbours is still a spinner. |
|
|
1655
1773
|
| `loadingLabel?` | `string` | — | Screen-reader-only label announced while `loading` is true. |
|
|
1656
1774
|
| `lead?` | `Snippet` | — | Icon rendered BEFORE the label, outside it. Use this rather than putting
|
|
1657
1775
|
an icon in `children`: the label then gets its own box, which is the only
|
|
@@ -1689,6 +1807,7 @@ snippet's text cannot be read before it renders.
|
|
|
1689
1807
|
Only reaches the label when `lead`/`trail` give it its own box. Without
|
|
1690
1808
|
one the label is an anonymous flex item that no selector can address,
|
|
1691
1809
|
which is the whole reason those snippets exist. |
|
|
1810
|
+
| `topology?` | `'bounded' \| 'docked'` | `'bounded'` | `docked` joins this control to a neighbour and removes one or more curves. |
|
|
1692
1811
|
| `children?` | `Snippet` | — | — |
|
|
1693
1812
|
| `ref?` | `(forwarded)` | `null` | bindable |
|
|
1694
1813
|
|
|
@@ -1799,11 +1918,41 @@ Inherits all props from `ButtonBits`.
|
|
|
1799
1918
|
|------|------|---------|-------|
|
|
1800
1919
|
| `ref?` | `CardElement \| null` | `null` | bindable |
|
|
1801
1920
|
| `tone?` | `'elevated' \| 'surface' \| 'well' \| 'flat'` | `'elevated'` | Surface tier the card paints on.
|
|
1802
|
-
- `elevated` (default): the lifted surface
|
|
1803
|
-
|
|
1804
|
-
- `
|
|
1805
|
-
|
|
1806
|
-
- `
|
|
1921
|
+
- `elevated` (default): the lifted surface, with a resting shadow. Use
|
|
1922
|
+
on the page background.
|
|
1923
|
+
- `surface`: the base surface tier, no shadow. Use when nesting cards
|
|
1924
|
+
inside another elevated container.
|
|
1925
|
+
- `well`: recessed. For content the surrounding UI puts INTO the card —
|
|
1926
|
+
a tool's output pane, a transcript body — the container twin of a
|
|
1927
|
+
text field's fill.
|
|
1928
|
+
- `flat`: no background; only the rounded/padded shell. For grouping
|
|
1929
|
+
content visually without adding contrast.
|
|
1930
|
+
READ THE CLASSES AND THEY LOOK SWAPPED. They are not, and this is
|
|
1931
|
+
worth a sentence because a consumer read them, believed it, and
|
|
1932
|
+
shipped flat cards for months. `surface` paints `bg-well` and `well`
|
|
1933
|
+
paints `bg-field`, because era's utility names describe FILLS rather
|
|
1934
|
+
than tiers: `bg-well` is the surface's own resting fill (it is what a
|
|
1935
|
+
panel is painted with, and it pairs with `shadow-well` when you want
|
|
1936
|
+
recessed chrome), and `bg-field` is the recessed fill a text input
|
|
1937
|
+
sits in. The tone names are the tiers; the class names are the paints.
|
|
1938
|
+
A CARD THAT IS PRESSABLE SHOULD USUALLY BE `elevated`. Passing `href`
|
|
1939
|
+
or `onclick` turns on the interactive face — hover, focus, press — but
|
|
1940
|
+
it deliberately does NOT override the tier you asked for, so a
|
|
1941
|
+
`surface` link card does not get the raised tier's separation and can
|
|
1942
|
+
read flatter than the static cards around it. That combination was
|
|
1943
|
+
reported as a bug and it is a choice: a tone that silently changed
|
|
1944
|
+
under an event handler would be a worse one.
|
|
1945
|
+
HOW THE TIERS DIFFER IS SURFACE-DEPENDENT, so do not go looking for a
|
|
1946
|
+
fill difference on every surface. `base` mixes the elevated fill 6%
|
|
1947
|
+
toward `--color-bright` and adds a resting shadow, so there the tiers
|
|
1948
|
+
differ in COLOUR. `bevel` sets `--era-surface-bg-elevated` to
|
|
1949
|
+
`--era-surface-bg` outright — elevation is a chisel, not a tone, which
|
|
1950
|
+
is bevel's whole premise — so `surface` and `elevated` paint the
|
|
1951
|
+
IDENTICAL fill there and differ only in relief. A consumer measured
|
|
1952
|
+
exactly that on 30.8.0 bevel: both tones `oklch(0.195 0 none)` in dark,
|
|
1953
|
+
`0.863` in light, one variable, side by side. `glass` splits the tiers
|
|
1954
|
+
its own way again. So the tier is real on every surface; the thing
|
|
1955
|
+
carrying it is not always the fill. |
|
|
1807
1956
|
| `header?` | `Snippet` | — | Rendered above the body with a subtle divider. |
|
|
1808
1957
|
| `footer?` | `Snippet` | — | Rendered below the body with a subtle divider. |
|
|
1809
1958
|
| `children?` | `Snippet` | — | — |
|
|
@@ -1832,6 +1981,22 @@ Inherits all props from `HTMLAttributes<HTMLDivElement>`.
|
|
|
1832
1981
|
| `size?` | `'chip' \| 'pill'` | `'chip'` | `sm` (default) is the standalone free chip; `pill` is the smaller pill
|
|
1833
1982
|
that nests inside an md container (a select trigger, a button). |
|
|
1834
1983
|
| `ondismiss?` | `() => void` | — | — |
|
|
1984
|
+
| `dismissAs?` | `'button' \| 'span'` | `'button'` | What the dismiss control RENDERS AS. `button` (the default) is right
|
|
1985
|
+
for a free-standing chip. Use `span` when the chip lives inside
|
|
1986
|
+
another control.
|
|
1987
|
+
A <button> inside a <button> is not merely bad manners: it is invalid,
|
|
1988
|
+
and the HTML parser repairs it by CLOSING the outer control before the
|
|
1989
|
+
inner one. So the server's markup and the client's DOM disagree, Svelte
|
|
1990
|
+
discards the page's hydration and re-renders from scratch, and the
|
|
1991
|
+
chips briefly sit outside the trigger they belong to. era's own
|
|
1992
|
+
multi-select shipped exactly that (a Chip with `ondismiss` inside
|
|
1993
|
+
Select.Trigger) and logged node_invalid_placement_ssr on every load.
|
|
1994
|
+
`span` also drops the control from the accessibility tree rather than
|
|
1995
|
+
announcing a button inside a button — which is the honest description
|
|
1996
|
+
of what it is there: a pointer shortcut. The accessible way to remove
|
|
1997
|
+
a selection is the listbox itself, which is unaffected. Keyboard focus
|
|
1998
|
+
order is unchanged, because a nested button was never reachable in a
|
|
1999
|
+
sensible order anyway. |
|
|
1835
2000
|
| `lead?` | `Snippet` | — | Icon rendered BEFORE the label, outside it. Use this rather than putting
|
|
1836
2001
|
an icon in `children`: the label then gets its own box, which is the only
|
|
1837
2002
|
place era's ink centring can reach. |
|
|
@@ -1997,6 +2162,24 @@ Inherits all props from `Separator.RootProps`.
|
|
|
1997
2162
|
| Prop | Type | Default | Notes |
|
|
1998
2163
|
|------|------|---------|-------|
|
|
1999
2164
|
| `variant?` | `'line' \| 'slant'` | `'line'` | Use `slant` for inline dividers in breadcrumbs, titles, and compact metadata. |
|
|
2165
|
+
| `size?` | `keyof typeof SIZES` | — | Give a VERTICAL rule a height of its own, from the tier ladder, instead
|
|
2166
|
+
of stretching to whatever line it lands in. Ignored when horizontal.
|
|
2167
|
+
WHY YOU WOULD WANT IT. A stretched rule is a passenger: it has no
|
|
2168
|
+
intrinsic height, so it measures whatever its neighbours measure and
|
|
2169
|
+
contributes nothing back. That is right inside a Bar, whose height is
|
|
2170
|
+
already fixed — and it is why a rule in an auto-height row cannot hold
|
|
2171
|
+
that row's height steady. A consumer whose site header gained and lost
|
|
2172
|
+
a qualifier between pages watched the chrome resize, and pinned a
|
|
2173
|
+
`min-h-[calc(...)]` on the header to stop it. Sizing the rule removes
|
|
2174
|
+
that calc: it becomes the piece that stands the row up.
|
|
2175
|
+
(For the record, since the report named the wrong mechanism: a
|
|
2176
|
+
stretched rule does not GROW its row. Measured in an 18px auto-height
|
|
2177
|
+
row, adding one leaves the row at 18px and the rule resolves to 10px —
|
|
2178
|
+
the line minus its two gutter margins. It can only ever be shorter
|
|
2179
|
+
than the row it divides, which is the whole problem here.)
|
|
2180
|
+
A sized rule drops the gutter margins with the stretch: the height is
|
|
2181
|
+
now a deliberate number, and silently adding 2 x gutter to it would
|
|
2182
|
+
make it the one element on the page you cannot reason about. |
|
|
2000
2183
|
| `ref?` | `(forwarded)` | `null` | bindable |
|
|
2001
2184
|
|
|
2002
2185
|
## Usage
|
|
@@ -3910,12 +4093,90 @@ Inherits all props from `Meter.RootProps`.
|
|
|
3910
4093
|
|
|
3911
4094
|
| Prop | Type | Default | Notes |
|
|
3912
4095
|
|------|------|---------|-------|
|
|
3913
|
-
| `tone?` | `'default' \| 'accent' \| 'destructive' \| 'success' \| 'warning'` | `'default'` | The band this reading falls in. Tone is the fill's colour only — the
|
|
4096
|
+
| `tone?` | `'default' \| 'accent' \| 'destructive' \| 'success' \| 'warning' \| 'info'` | `'default'` | The band this reading falls in. Tone is the fill's colour only — the
|
|
3914
4097
|
track stays neutral, because the well belongs to the control and the
|
|
3915
4098
|
fill belongs to the value.
|
|
3916
4099
|
Tone carries no semantics on its own: a meter in the destructive band
|
|
3917
4100
|
still needs an accessible label saying what has run out. Pair it with
|
|
3918
4101
|
`aria-label` / a visible label, never rely on the hue alone. |
|
|
4102
|
+
| `threshold?` | `number` | — | A BOUNDARY INSIDE THE RANGE — in the same units as `value`, not a
|
|
4103
|
+
percentage. A quota with a soft limit before the hard one; a plan that
|
|
4104
|
+
includes 30 hours of the 50 it bills against; a temperature that is
|
|
4105
|
+
fine until it is not. The bar fills against `max`, and the mark says
|
|
4106
|
+
where the number the reader is actually deciding about sits.
|
|
4107
|
+
WHY THE MARK HAS NO COLOUR OF ITS OWN. It has to read against both
|
|
4108
|
+
sides of itself: over the empty track before the value reaches it, and
|
|
4109
|
+
over the fill afterwards. One token cannot do that — a colour tuned
|
|
4110
|
+
against the track disappears into the fill the moment the value
|
|
4111
|
+
crosses, which is exactly what a consumer hit hand-rolling this. So
|
|
4112
|
+
the mark is painted in the colour of the side it is NOT on: the fill's
|
|
4113
|
+
paint while the value is short of it, the track's fill once the value
|
|
4114
|
+
has passed. That contrast is not a new promise — it is the meter's
|
|
4115
|
+
own. A fill that did not stand out from its track would not be a
|
|
4116
|
+
meter, so borrowing the pair is the one choice that cannot be wrong in
|
|
4117
|
+
a theme, a tone, or a surface era has not seen.
|
|
4118
|
+
IT IS DECORATION, and silent on purpose. There is no `role` and
|
|
4119
|
+
nothing to announce: a screen reader gets `value`/`min`/`max` and the
|
|
4120
|
+
meter's own accessible name, and a boundary it cannot position adds
|
|
4121
|
+
nothing. If the threshold is part of the reading — it usually is —
|
|
4122
|
+
put the figure in `aria-label` and in a caption, where it is a number
|
|
4123
|
+
rather than a position.
|
|
4124
|
+
PASS `aria-valuetext` IF YOUR STORED UNIT IS NOT YOUR DISPLAYED ONE.
|
|
4125
|
+
`value`, `max` and `threshold` all have to sit in one unit for this
|
|
4126
|
+
arithmetic to work, and `aria-valuenow` is `value` verbatim — so a bar
|
|
4127
|
+
stored in minutes and read in hours announces "2640 of 3000", a figure
|
|
4128
|
+
the customer was never quoted. Converting the props is not available
|
|
4129
|
+
to you (it would move the mark), which makes `aria-valuetext` the only
|
|
4130
|
+
lever; it passes through `restProps` onto the same element. Reported
|
|
4131
|
+
by a consumer billing minutes and quoting hours.
|
|
4132
|
+
Outside `[min, max]` it renders NOTHING rather than clamping to an
|
|
4133
|
+
end, because a mark pinned to the edge of the bar would claim a
|
|
4134
|
+
boundary that is not in the range. |
|
|
4135
|
+
| `buffer?` | `number` | — | A REGION FROM `min` THAT IS A DIFFERENT KIND OF QUANTITY — painted
|
|
4136
|
+
under the fill, over the track, in the same units as `value`.
|
|
4137
|
+
The media player's buffered-progress shape, and the name is borrowed
|
|
4138
|
+
from it, but the reading is more general: some of the range is already
|
|
4139
|
+
accounted for. A plan whose first 30 of 50 hours are included in the
|
|
4140
|
+
monthly minimum is not "24 hours into a bill", it is "24 of 30 hours
|
|
4141
|
+
you have already paid for" — money spent against money that will be
|
|
4142
|
+
spent, which is a distinction the bar could not draw.
|
|
4143
|
+
NO COLOUR OF ITS OWN, for the reason `threshold` has none: it has to
|
|
4144
|
+
be legible over the track while never competing with the fill that
|
|
4145
|
+
crosses it, and a token tuned for one of those is wrong for the other.
|
|
4146
|
+
It is the fill's own paint at 30%, so it cannot be wrong in a theme,
|
|
4147
|
+
a tone or a surface era has not seen, and it is the same 30% Slider's
|
|
4148
|
+
`progress` has used for a seek bar's buffer since it shipped.
|
|
4149
|
+
UNDER the fill, so it disappears as the value consumes it. That is the
|
|
4150
|
+
reading, not a limitation: once you are past your included hours, the
|
|
4151
|
+
included region IS spent, and `threshold` is what goes on marking
|
|
4152
|
+
where it ended.
|
|
4153
|
+
CLAMPED to the range rather than dropped, which is where it differs
|
|
4154
|
+
from `threshold`. A region can be honestly truncated — a buffer past
|
|
4155
|
+
`max` means the whole visible bar is accounted for, and painting it
|
|
4156
|
+
all says exactly that. A point cannot: a mark pinned to the edge would
|
|
4157
|
+
claim a boundary that is not in the range, so an out-of-range
|
|
4158
|
+
`threshold` renders nothing instead.
|
|
4159
|
+
Silent, like the mark. `aria-valuetext` already carries the reading,
|
|
4160
|
+
and a second region a screen reader cannot position adds nothing.
|
|
4161
|
+
(Slider spells its equivalent `progress` and takes a 0–1 FRACTION.
|
|
4162
|
+
Here every positional prop is in the value's own units — `value`,
|
|
4163
|
+
`max`, `threshold`, `buffer` — because a component that mixed the two
|
|
4164
|
+
would be a bug generator. The names differ because on a Meter
|
|
4165
|
+
`progress` would be a synonym for `value`.) |
|
|
4166
|
+
| `start?` | `Snippet` | — | Captions under the two ends of the bar — what the range MEANS.
|
|
4167
|
+
A meter states a proportion and leaves the reader to work out what of.
|
|
4168
|
+
"0m used" on the left and "50h before approval" on the right is not
|
|
4169
|
+
decoration, it is the reading; every consumer of a bare meter ends up
|
|
4170
|
+
hand-rolling the same flex row underneath it, which is where this came
|
|
4171
|
+
from. `start` is left, `end` is right, either may stand alone.
|
|
4172
|
+
NOT ANNOUNCED. They are captions, so a screen reader gets the meter's
|
|
4173
|
+
value and its own `aria-label`, not these. If the range needs saying
|
|
4174
|
+
out loud, say it in the label too — the same rule `tone` carries.
|
|
4175
|
+
THE DOM IS UNCHANGED WITHOUT THEM. With neither snippet this renders
|
|
4176
|
+
exactly the element it always did, so `class` still lands on the track
|
|
4177
|
+
and the geometry audits still walk the same box. Passing one wraps the
|
|
4178
|
+
track in a column, and `class` still lands on the track. |
|
|
4179
|
+
| `end?` | `Snippet` | — | — |
|
|
3919
4180
|
| `ref?` | `(forwarded)` | `null` | bindable |
|
|
3920
4181
|
|
|
3921
4182
|
<!-- end: meter -->
|
|
@@ -102,8 +102,9 @@ Classes, not components — they need no import beyond the stylesheet. Reach for
|
|
|
102
102
|
- `era-token-ink` — the ink centring for a token pill — a badge, a KV value, any short caps-or-digits label in a fixed-height box, CENTRED horizontally and with no icon sibling. For a left-aligned sentence-case label use era-label-ink; when an icon really must sit beside the text, see the note there.
|
|
103
103
|
- `era-label-ink` — the ink centring for a fixed-height control holding ONE line of sentence-case text and no icon — a menu item, a nav trigger, a button label. Never alongside `truncate` (the trimmed box becomes the clip).
|
|
104
104
|
- `glass-blur` — the backdrop blur for a floating panel (popover, dialog, taskbar) — it applies only inside a data-surface="glass" subtree and is inert elsewhere, so it is safe to leave on a panel that renders under every surface.
|
|
105
|
-
- `
|
|
105
|
+
- `tier-icon · tier-pill · tier-chip · tier-control · tier-bar` — BOUNDED GEOMETRY — height and radius are one decision.
|
|
106
106
|
- `h-line` — the height of one line of the element's own text — a skeleton standing in for a line, a spacer that must match a line box.
|
|
107
|
+
- `era-track-well` — instead of `shadow-well` on a track whose value is painted by a child that covers the box — a progress/meter/slider track, a custom gauge. For a well holding ordinary content, `shadow-well` is still right.
|
|
107
108
|
- `era-skeleton-pulse` — Skeleton's pulse, on the MOTION AXIS.
|
|
108
109
|
- `era-shimmer` — the in-progress text treatment — put it on a "working…" / "thinking…" label while a task streams, instead of a spinner beside the text.
|
|
109
110
|
- `era-collapse` — the height sweep for a bits-ui Collapsible.Content — put it on the Content element itself (it carries its own overflow: hidden).
|
|
@@ -124,11 +125,11 @@ Classes, not components — they need no import beyond the stylesheet. Reach for
|
|
|
124
125
|
- `bg-well · text-well · border-well · bg-elevated · text-elevated · border-elevated · bg-highlight · text-highlight · … (12 in all)` — Surface fills — bg-well is the surface's own resting fill (pairs with
|
|
125
126
|
- `p-gutter · px-gutter · py-gutter · gap-gutter · p-panel · px-panel · py-panel · gap-panel · … (24 in all)` — THE SPACING SCALE — one entry per token, from which Tailwind derives the
|
|
126
127
|
- `p-inset-pill · px-inset-pill · py-inset-pill · gap-inset-pill · p-inset-chip · px-inset-chip · py-inset-chip · gap-inset-chip · … (12 in all)` — text-symmetric content padding — (tier − text)/2, the inset that vertically centres body text in its tier; px-inset-control is a text button's side padding, p-inset-control a code block's.
|
|
127
|
-
- `p-icon-inset-pill · px-icon-inset-pill · py-icon-inset-pill · gap-icon-inset-pill · p-icon-inset-chip · px-icon-inset-chip · py-icon-inset-chip · gap-icon-inset-chip · … (
|
|
128
|
+
- `p-icon-inset-pill · px-icon-inset-pill · py-icon-inset-pill · gap-icon-inset-pill · p-icon-inset-chip · px-icon-inset-chip · py-icon-inset-chip · gap-icon-inset-chip · … (40 in all)` — the concentric inset for a nested pair — (h-container − h-child)/2, the gap that makes a child control sit evenly inside its container, and the radius step that keeps their corners concentric. Named for the pair it joins: gap-icon-inset-control seats an icon in a control.
|
|
128
129
|
- `p-glyph-icon · px-glyph-icon · py-glyph-icon · gap-glyph-icon · p-glyph-pill · px-glyph-pill · py-glyph-pill · gap-glyph-pill` — the glyph size for a tier — the INK inside the box, not the box (size-glyph-pill is the dismiss × in a pill, size-pill is the pill).
|
|
129
130
|
- `bg-field · text-field · border-field · bg-field-highlight · text-field-highlight · border-field-highlight` — the recessed field fill — bg-field is a text input's resting well, bg-field-highlight its focused/hovered face.
|
|
130
131
|
- `ease-base` — Motion — bare transition utilities default to the motion axis, so
|
|
131
132
|
- `bg-divider · text-divider · border-divider · bg-divider-faded · text-divider-faded · border-divider-faded · bg-background · text-background · … (66 in all)` — Surface divider colors: border-divider, bg-divider-faded, …
|
|
132
|
-
- `bg-fill · text-fill · border-fill · bg-link · text-link · border-link · bg-primary · text-primary · … (
|
|
133
|
+
- `bg-fill · text-fill · border-fill · bg-link · text-link · border-link · bg-primary · text-primary · … (39 in all)` — The standing pill fill — --era-fill, the latched counterpart of the
|
|
133
134
|
|
|
134
135
|
Full reference (what each emits, when to use it): `{{ORIGIN}}/utilities.md`. Machine-readable list: `{{ORIGIN}}/utilities.json`.
|