@signal9/era-ui 30.7.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 +20 -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/alert-dialog/alert-dialog-action.svelte +2 -0
- package/dist/ui/alert-dialog/alert-dialog-cancel.svelte +2 -0
- 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 +38 -2
- package/dist/ui/button/button.svelte.d.ts +29 -0
- package/dist/ui/button/index.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-close.svelte +2 -0
- 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
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"slug": "utilities",
|
|
53
53
|
"title": "Utilities",
|
|
54
54
|
"summary": "The CSS classes era ships alongside the components — links, ink-centred text, shimmer, hidden scrollbars.",
|
|
55
|
-
"tokenEstimate":
|
|
55
|
+
"tokenEstimate": 13623,
|
|
56
56
|
"sections": [
|
|
57
57
|
"Overview",
|
|
58
58
|
"era-interactive",
|
|
@@ -65,8 +65,9 @@
|
|
|
65
65
|
"era-token-ink",
|
|
66
66
|
"era-label-ink",
|
|
67
67
|
"glass-blur",
|
|
68
|
-
"
|
|
68
|
+
"tier-icon · tier-pill · tier-chip · tier-control · tier-bar",
|
|
69
69
|
"h-line",
|
|
70
|
+
"era-track-well",
|
|
70
71
|
"era-skeleton-pulse",
|
|
71
72
|
"era-shimmer",
|
|
72
73
|
"era-collapse",
|
|
@@ -87,12 +88,12 @@
|
|
|
87
88
|
"bg-well · text-well · border-well · bg-elevated · text-elevated · border-elevated · bg-highlight · text-highlight · … (12 in all)",
|
|
88
89
|
"p-gutter · px-gutter · py-gutter · gap-gutter · p-panel · px-panel · py-panel · gap-panel · … (24 in all)",
|
|
89
90
|
"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)",
|
|
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 · … (
|
|
91
|
+
"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)",
|
|
91
92
|
"p-glyph-icon · px-glyph-icon · py-glyph-icon · gap-glyph-icon · p-glyph-pill · px-glyph-pill · py-glyph-pill · gap-glyph-pill",
|
|
92
93
|
"bg-field · text-field · border-field · bg-field-highlight · text-field-highlight · border-field-highlight",
|
|
93
94
|
"ease-base",
|
|
94
95
|
"bg-divider · text-divider · border-divider · bg-divider-faded · text-divider-faded · border-divider-faded · bg-background · text-background · … (66 in all)",
|
|
95
|
-
"bg-fill · text-fill · border-fill · bg-link · text-link · border-link · bg-primary · text-primary · … (
|
|
96
|
+
"bg-fill · text-fill · border-fill · bg-link · text-link · border-link · bg-primary · text-primary · … (39 in all)"
|
|
96
97
|
],
|
|
97
98
|
"file": "utilities.md"
|
|
98
99
|
},
|
|
@@ -158,7 +159,7 @@
|
|
|
158
159
|
"slug": "badge",
|
|
159
160
|
"title": "Badge",
|
|
160
161
|
"summary": "A small label for status or categorization.",
|
|
161
|
-
"tokenEstimate":
|
|
162
|
+
"tokenEstimate": 282,
|
|
162
163
|
"sections": [
|
|
163
164
|
"Import",
|
|
164
165
|
"Props",
|
|
@@ -184,7 +185,7 @@
|
|
|
184
185
|
"slug": "bar",
|
|
185
186
|
"title": "Bar",
|
|
186
187
|
"summary": "A flex container for toolbars and headers, in three heights.",
|
|
187
|
-
"tokenEstimate":
|
|
188
|
+
"tokenEstimate": 500,
|
|
188
189
|
"sections": [
|
|
189
190
|
"Import",
|
|
190
191
|
"Props"
|
|
@@ -195,7 +196,7 @@
|
|
|
195
196
|
"slug": "nav",
|
|
196
197
|
"title": "Nav",
|
|
197
198
|
"summary": "A navigation landmark and its items — the current one announces itself, and that announcement is what paints it.",
|
|
198
|
-
"tokenEstimate":
|
|
199
|
+
"tokenEstimate": 955,
|
|
199
200
|
"sections": [
|
|
200
201
|
"Import",
|
|
201
202
|
"Nav.Bar",
|
|
@@ -207,7 +208,7 @@
|
|
|
207
208
|
"slug": "button",
|
|
208
209
|
"title": "Button",
|
|
209
210
|
"summary": "A flexible button or link element.",
|
|
210
|
-
"tokenEstimate":
|
|
211
|
+
"tokenEstimate": 1625,
|
|
211
212
|
"sections": [
|
|
212
213
|
"Import",
|
|
213
214
|
"Props",
|
|
@@ -242,7 +243,7 @@
|
|
|
242
243
|
"slug": "card",
|
|
243
244
|
"title": "Card",
|
|
244
245
|
"summary": "A surface container that can behave as a link or button.",
|
|
245
|
-
"tokenEstimate":
|
|
246
|
+
"tokenEstimate": 725,
|
|
246
247
|
"sections": [
|
|
247
248
|
"Import",
|
|
248
249
|
"Props"
|
|
@@ -253,7 +254,7 @@
|
|
|
253
254
|
"slug": "chip",
|
|
254
255
|
"title": "Chip",
|
|
255
256
|
"summary": "An interactive, optionally dismissible token.",
|
|
256
|
-
"tokenEstimate":
|
|
257
|
+
"tokenEstimate": 593,
|
|
257
258
|
"sections": [
|
|
258
259
|
"Import",
|
|
259
260
|
"Props",
|
|
@@ -310,7 +311,7 @@
|
|
|
310
311
|
"slug": "separator",
|
|
311
312
|
"title": "Separator",
|
|
312
313
|
"summary": "A visual divider between content.",
|
|
313
|
-
"tokenEstimate":
|
|
314
|
+
"tokenEstimate": 531,
|
|
314
315
|
"sections": [
|
|
315
316
|
"Import",
|
|
316
317
|
"Props",
|
|
@@ -752,7 +753,7 @@
|
|
|
752
753
|
"slug": "meter",
|
|
753
754
|
"title": "Meter",
|
|
754
755
|
"summary": "Displays a value within a known range.",
|
|
755
|
-
"tokenEstimate":
|
|
756
|
+
"tokenEstimate": 1469,
|
|
756
757
|
"sections": [
|
|
757
758
|
"Import",
|
|
758
759
|
"Props"
|
|
@@ -1129,14 +1130,17 @@
|
|
|
1129
1130
|
"css": "@utility` cannot be nested inside one. Surface-scoped RULES stay\n * in their surface file; surface-scoped UTILITIES have to come out.\n *\n * @use the backdrop blur for a floating panel (popover, dialog, taskbar) — it\n * applies only inside a data-surface=\"glass\" subtree and is inert elsewhere,\n * so it is safe to leave on a panel that renders under every surface. */\n@utility glass-blur {\n\t[data-surface='glass'] & {\n\t\tbackdrop-filter: blur(var(--era-blur)) saturate(var(--era-saturate));\n\t\t-webkit-backdrop-filter: blur(var(--era-blur)) saturate(var(--era-saturate));\n\t}\n}"
|
|
1130
1131
|
},
|
|
1131
1132
|
{
|
|
1132
|
-
"name": "
|
|
1133
|
+
"name": "tier-icon",
|
|
1133
1134
|
"names": [
|
|
1134
|
-
"
|
|
1135
|
+
"tier-icon",
|
|
1136
|
+
"tier-pill",
|
|
1137
|
+
"tier-chip",
|
|
1138
|
+
"tier-control",
|
|
1139
|
+
"tier-bar"
|
|
1135
1140
|
],
|
|
1136
1141
|
"file": "index.css",
|
|
1137
|
-
"
|
|
1138
|
-
"
|
|
1139
|
-
"css": "@utility rounded-row {\n\tborder-radius: max(0px, calc(var(--era-container-rd, var(--era-rd-control)) - var(--era-gap)));\n}"
|
|
1142
|
+
"description": "BOUNDED GEOMETRY — height and radius are one decision.\n\nA tier is a geometric type, not two classes a caller must remember to keep in\nsync. `tier-control` establishes h-control AND rd-control; the radius ladder\nthen guarantees rd_outer − rd_inner = (h_outer − h_inner)/2 for every pair.\nWidth remains the component's decision: a row stretches, a button adds\nmin-w-control, and a square control adds w-control.",
|
|
1143
|
+
"css": "@utility tier-icon {\n\theight: var(--era-h-icon);\n\tborder-radius: var(--era-rd-icon);\n}\n\n@utility tier-pill {\n\theight: var(--era-h-pill);\n\tborder-radius: var(--era-rd-pill);\n}\n\n@utility tier-chip {\n\theight: var(--era-h-chip);\n\tborder-radius: var(--era-rd-chip);\n}\n\n@utility tier-control {\n\theight: var(--era-h-control);\n\tborder-radius: var(--era-rd-control);\n}\n\n@utility tier-bar {\n\theight: var(--era-h-bar);\n\tborder-radius: var(--era-rd-bar);\n}"
|
|
1140
1144
|
},
|
|
1141
1145
|
{
|
|
1142
1146
|
"name": "h-line",
|
|
@@ -1148,6 +1152,16 @@
|
|
|
1148
1152
|
"description": "One LINE BOX tall — the height of the text this stands in for.\n\nSkeleton's `line` used h-(--era-text), which is the body FONT SIZE: never the\nheight of a rendered line (that is font-size x leading), and wrong again by\nthe ladder's ratio for any rung other than body. `1lh` resolves against the\nelement's OWN computed line-height, so putting a text-* class on the skeleton\nmakes it match that tier exactly, at every density, and it follows a leading\nchange for free.",
|
|
1149
1153
|
"css": "@utility h-line {\n\theight: 1lh;\n}"
|
|
1150
1154
|
},
|
|
1155
|
+
{
|
|
1156
|
+
"name": "era-track-well",
|
|
1157
|
+
"names": [
|
|
1158
|
+
"era-track-well"
|
|
1159
|
+
],
|
|
1160
|
+
"file": "index.css",
|
|
1161
|
+
"useCase": "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.",
|
|
1162
|
+
"description": "A WELL THAT SURVIVES BEING FILLED.\n\n`shadow-well` is an INSET shadow, and an inset shadow belongs to the\nelement's background layer — it paints under the element's own descendants.\nThat is invisible on a well holding text (a checkbox, a code block: the\nchrome runs around the content) and wrong the moment something paints the\nwhole box. Meter, Progress and the Slider track all do exactly that: an\nopaque child, `translateX`-ed to the value. So the well survived only where\nthe track was EMPTY — a half-full meter on bevel had a chisel to the right\nof the value and none to the left, which reads as a hole with a sticker\nover it rather than a level inside a well.\n\nThe fix is painting order, not geometry: the same `--era-shadow-well` on a\npseudo-element that is the element's LAST child, so it lands above the fill.\nThe fill still spans the full box — nothing is inset, no radius is\nre-derived, and 0% and 100% keep their exact ends. The `position: relative`\nis load-bearing (the overlay resolves against this box) and `inherit` on the\nradius keeps it honest under `data-corners=\"square\"`.\n\nSurface-agnostic on purpose. It reads the same token every well reads, so\nglass's hairline rim is restored by the same line that restores bevel's\nchisel, and flat — where the token is `none` — renders exactly as before.\nReported against bevel by a consumer; it was never a bevel bug.",
|
|
1163
|
+
"css": "@utility era-track-well {\n\tposition: relative;\n\t&::after {\n\t\tcontent: '';\n\t\tposition: absolute;\n\t\tinset: 0;\n\t\tborder-radius: inherit;\n\t\tbox-shadow: var(--era-shadow-well);\n\t\tpointer-events: none;\n\t}\n}"
|
|
1164
|
+
},
|
|
1151
1165
|
{
|
|
1152
1166
|
"name": "era-skeleton-pulse",
|
|
1153
1167
|
"names": [
|
|
@@ -1461,12 +1475,16 @@
|
|
|
1461
1475
|
"p-chip-inset-bar",
|
|
1462
1476
|
"px-chip-inset-bar",
|
|
1463
1477
|
"py-chip-inset-bar",
|
|
1464
|
-
"gap-chip-inset-bar"
|
|
1478
|
+
"gap-chip-inset-bar",
|
|
1479
|
+
"p-control-inset-bar",
|
|
1480
|
+
"px-control-inset-bar",
|
|
1481
|
+
"py-control-inset-bar",
|
|
1482
|
+
"gap-control-inset-bar"
|
|
1465
1483
|
],
|
|
1466
1484
|
"file": "index.css",
|
|
1467
1485
|
"useCase": "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.",
|
|
1468
1486
|
"description": "",
|
|
1469
|
-
"css": "@theme inline {\n\t--spacing-icon-inset-pill: var(--era-icon-inset-pill);\n\t--spacing-icon-inset-chip: var(--era-icon-inset-chip);\n\t--spacing-icon-inset-control: var(--era-icon-inset-control);\n\t--spacing-icon-inset-bar: var(--era-icon-inset-bar);\n\t--spacing-pill-inset-chip: var(--era-pill-inset-chip);\n\t--spacing-pill-inset-control: var(--era-pill-inset-control);\n\t--spacing-pill-inset-bar: var(--era-pill-inset-bar);\n\t--spacing-chip-inset-control: var(--era-chip-inset-control);\n\t--spacing-chip-inset-bar: var(--era-chip-inset-bar);\n}"
|
|
1487
|
+
"css": "@theme inline {\n\t--spacing-icon-inset-pill: var(--era-icon-inset-pill);\n\t--spacing-icon-inset-chip: var(--era-icon-inset-chip);\n\t--spacing-icon-inset-control: var(--era-icon-inset-control);\n\t--spacing-icon-inset-bar: var(--era-icon-inset-bar);\n\t--spacing-pill-inset-chip: var(--era-pill-inset-chip);\n\t--spacing-pill-inset-control: var(--era-pill-inset-control);\n\t--spacing-pill-inset-bar: var(--era-pill-inset-bar);\n\t--spacing-chip-inset-control: var(--era-chip-inset-control);\n\t--spacing-chip-inset-bar: var(--era-chip-inset-bar);\n\t--spacing-control-inset-bar: var(--era-control-inset-bar);\n}"
|
|
1470
1488
|
},
|
|
1471
1489
|
{
|
|
1472
1490
|
"name": "p-glyph-icon",
|
|
@@ -1618,11 +1636,17 @@
|
|
|
1618
1636
|
"border-warning",
|
|
1619
1637
|
"bg-warning-fg",
|
|
1620
1638
|
"text-warning-fg",
|
|
1621
|
-
"border-warning-fg"
|
|
1639
|
+
"border-warning-fg",
|
|
1640
|
+
"bg-info",
|
|
1641
|
+
"text-info",
|
|
1642
|
+
"border-info",
|
|
1643
|
+
"bg-info-fg",
|
|
1644
|
+
"text-info-fg",
|
|
1645
|
+
"border-info-fg"
|
|
1622
1646
|
],
|
|
1623
1647
|
"file": "index.css",
|
|
1624
1648
|
"description": "The standing pill fill — --era-fill, the latched counterpart of the\ntransient highlight. Surface-owned: a composing wash on flat/bevel, the\nopaque swatch on glass.",
|
|
1625
|
-
"css": "@theme inline {\n\t--color-fill: var(--era-fill);\n\t--color-link: var(--color-link);\n\t--color-primary: var(--color-primary);\n\t--color-primary-fg: var(--color-primary-fg);\n\t--color-primary-hover: var(--color-primary-hover);\n\t--color-destructive: var(--color-destructive);\n\t--color-destructive-fg: var(--color-destructive-fg);\n\t--color-success: var(--color-success);\n\t--color-success-fg: var(--color-success-fg);\n\t--color-warning: var(--color-warning);\n\t--color-warning-fg: var(--color-warning-fg);\n}"
|
|
1649
|
+
"css": "@theme inline {\n\t--color-fill: var(--era-fill);\n\t--color-link: var(--color-link);\n\t--color-primary: var(--color-primary);\n\t--color-primary-fg: var(--color-primary-fg);\n\t--color-primary-hover: var(--color-primary-hover);\n\t--color-destructive: var(--color-destructive);\n\t--color-destructive-fg: var(--color-destructive-fg);\n\t--color-success: var(--color-success);\n\t--color-success-fg: var(--color-success-fg);\n\t--color-warning: var(--color-warning);\n\t--color-warning-fg: var(--color-warning-fg);\n\t--color-info: var(--color-info);\n\t--color-info-fg: var(--color-info-fg);\n}"
|
|
1626
1650
|
}
|
|
1627
1651
|
]
|
|
1628
1652
|
}
|
|
@@ -14,10 +14,88 @@ Inherits all props from `Meter.RootProps`.
|
|
|
14
14
|
|
|
15
15
|
| Prop | Type | Default | Notes |
|
|
16
16
|
|------|------|---------|-------|
|
|
17
|
-
| `tone?` | `'default' \| 'accent' \| 'destructive' \| 'success' \| 'warning'` | `'default'` | The band this reading falls in. Tone is the fill's colour only — the
|
|
17
|
+
| `tone?` | `'default' \| 'accent' \| 'destructive' \| 'success' \| 'warning' \| 'info'` | `'default'` | The band this reading falls in. Tone is the fill's colour only — the
|
|
18
18
|
track stays neutral, because the well belongs to the control and the
|
|
19
19
|
fill belongs to the value.
|
|
20
20
|
Tone carries no semantics on its own: a meter in the destructive band
|
|
21
21
|
still needs an accessible label saying what has run out. Pair it with
|
|
22
22
|
`aria-label` / a visible label, never rely on the hue alone. |
|
|
23
|
+
| `threshold?` | `number` | — | A BOUNDARY INSIDE THE RANGE — in the same units as `value`, not a
|
|
24
|
+
percentage. A quota with a soft limit before the hard one; a plan that
|
|
25
|
+
includes 30 hours of the 50 it bills against; a temperature that is
|
|
26
|
+
fine until it is not. The bar fills against `max`, and the mark says
|
|
27
|
+
where the number the reader is actually deciding about sits.
|
|
28
|
+
WHY THE MARK HAS NO COLOUR OF ITS OWN. It has to read against both
|
|
29
|
+
sides of itself: over the empty track before the value reaches it, and
|
|
30
|
+
over the fill afterwards. One token cannot do that — a colour tuned
|
|
31
|
+
against the track disappears into the fill the moment the value
|
|
32
|
+
crosses, which is exactly what a consumer hit hand-rolling this. So
|
|
33
|
+
the mark is painted in the colour of the side it is NOT on: the fill's
|
|
34
|
+
paint while the value is short of it, the track's fill once the value
|
|
35
|
+
has passed. That contrast is not a new promise — it is the meter's
|
|
36
|
+
own. A fill that did not stand out from its track would not be a
|
|
37
|
+
meter, so borrowing the pair is the one choice that cannot be wrong in
|
|
38
|
+
a theme, a tone, or a surface era has not seen.
|
|
39
|
+
IT IS DECORATION, and silent on purpose. There is no `role` and
|
|
40
|
+
nothing to announce: a screen reader gets `value`/`min`/`max` and the
|
|
41
|
+
meter's own accessible name, and a boundary it cannot position adds
|
|
42
|
+
nothing. If the threshold is part of the reading — it usually is —
|
|
43
|
+
put the figure in `aria-label` and in a caption, where it is a number
|
|
44
|
+
rather than a position.
|
|
45
|
+
PASS `aria-valuetext` IF YOUR STORED UNIT IS NOT YOUR DISPLAYED ONE.
|
|
46
|
+
`value`, `max` and `threshold` all have to sit in one unit for this
|
|
47
|
+
arithmetic to work, and `aria-valuenow` is `value` verbatim — so a bar
|
|
48
|
+
stored in minutes and read in hours announces "2640 of 3000", a figure
|
|
49
|
+
the customer was never quoted. Converting the props is not available
|
|
50
|
+
to you (it would move the mark), which makes `aria-valuetext` the only
|
|
51
|
+
lever; it passes through `restProps` onto the same element. Reported
|
|
52
|
+
by a consumer billing minutes and quoting hours.
|
|
53
|
+
Outside `[min, max]` it renders NOTHING rather than clamping to an
|
|
54
|
+
end, because a mark pinned to the edge of the bar would claim a
|
|
55
|
+
boundary that is not in the range. |
|
|
56
|
+
| `buffer?` | `number` | — | A REGION FROM `min` THAT IS A DIFFERENT KIND OF QUANTITY — painted
|
|
57
|
+
under the fill, over the track, in the same units as `value`.
|
|
58
|
+
The media player's buffered-progress shape, and the name is borrowed
|
|
59
|
+
from it, but the reading is more general: some of the range is already
|
|
60
|
+
accounted for. A plan whose first 30 of 50 hours are included in the
|
|
61
|
+
monthly minimum is not "24 hours into a bill", it is "24 of 30 hours
|
|
62
|
+
you have already paid for" — money spent against money that will be
|
|
63
|
+
spent, which is a distinction the bar could not draw.
|
|
64
|
+
NO COLOUR OF ITS OWN, for the reason `threshold` has none: it has to
|
|
65
|
+
be legible over the track while never competing with the fill that
|
|
66
|
+
crosses it, and a token tuned for one of those is wrong for the other.
|
|
67
|
+
It is the fill's own paint at 30%, so it cannot be wrong in a theme,
|
|
68
|
+
a tone or a surface era has not seen, and it is the same 30% Slider's
|
|
69
|
+
`progress` has used for a seek bar's buffer since it shipped.
|
|
70
|
+
UNDER the fill, so it disappears as the value consumes it. That is the
|
|
71
|
+
reading, not a limitation: once you are past your included hours, the
|
|
72
|
+
included region IS spent, and `threshold` is what goes on marking
|
|
73
|
+
where it ended.
|
|
74
|
+
CLAMPED to the range rather than dropped, which is where it differs
|
|
75
|
+
from `threshold`. A region can be honestly truncated — a buffer past
|
|
76
|
+
`max` means the whole visible bar is accounted for, and painting it
|
|
77
|
+
all says exactly that. A point cannot: a mark pinned to the edge would
|
|
78
|
+
claim a boundary that is not in the range, so an out-of-range
|
|
79
|
+
`threshold` renders nothing instead.
|
|
80
|
+
Silent, like the mark. `aria-valuetext` already carries the reading,
|
|
81
|
+
and a second region a screen reader cannot position adds nothing.
|
|
82
|
+
(Slider spells its equivalent `progress` and takes a 0–1 FRACTION.
|
|
83
|
+
Here every positional prop is in the value's own units — `value`,
|
|
84
|
+
`max`, `threshold`, `buffer` — because a component that mixed the two
|
|
85
|
+
would be a bug generator. The names differ because on a Meter
|
|
86
|
+
`progress` would be a synonym for `value`.) |
|
|
87
|
+
| `start?` | `Snippet` | — | Captions under the two ends of the bar — what the range MEANS.
|
|
88
|
+
A meter states a proportion and leaves the reader to work out what of.
|
|
89
|
+
"0m used" on the left and "50h before approval" on the right is not
|
|
90
|
+
decoration, it is the reading; every consumer of a bare meter ends up
|
|
91
|
+
hand-rolling the same flex row underneath it, which is where this came
|
|
92
|
+
from. `start` is left, `end` is right, either may stand alone.
|
|
93
|
+
NOT ANNOUNCED. They are captions, so a screen reader gets the meter's
|
|
94
|
+
value and its own `aria-label`, not these. If the range needs saying
|
|
95
|
+
out loud, say it in the label too — the same rule `tone` carries.
|
|
96
|
+
THE DOM IS UNCHANGED WITHOUT THEM. With neither snippet this renders
|
|
97
|
+
exactly the element it always did, so `class` still lands on the track
|
|
98
|
+
and the geometry audits still walk the same box. Passing one wraps the
|
|
99
|
+
track in a column, and `class` still lands on the track. |
|
|
100
|
+
| `end?` | `Snippet` | — | — |
|
|
23
101
|
| `ref?` | `(forwarded)` | `null` | bindable |
|
|
@@ -21,7 +21,7 @@ Inherits all props from `HTMLAttributes<HTMLElement>`.
|
|
|
21
21
|
|------|------|---------|-------|
|
|
22
22
|
| `ref?` | `HTMLElement \| null` | `null` | bindable |
|
|
23
23
|
| `size?` | `'chip' \| 'control' \| 'bar'` | `'bar'` | Height tier, exactly as Bar's — the geometry is Bar's, not a second copy. |
|
|
24
|
-
| `content?` | `
|
|
24
|
+
| `content?` | `BarContent` | — | Tier of the items inside, so the wall stays concentric to them. |
|
|
25
25
|
| `divider?` | `boolean` | `false` | Draw Bar's flush cap-a-panel rule beneath the bar. Off by default,
|
|
26
26
|
because a nav that sits in a page already has whatever separation the
|
|
27
27
|
layout gives it — and a link-variant nav in particular reads as text,
|
|
@@ -46,6 +46,13 @@ Inherits all props from `HTMLAnchorAttributes`.
|
|
|
46
46
|
drops the chrome entirely and renders running text, for a primary nav
|
|
47
47
|
that should read as links rather than a row of raised keycaps. Existing
|
|
48
48
|
bars are byte-identical. |
|
|
49
|
+
| `currentCue?` | `'thickness' \| 'ink' \| 'none'` | `'thickness'` | WHAT MARKS THE CURRENT ITEM. `thickness` (default) is the three-state
|
|
50
|
+
decoration — portable across every theme and font because it is one
|
|
51
|
+
ink at three strengths. `ink` brightens the current item instead, and
|
|
52
|
+
is theme-dependent by construction: era's default themes point
|
|
53
|
+
--color-link at --color-bright, so its delta there is zero. `none`
|
|
54
|
+
silences era's cue entirely, for a consumer painting their own.
|
|
55
|
+
See navItemVariants above for the measurements behind each. |
|
|
49
56
|
| `current?` | `boolean` | `false` | Whether this item points at the page you are on.
|
|
50
57
|
There is deliberately no `active` prop beside this one. `active` would
|
|
51
58
|
be a second source of truth for one fact, and the two drift the moment
|
|
@@ -15,6 +15,24 @@ Inherits all props from `Separator.RootProps`.
|
|
|
15
15
|
| Prop | Type | Default | Notes |
|
|
16
16
|
|------|------|---------|-------|
|
|
17
17
|
| `variant?` | `'line' \| 'slant'` | `'line'` | Use `slant` for inline dividers in breadcrumbs, titles, and compact metadata. |
|
|
18
|
+
| `size?` | `keyof typeof SIZES` | — | Give a VERTICAL rule a height of its own, from the tier ladder, instead
|
|
19
|
+
of stretching to whatever line it lands in. Ignored when horizontal.
|
|
20
|
+
WHY YOU WOULD WANT IT. A stretched rule is a passenger: it has no
|
|
21
|
+
intrinsic height, so it measures whatever its neighbours measure and
|
|
22
|
+
contributes nothing back. That is right inside a Bar, whose height is
|
|
23
|
+
already fixed — and it is why a rule in an auto-height row cannot hold
|
|
24
|
+
that row's height steady. A consumer whose site header gained and lost
|
|
25
|
+
a qualifier between pages watched the chrome resize, and pinned a
|
|
26
|
+
`min-h-[calc(...)]` on the header to stop it. Sizing the rule removes
|
|
27
|
+
that calc: it becomes the piece that stands the row up.
|
|
28
|
+
(For the record, since the report named the wrong mechanism: a
|
|
29
|
+
stretched rule does not GROW its row. Measured in an 18px auto-height
|
|
30
|
+
row, adding one leaves the row at 18px and the rule resolves to 10px —
|
|
31
|
+
the line minus its two gutter margins. It can only ever be shorter
|
|
32
|
+
than the row it divides, which is the whole problem here.)
|
|
33
|
+
A sized rule drops the gutter margins with the stretch: the height is
|
|
34
|
+
now a deliberate number, and silently adding 2 x gutter to it would
|
|
35
|
+
make it the one element on the page you cannot reason about. |
|
|
18
36
|
| `ref?` | `(forwarded)` | `null` | bindable |
|
|
19
37
|
|
|
20
38
|
## Usage
|
|
@@ -101,14 +101,17 @@
|
|
|
101
101
|
"css": "@utility` cannot be nested inside one. Surface-scoped RULES stay\n * in their surface file; surface-scoped UTILITIES have to come out.\n *\n * @use the backdrop blur for a floating panel (popover, dialog, taskbar) — it\n * applies only inside a data-surface=\"glass\" subtree and is inert elsewhere,\n * so it is safe to leave on a panel that renders under every surface. */\n@utility glass-blur {\n\t[data-surface='glass'] & {\n\t\tbackdrop-filter: blur(var(--era-blur)) saturate(var(--era-saturate));\n\t\t-webkit-backdrop-filter: blur(var(--era-blur)) saturate(var(--era-saturate));\n\t}\n}"
|
|
102
102
|
},
|
|
103
103
|
{
|
|
104
|
-
"name": "
|
|
104
|
+
"name": "tier-icon",
|
|
105
105
|
"names": [
|
|
106
|
-
"
|
|
106
|
+
"tier-icon",
|
|
107
|
+
"tier-pill",
|
|
108
|
+
"tier-chip",
|
|
109
|
+
"tier-control",
|
|
110
|
+
"tier-bar"
|
|
107
111
|
],
|
|
108
112
|
"file": "index.css",
|
|
109
|
-
"
|
|
110
|
-
"
|
|
111
|
-
"css": "@utility rounded-row {\n\tborder-radius: max(0px, calc(var(--era-container-rd, var(--era-rd-control)) - var(--era-gap)));\n}"
|
|
113
|
+
"description": "BOUNDED GEOMETRY — height and radius are one decision.\n\nA tier is a geometric type, not two classes a caller must remember to keep in\nsync. `tier-control` establishes h-control AND rd-control; the radius ladder\nthen guarantees rd_outer − rd_inner = (h_outer − h_inner)/2 for every pair.\nWidth remains the component's decision: a row stretches, a button adds\nmin-w-control, and a square control adds w-control.",
|
|
114
|
+
"css": "@utility tier-icon {\n\theight: var(--era-h-icon);\n\tborder-radius: var(--era-rd-icon);\n}\n\n@utility tier-pill {\n\theight: var(--era-h-pill);\n\tborder-radius: var(--era-rd-pill);\n}\n\n@utility tier-chip {\n\theight: var(--era-h-chip);\n\tborder-radius: var(--era-rd-chip);\n}\n\n@utility tier-control {\n\theight: var(--era-h-control);\n\tborder-radius: var(--era-rd-control);\n}\n\n@utility tier-bar {\n\theight: var(--era-h-bar);\n\tborder-radius: var(--era-rd-bar);\n}"
|
|
112
115
|
},
|
|
113
116
|
{
|
|
114
117
|
"name": "h-line",
|
|
@@ -120,6 +123,16 @@
|
|
|
120
123
|
"description": "One LINE BOX tall — the height of the text this stands in for.\n\nSkeleton's `line` used h-(--era-text), which is the body FONT SIZE: never the\nheight of a rendered line (that is font-size x leading), and wrong again by\nthe ladder's ratio for any rung other than body. `1lh` resolves against the\nelement's OWN computed line-height, so putting a text-* class on the skeleton\nmakes it match that tier exactly, at every density, and it follows a leading\nchange for free.",
|
|
121
124
|
"css": "@utility h-line {\n\theight: 1lh;\n}"
|
|
122
125
|
},
|
|
126
|
+
{
|
|
127
|
+
"name": "era-track-well",
|
|
128
|
+
"names": [
|
|
129
|
+
"era-track-well"
|
|
130
|
+
],
|
|
131
|
+
"file": "index.css",
|
|
132
|
+
"useCase": "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.",
|
|
133
|
+
"description": "A WELL THAT SURVIVES BEING FILLED.\n\n`shadow-well` is an INSET shadow, and an inset shadow belongs to the\nelement's background layer — it paints under the element's own descendants.\nThat is invisible on a well holding text (a checkbox, a code block: the\nchrome runs around the content) and wrong the moment something paints the\nwhole box. Meter, Progress and the Slider track all do exactly that: an\nopaque child, `translateX`-ed to the value. So the well survived only where\nthe track was EMPTY — a half-full meter on bevel had a chisel to the right\nof the value and none to the left, which reads as a hole with a sticker\nover it rather than a level inside a well.\n\nThe fix is painting order, not geometry: the same `--era-shadow-well` on a\npseudo-element that is the element's LAST child, so it lands above the fill.\nThe fill still spans the full box — nothing is inset, no radius is\nre-derived, and 0% and 100% keep their exact ends. The `position: relative`\nis load-bearing (the overlay resolves against this box) and `inherit` on the\nradius keeps it honest under `data-corners=\"square\"`.\n\nSurface-agnostic on purpose. It reads the same token every well reads, so\nglass's hairline rim is restored by the same line that restores bevel's\nchisel, and flat — where the token is `none` — renders exactly as before.\nReported against bevel by a consumer; it was never a bevel bug.",
|
|
134
|
+
"css": "@utility era-track-well {\n\tposition: relative;\n\t&::after {\n\t\tcontent: '';\n\t\tposition: absolute;\n\t\tinset: 0;\n\t\tborder-radius: inherit;\n\t\tbox-shadow: var(--era-shadow-well);\n\t\tpointer-events: none;\n\t}\n}"
|
|
135
|
+
},
|
|
123
136
|
{
|
|
124
137
|
"name": "era-skeleton-pulse",
|
|
125
138
|
"names": [
|
|
@@ -433,12 +446,16 @@
|
|
|
433
446
|
"p-chip-inset-bar",
|
|
434
447
|
"px-chip-inset-bar",
|
|
435
448
|
"py-chip-inset-bar",
|
|
436
|
-
"gap-chip-inset-bar"
|
|
449
|
+
"gap-chip-inset-bar",
|
|
450
|
+
"p-control-inset-bar",
|
|
451
|
+
"px-control-inset-bar",
|
|
452
|
+
"py-control-inset-bar",
|
|
453
|
+
"gap-control-inset-bar"
|
|
437
454
|
],
|
|
438
455
|
"file": "index.css",
|
|
439
456
|
"useCase": "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.",
|
|
440
457
|
"description": "",
|
|
441
|
-
"css": "@theme inline {\n\t--spacing-icon-inset-pill: var(--era-icon-inset-pill);\n\t--spacing-icon-inset-chip: var(--era-icon-inset-chip);\n\t--spacing-icon-inset-control: var(--era-icon-inset-control);\n\t--spacing-icon-inset-bar: var(--era-icon-inset-bar);\n\t--spacing-pill-inset-chip: var(--era-pill-inset-chip);\n\t--spacing-pill-inset-control: var(--era-pill-inset-control);\n\t--spacing-pill-inset-bar: var(--era-pill-inset-bar);\n\t--spacing-chip-inset-control: var(--era-chip-inset-control);\n\t--spacing-chip-inset-bar: var(--era-chip-inset-bar);\n}"
|
|
458
|
+
"css": "@theme inline {\n\t--spacing-icon-inset-pill: var(--era-icon-inset-pill);\n\t--spacing-icon-inset-chip: var(--era-icon-inset-chip);\n\t--spacing-icon-inset-control: var(--era-icon-inset-control);\n\t--spacing-icon-inset-bar: var(--era-icon-inset-bar);\n\t--spacing-pill-inset-chip: var(--era-pill-inset-chip);\n\t--spacing-pill-inset-control: var(--era-pill-inset-control);\n\t--spacing-pill-inset-bar: var(--era-pill-inset-bar);\n\t--spacing-chip-inset-control: var(--era-chip-inset-control);\n\t--spacing-chip-inset-bar: var(--era-chip-inset-bar);\n\t--spacing-control-inset-bar: var(--era-control-inset-bar);\n}"
|
|
442
459
|
},
|
|
443
460
|
{
|
|
444
461
|
"name": "p-glyph-icon",
|
|
@@ -590,11 +607,17 @@
|
|
|
590
607
|
"border-warning",
|
|
591
608
|
"bg-warning-fg",
|
|
592
609
|
"text-warning-fg",
|
|
593
|
-
"border-warning-fg"
|
|
610
|
+
"border-warning-fg",
|
|
611
|
+
"bg-info",
|
|
612
|
+
"text-info",
|
|
613
|
+
"border-info",
|
|
614
|
+
"bg-info-fg",
|
|
615
|
+
"text-info-fg",
|
|
616
|
+
"border-info-fg"
|
|
594
617
|
],
|
|
595
618
|
"file": "index.css",
|
|
596
619
|
"description": "The standing pill fill — --era-fill, the latched counterpart of the\ntransient highlight. Surface-owned: a composing wash on flat/bevel, the\nopaque swatch on glass.",
|
|
597
|
-
"css": "@theme inline {\n\t--color-fill: var(--era-fill);\n\t--color-link: var(--color-link);\n\t--color-primary: var(--color-primary);\n\t--color-primary-fg: var(--color-primary-fg);\n\t--color-primary-hover: var(--color-primary-hover);\n\t--color-destructive: var(--color-destructive);\n\t--color-destructive-fg: var(--color-destructive-fg);\n\t--color-success: var(--color-success);\n\t--color-success-fg: var(--color-success-fg);\n\t--color-warning: var(--color-warning);\n\t--color-warning-fg: var(--color-warning-fg);\n}"
|
|
620
|
+
"css": "@theme inline {\n\t--color-fill: var(--era-fill);\n\t--color-link: var(--color-link);\n\t--color-primary: var(--color-primary);\n\t--color-primary-fg: var(--color-primary-fg);\n\t--color-primary-hover: var(--color-primary-hover);\n\t--color-destructive: var(--color-destructive);\n\t--color-destructive-fg: var(--color-destructive-fg);\n\t--color-success: var(--color-success);\n\t--color-success-fg: var(--color-success-fg);\n\t--color-warning: var(--color-warning);\n\t--color-warning-fg: var(--color-warning-fg);\n\t--color-info: var(--color-info);\n\t--color-info-fg: var(--color-info-fg);\n}"
|
|
598
621
|
}
|
|
599
622
|
]
|
|
600
623
|
}
|