@signal9/era-ui 3.0.1 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs/css-utilities.d.ts +8 -2
- package/dist/docs/css-utilities.js +45 -12
- package/dist/era-ui.css +1 -1
- package/dist/generated-docs/llms-full.txt +267 -4
- package/dist/generated-docs/llms.txt +11 -0
- package/dist/generated-docs/manifest.json +171 -1
- package/dist/generated-docs/utilities.json +159 -0
- package/dist/generated-docs/utilities.md +256 -4
- package/dist/os/taskbar.svelte +10 -2
- package/dist/os/taskbar.svelte.d.ts +5 -0
- package/dist/styles/index.css +234 -1
- package/dist/ui/pane/pane-root.svelte.d.ts +1 -1
- package/dist/ui/pane/pane.svelte.d.ts +1 -1
- package/dist/ui/toggle/toggle.svelte.d.ts +1 -1
- package/dist/utils/index.js +21 -1
- package/package.json +1 -1
- package/skill/SKILL.md +75 -51
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
"utilities": [
|
|
3
3
|
{
|
|
4
4
|
"name": "era-interactive",
|
|
5
|
+
"names": [
|
|
6
|
+
"era-interactive"
|
|
7
|
+
],
|
|
5
8
|
"file": "index.css",
|
|
6
9
|
"useCase": "the focus/disabled recipe every era control carries — put it on a custom interactive element instead of hand-writing focus/disabled variants.",
|
|
7
10
|
"description": "Shared interactive-state recipe: quiet focus, disabled affordance.\nEquivalent to `focus:outline-none disabled:cursor-not-allowed disabled:opacity-50`.",
|
|
@@ -9,6 +12,9 @@
|
|
|
9
12
|
},
|
|
10
13
|
{
|
|
11
14
|
"name": "era-link",
|
|
15
|
+
"names": [
|
|
16
|
+
"era-link"
|
|
17
|
+
],
|
|
12
18
|
"file": "index.css",
|
|
13
19
|
"useCase": "understated, motion-aware inline text link — the canonical style for a link in body copy or prose; prefer it over a hand-rolled underline or `Button variant=\"link\"` (which is a control, not running text).",
|
|
14
20
|
"description": "Inline text link. An understated, permanent underline that darkens from\nmuted to the text colour on hover — no layout shift, no appearing/vanishing\nunderline. The colour fade rides the MOTION axis (--era-duration/-ease), so\nit snaps at data-motion=\"instant\", eases at \"normal\", and sweeps longer at\n\"extra\" — matching every other era transition. Font-agnostic: it styles\ndecoration + colour only, so it reads correctly in mono, sans, or serif, and\nthe 0.2em offset scales with the type size. Keyboard focus mirrors hover so\nthe affordance is reachable without a pointer.",
|
|
@@ -16,6 +22,9 @@
|
|
|
16
22
|
},
|
|
17
23
|
{
|
|
18
24
|
"name": "scrollbar-none",
|
|
25
|
+
"names": [
|
|
26
|
+
"scrollbar-none"
|
|
27
|
+
],
|
|
19
28
|
"file": "index.css",
|
|
20
29
|
"useCase": "hide the scrollbar on an overflowing strip or rail while keeping it scrollable — for a scroll region that should show its bar, use ScrollArea.",
|
|
21
30
|
"description": "Scrollable but chromeless — hides the scrollbar while keeping wheel / touch /\ndrag scrolling (e.g. an overflowing tab strip in a small pane handle).",
|
|
@@ -23,6 +32,9 @@
|
|
|
23
32
|
},
|
|
24
33
|
{
|
|
25
34
|
"name": "era-text-trim",
|
|
35
|
+
"names": [
|
|
36
|
+
"era-text-trim"
|
|
37
|
+
],
|
|
26
38
|
"file": "index.css",
|
|
27
39
|
"useCase": "vertically center single-line control text (a label beside an icon, a button's own text) without a translateY nudge — fixed-height, non-editable elements only; see era-text-trim-caps for ALL-CAPS strings.",
|
|
28
40
|
"description": "Font-agnostic vertical ink-centering for single-line control text.\nMeasured verdict (4 fonts x 2 dpr, ink from device-pixel screenshots):\nthe offset has TWO causes — a fractional line box (14px x 1.5lh = 21px in\na 24px row places ink on a half pixel, ~1px error) and font ascent/descent\nasymmetry (+-1px, sign flips per font). line-height: 1 fixes the first and\nis the Firefox fallback; text-box ex/alphabetic fixes the second by\ncentering the x-height band — the visual mass of MIXED-CASE text (caps and\ndescenders cancel above/below). cap alphabetic is the spec-example recipe\nbut is descender-blind (reads high; CSSWG #9148) — measured 4x worse here.\nWhere text-box is supported it fully determines the box, so the two\ndeclarations never fight. Worst-case residual: 0.44px.\n\nThe hard rules concern overflow clipping, and there are TWO of them.\n\n1. NEVER on a NATIVE EDITABLE — <input>, <textarea>, <select>. These clip to\n a UA-owned inner editor box that IS the trimmed line box, so a fixed\n height does NOT hold it open: whatever you type gets its ascenders and\n descenders sliced off (a \"d\" renders as an \"o\"). This rule used to read\n the other way round — it claimed a fixed-height <input> was the trim's\n intended home — and the Input component shipped chopped text as a result.\n A tier-height input centres its own text; it needs no trim.\n\n2. NEVER on an AUTO-height element that clips — a `truncate` child, an\n auto-height box with overflow-hidden. With no height to hold it open the\n box collapses to the x-height band (~7.5px at 14px) and the clip chops the\n glyphs into a middle stripe. Put the trim on the fixed-height ROW instead\n and let the child centre via the row's items-center.\n\nA fixed-height NON-editable element is the safe home: the ink overflows the\ntrimmed LINE box but stays inside the padding box, which is what actually\nclips. Both rules are enforced at runtime by typography/collapsed-text-trim.",
|
|
@@ -30,6 +42,9 @@
|
|
|
30
42
|
},
|
|
31
43
|
{
|
|
32
44
|
"name": "era-text-trim-caps",
|
|
45
|
+
"names": [
|
|
46
|
+
"era-text-trim-caps"
|
|
47
|
+
],
|
|
33
48
|
"file": "index.css",
|
|
34
49
|
"useCase": "the era-text-trim variant for ALL-CAPS single-line strings (kbd hints, acronym badges) — never use it for mixed-case text.",
|
|
35
50
|
"description": "ALL-CAPS single-line text (kbd hints, acronym badges): the x-height band\nmisjudges caps-only strings — cap/alphabetic edges are the right box.",
|
|
@@ -37,13 +52,157 @@
|
|
|
37
52
|
},
|
|
38
53
|
{
|
|
39
54
|
"name": "era-shimmer",
|
|
55
|
+
"names": [
|
|
56
|
+
"era-shimmer"
|
|
57
|
+
],
|
|
40
58
|
"file": "index.css",
|
|
41
59
|
"useCase": "the in-progress text treatment — put it on a \"working…\" / \"thinking…\" label while a task streams, instead of a spinner beside the text.",
|
|
42
60
|
"description": "In-progress text shimmer — a bright sweep through muted text (the standard\n\"working…\" label treatment in streaming UIs). Timing derives from the motion\naxis (10× --era-duration ≈ 1.5s at normal, 2.6s at extra); at instant the\nduration is 0s and the sweep freezes on its base frame — plain muted text —\nso reduced-motion and data-motion=\"instant\" both kill it for free.",
|
|
43
61
|
"css": "@utility era-shimmer {\n\tbackground: linear-gradient(\n\t\t110deg,\n\t\tvar(--color-muted) 0% 43%,\n\t\tvar(--color-bright) 50%,\n\t\tvar(--color-muted) 57% 100%\n\t);\n\tbackground-size: 200% 100%;\n\tbackground-clip: text;\n\t-webkit-text-fill-color: transparent;\n\tanimation: era-shimmer calc(var(--era-duration) * 10) cubic-bezier(0.7, 0, 1, 0.4) infinite;\n}"
|
|
44
62
|
},
|
|
63
|
+
{
|
|
64
|
+
"name": "h-xs",
|
|
65
|
+
"names": [
|
|
66
|
+
"h-xs",
|
|
67
|
+
"h-xxs",
|
|
68
|
+
"h-sm",
|
|
69
|
+
"h-md",
|
|
70
|
+
"h-lg"
|
|
71
|
+
],
|
|
72
|
+
"file": "index.css",
|
|
73
|
+
"useCase": "the tier-height ladder — h-xs (icon) · h-xxs (nested pill) · h-sm (standalone pill) · h-md (control) · h-lg (bar); the named form of h-(--era-h-*).",
|
|
74
|
+
"description": "",
|
|
75
|
+
"css": "@utility h-xs {\n\theight: var(--era-h-xs);\n}\n@utility h-xxs {\n\theight: var(--era-h-xxs);\n}\n@utility h-sm {\n\theight: var(--era-h-sm);\n}\n@utility h-md {\n\theight: var(--era-h-md);\n}\n@utility h-lg {\n\theight: var(--era-h-lg);\n}"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"name": "min-h-xs",
|
|
79
|
+
"names": [
|
|
80
|
+
"min-h-xs",
|
|
81
|
+
"min-h-xxs",
|
|
82
|
+
"min-h-sm",
|
|
83
|
+
"min-h-md",
|
|
84
|
+
"min-h-lg"
|
|
85
|
+
],
|
|
86
|
+
"file": "index.css",
|
|
87
|
+
"useCase": "minimum tier height for containers that may grow — a bar that is at least lg-tier but can wrap (min-h-lg).",
|
|
88
|
+
"description": "",
|
|
89
|
+
"css": "@utility min-h-xs {\n\tmin-height: var(--era-h-xs);\n}\n@utility min-h-xxs {\n\tmin-height: var(--era-h-xxs);\n}\n@utility min-h-sm {\n\tmin-height: var(--era-h-sm);\n}\n@utility min-h-md {\n\tmin-height: var(--era-h-md);\n}\n@utility min-h-lg {\n\tmin-height: var(--era-h-lg);\n}"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"name": "size-xs",
|
|
93
|
+
"names": [
|
|
94
|
+
"size-xs",
|
|
95
|
+
"size-xxs",
|
|
96
|
+
"size-sm",
|
|
97
|
+
"size-md",
|
|
98
|
+
"size-lg"
|
|
99
|
+
],
|
|
100
|
+
"file": "index.css",
|
|
101
|
+
"useCase": "a tier-sized square — size-xs is THE icon size (a Lucide glyph beside body text), size-md a square control face.",
|
|
102
|
+
"description": "",
|
|
103
|
+
"css": "@utility size-xs {\n\twidth: var(--era-h-xs);\n\theight: var(--era-h-xs);\n}\n@utility size-xxs {\n\twidth: var(--era-h-xxs);\n\theight: var(--era-h-xxs);\n}\n@utility size-sm {\n\twidth: var(--era-h-sm);\n\theight: var(--era-h-sm);\n}\n@utility size-md {\n\twidth: var(--era-h-md);\n\theight: var(--era-h-md);\n}\n@utility size-lg {\n\twidth: var(--era-h-lg);\n\theight: var(--era-h-lg);\n}"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"name": "px-sm",
|
|
107
|
+
"names": [
|
|
108
|
+
"px-sm",
|
|
109
|
+
"px-md",
|
|
110
|
+
"px-lg"
|
|
111
|
+
],
|
|
112
|
+
"file": "index.css",
|
|
113
|
+
"useCase": "tier-to-tier nesting padding (sp/2) — the horizontal padding of a bar or row that holds tiered controls; the named form of px-(--era-px-*).",
|
|
114
|
+
"description": "",
|
|
115
|
+
"css": "@utility px-sm {\n\tpadding-inline: var(--era-px-sm);\n}\n@utility px-md {\n\tpadding-inline: var(--era-px-md);\n}\n@utility px-lg {\n\tpadding-inline: var(--era-px-lg);\n}"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"name": "gap-gutter",
|
|
119
|
+
"names": [
|
|
120
|
+
"gap-gutter",
|
|
121
|
+
"p-gutter",
|
|
122
|
+
"px-gutter",
|
|
123
|
+
"py-gutter"
|
|
124
|
+
],
|
|
125
|
+
"file": "index.css",
|
|
126
|
+
"useCase": "the inter-element gap (sp/2) — flex/grid gap between sibling controls, and the matching gutter padding a scrollable list or rail owes its rows on all four sides (p-gutter on the rail = gap-gutter between its rows).",
|
|
127
|
+
"description": "",
|
|
128
|
+
"css": "@utility gap-gutter {\n\tgap: var(--era-gap);\n}\n@utility p-gutter {\n\tpadding: var(--era-gap);\n}\n@utility px-gutter {\n\tpadding-inline: var(--era-gap);\n}\n@utility py-gutter {\n\tpadding-block: var(--era-gap);\n}"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"name": "p-inset-xxs",
|
|
132
|
+
"names": [
|
|
133
|
+
"p-inset-xxs",
|
|
134
|
+
"p-inset-sm",
|
|
135
|
+
"p-inset-md",
|
|
136
|
+
"px-inset-xxs",
|
|
137
|
+
"px-inset-sm",
|
|
138
|
+
"px-inset-md",
|
|
139
|
+
"py-inset-xxs",
|
|
140
|
+
"py-inset-sm",
|
|
141
|
+
"py-inset-md"
|
|
142
|
+
],
|
|
143
|
+
"file": "index.css",
|
|
144
|
+
"useCase": "text-symmetric content padding — (tier − text)/2, the inset that vertically centers body text in its tier; px-inset-md is a text button's side padding, p-inset-md a code block's.",
|
|
145
|
+
"description": "",
|
|
146
|
+
"css": "@utility p-inset-xxs {\n\tpadding: var(--era-inset-xxs);\n}\n@utility p-inset-sm {\n\tpadding: var(--era-inset-sm);\n}\n@utility p-inset-md {\n\tpadding: var(--era-inset-md);\n}\n@utility px-inset-xxs {\n\tpadding-inline: var(--era-inset-xxs);\n}\n@utility px-inset-sm {\n\tpadding-inline: var(--era-inset-sm);\n}\n@utility px-inset-md {\n\tpadding-inline: var(--era-inset-md);\n}\n@utility py-inset-xxs {\n\tpadding-block: var(--era-inset-xxs);\n}\n@utility py-inset-sm {\n\tpadding-block: var(--era-inset-sm);\n}\n@utility py-inset-md {\n\tpadding-block: var(--era-inset-md);\n}"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"name": "px-pill-xxs",
|
|
150
|
+
"names": [
|
|
151
|
+
"px-pill-xxs",
|
|
152
|
+
"px-pill-sm"
|
|
153
|
+
],
|
|
154
|
+
"file": "index.css",
|
|
155
|
+
"useCase": "pill side padding — the wider-than-vertical horizontal breathing room badge/chip text wants (glyph-advance derived, ~2× the vertical inset).",
|
|
156
|
+
"description": "",
|
|
157
|
+
"css": "@utility px-pill-xxs {\n\tpadding-inline: var(--era-pill-xxs);\n}\n@utility px-pill-sm {\n\tpadding-inline: var(--era-pill-sm);\n}"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"name": "px-field",
|
|
161
|
+
"names": [
|
|
162
|
+
"px-field"
|
|
163
|
+
],
|
|
164
|
+
"file": "index.css",
|
|
165
|
+
"useCase": "text-field side padding — where typed text starts in an md-tier input; the named form of px-(--era-field-px).",
|
|
166
|
+
"description": "",
|
|
167
|
+
"css": "@utility px-field {\n\tpadding-inline: var(--era-field-px);\n}"
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"name": "p-panel",
|
|
171
|
+
"names": [
|
|
172
|
+
"p-panel",
|
|
173
|
+
"p-card",
|
|
174
|
+
"p-content"
|
|
175
|
+
],
|
|
176
|
+
"file": "index.css",
|
|
177
|
+
"useCase": "optical padding for unbounded containers — p-panel for compact shells and menu-adjacent chrome, p-card for cards/dialogs/popovers, p-content for full content panels. Grows super-linearly with density so whitespace holds its perceived share as controls loosen.",
|
|
178
|
+
"description": "",
|
|
179
|
+
"css": "@utility p-panel {\n\tpadding: var(--era-pad-sm);\n}\n@utility p-card {\n\tpadding: var(--era-pad-md);\n}\n@utility p-content {\n\tpadding: var(--era-content-p);\n}"
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"name": "p-menu",
|
|
183
|
+
"names": [
|
|
184
|
+
"p-menu"
|
|
185
|
+
],
|
|
186
|
+
"file": "index.css",
|
|
187
|
+
"useCase": "menu-panel padding — the surface-owned inset (0 on flat, 2px on glass/bevel) that keeps row highlights inside a floating panel's frame; pairs with rounded-item on the rows.",
|
|
188
|
+
"description": "",
|
|
189
|
+
"css": "@utility p-menu {\n\tpadding: var(--era-panel-inset);\n}"
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"name": "duration-base",
|
|
193
|
+
"names": [
|
|
194
|
+
"duration-base"
|
|
195
|
+
],
|
|
196
|
+
"file": "index.css",
|
|
197
|
+
"useCase": "the motion axis as an explicit transition-duration — for the rare case a utility (not the transition-* default) needs to name it; 0s at data-motion=\"instant\", longer at \"extra\".",
|
|
198
|
+
"description": "",
|
|
199
|
+
"css": "@utility duration-base {\n\ttransition-duration: var(--era-duration);\n}"
|
|
200
|
+
},
|
|
45
201
|
{
|
|
46
202
|
"name": "glass-blur",
|
|
203
|
+
"names": [
|
|
204
|
+
"glass-blur"
|
|
205
|
+
],
|
|
47
206
|
"file": "surfaces/glass.css",
|
|
48
207
|
"useCase": "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.",
|
|
49
208
|
"description": "Tailwind v4 cannot resolve var() inside backdrop-blur-[], so the filter\nis a registered utility, gated to glass subtrees.",
|
|
@@ -4,18 +4,38 @@ The CSS classes era ships alongside the components — links, ink-centred text,
|
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
era
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
era's styling API is pure class names — write `h-md rounded-md px-md shadow`,
|
|
8
|
+
never the `h-(--era-h-md)` var-class spelling. Everything below rides along
|
|
9
|
+
with the stylesheet and needs no import:
|
|
10
10
|
|
|
11
11
|
```ts
|
|
12
12
|
import "@sig-nine/era-ui/css";
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
```svelte
|
|
16
|
-
<
|
|
16
|
+
<button class="h-md rounded-md px-inset-md shadow text-body">era styled</button>
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
+
Alongside the `@utility` classes referenced below, era registers named theme
|
|
20
|
+
scales that OVERLOAD the stock Tailwind names, so ordinary-looking markup
|
|
21
|
+
renders on-design and responds to every axis (density, surface, corners,
|
|
22
|
+
motion):
|
|
23
|
+
|
|
24
|
+
| Stock-looking class | What it resolves to |
|
|
25
|
+
|---|---|
|
|
26
|
+
| `rounded-xs/xxs/sm/md/lg` | the concentric radius ladder (collapses on `data-corners="square"`) |
|
|
27
|
+
| `rounded-item` | menu-row radius, concentric inside a `rounded-md` panel |
|
|
28
|
+
| `shadow` / `shadow-lg` | resting control edge / floating panel chrome, per surface |
|
|
29
|
+
| `shadow-well` / `shadow-pressed` / `shadow-highlight` | recessed, pressed/latched, hover-material chrome |
|
|
30
|
+
| `bg-well` / `bg-elevated` / `bg-highlight` / `bg-overlay` | surface fills: resting, raised, transient feedback, modal scrim |
|
|
31
|
+
| `transition-*` (bare) | duration + easing default to the motion axis |
|
|
32
|
+
| `ease-base` / `duration-base` | the motion axis, named explicitly |
|
|
33
|
+
| `text-body` | density-derived body/control text size |
|
|
34
|
+
|
|
35
|
+
Deliberate gaps: `w-*`/`min-w-*` tier names would shadow Tailwind's container
|
|
36
|
+
scale (`min-w-md` stays 28rem), and the concentric-inset tokens are advanced
|
|
37
|
+
enough to stay var-form — `min-w-(--era-h-md)` etc. remain the escape hatch.
|
|
38
|
+
|
|
19
39
|
| Utility | Use it for |
|
|
20
40
|
|---|---|
|
|
21
41
|
| `era-interactive` | the focus/disabled recipe every era control carries — put it on a custom interactive element instead of hand-writing focus/disabled variants. |
|
|
@@ -24,6 +44,17 @@ import "@sig-nine/era-ui/css";
|
|
|
24
44
|
| `era-text-trim` | vertically center single-line control text (a label beside an icon, a button's own text) without a translateY nudge — fixed-height, non-editable elements only; see era-text-trim-caps for ALL-CAPS strings. |
|
|
25
45
|
| `era-text-trim-caps` | the era-text-trim variant for ALL-CAPS single-line strings (kbd hints, acronym badges) — never use it for mixed-case text. |
|
|
26
46
|
| `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. |
|
|
47
|
+
| `h-xs` `h-xxs` `h-sm` `h-md` `h-lg` | the tier-height ladder — h-xs (icon) · h-xxs (nested pill) · h-sm (standalone pill) · h-md (control) · h-lg (bar); the named form of h-(--era-h-*). |
|
|
48
|
+
| `min-h-xs` `min-h-xxs` `min-h-sm` `min-h-md` `min-h-lg` | minimum tier height for containers that may grow — a bar that is at least lg-tier but can wrap (min-h-lg). |
|
|
49
|
+
| `size-xs` `size-xxs` `size-sm` `size-md` `size-lg` | a tier-sized square — size-xs is THE icon size (a Lucide glyph beside body text), size-md a square control face. |
|
|
50
|
+
| `px-sm` `px-md` `px-lg` | tier-to-tier nesting padding (sp/2) — the horizontal padding of a bar or row that holds tiered controls; the named form of px-(--era-px-*). |
|
|
51
|
+
| `gap-gutter` `p-gutter` `px-gutter` `py-gutter` | the inter-element gap (sp/2) — flex/grid gap between sibling controls, and the matching gutter padding a scrollable list or rail owes its rows on all four sides (p-gutter on the rail = gap-gutter between its rows). |
|
|
52
|
+
| `p-inset-xxs` `p-inset-sm` `p-inset-md` `px-inset-xxs` `px-inset-sm` `px-inset-md` `py-inset-xxs` `py-inset-sm` `py-inset-md` | text-symmetric content padding — (tier − text)/2, the inset that vertically centers body text in its tier; px-inset-md is a text button's side padding, p-inset-md a code block's. |
|
|
53
|
+
| `px-pill-xxs` `px-pill-sm` | pill side padding — the wider-than-vertical horizontal breathing room badge/chip text wants (glyph-advance derived, ~2× the vertical inset). |
|
|
54
|
+
| `px-field` | text-field side padding — where typed text starts in an md-tier input; the named form of px-(--era-field-px). |
|
|
55
|
+
| `p-panel` `p-card` `p-content` | optical padding for unbounded containers — p-panel for compact shells and menu-adjacent chrome, p-card for cards/dialogs/popovers, p-content for full content panels. Grows super-linearly with density so whitespace holds its perceived share as controls loosen. |
|
|
56
|
+
| `p-menu` | menu-panel padding — the surface-owned inset (0 on flat, 2px on glass/bevel) that keeps row highlights inside a floating panel's frame; pairs with rounded-item on the rows. |
|
|
57
|
+
| `duration-base` | the motion axis as an explicit transition-duration — for the rare case a utility (not the transition-* default) needs to name it; 0s at data-motion="instant", longer at "extra". |
|
|
27
58
|
| `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. |
|
|
28
59
|
|
|
29
60
|
## era-interactive
|
|
@@ -186,6 +217,227 @@ Declared in `index.css`.
|
|
|
186
217
|
}
|
|
187
218
|
```
|
|
188
219
|
|
|
220
|
+
## h-xs · h-xxs · h-sm · h-md · h-lg
|
|
221
|
+
|
|
222
|
+
**Use it for:** the tier-height ladder — h-xs (icon) · h-xxs (nested pill) · h-sm (standalone pill) · h-md (control) · h-lg (bar); the named form of h-(--era-h-*).
|
|
223
|
+
|
|
224
|
+
Declared in `index.css`.
|
|
225
|
+
|
|
226
|
+
```css
|
|
227
|
+
@utility h-xs {
|
|
228
|
+
height: var(--era-h-xs);
|
|
229
|
+
}
|
|
230
|
+
@utility h-xxs {
|
|
231
|
+
height: var(--era-h-xxs);
|
|
232
|
+
}
|
|
233
|
+
@utility h-sm {
|
|
234
|
+
height: var(--era-h-sm);
|
|
235
|
+
}
|
|
236
|
+
@utility h-md {
|
|
237
|
+
height: var(--era-h-md);
|
|
238
|
+
}
|
|
239
|
+
@utility h-lg {
|
|
240
|
+
height: var(--era-h-lg);
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## min-h-xs · min-h-xxs · min-h-sm · min-h-md · min-h-lg
|
|
245
|
+
|
|
246
|
+
**Use it for:** minimum tier height for containers that may grow — a bar that is at least lg-tier but can wrap (min-h-lg).
|
|
247
|
+
|
|
248
|
+
Declared in `index.css`.
|
|
249
|
+
|
|
250
|
+
```css
|
|
251
|
+
@utility min-h-xs {
|
|
252
|
+
min-height: var(--era-h-xs);
|
|
253
|
+
}
|
|
254
|
+
@utility min-h-xxs {
|
|
255
|
+
min-height: var(--era-h-xxs);
|
|
256
|
+
}
|
|
257
|
+
@utility min-h-sm {
|
|
258
|
+
min-height: var(--era-h-sm);
|
|
259
|
+
}
|
|
260
|
+
@utility min-h-md {
|
|
261
|
+
min-height: var(--era-h-md);
|
|
262
|
+
}
|
|
263
|
+
@utility min-h-lg {
|
|
264
|
+
min-height: var(--era-h-lg);
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## size-xs · size-xxs · size-sm · size-md · size-lg
|
|
269
|
+
|
|
270
|
+
**Use it for:** a tier-sized square — size-xs is THE icon size (a Lucide glyph beside body text), size-md a square control face.
|
|
271
|
+
|
|
272
|
+
Declared in `index.css`.
|
|
273
|
+
|
|
274
|
+
```css
|
|
275
|
+
@utility size-xs {
|
|
276
|
+
width: var(--era-h-xs);
|
|
277
|
+
height: var(--era-h-xs);
|
|
278
|
+
}
|
|
279
|
+
@utility size-xxs {
|
|
280
|
+
width: var(--era-h-xxs);
|
|
281
|
+
height: var(--era-h-xxs);
|
|
282
|
+
}
|
|
283
|
+
@utility size-sm {
|
|
284
|
+
width: var(--era-h-sm);
|
|
285
|
+
height: var(--era-h-sm);
|
|
286
|
+
}
|
|
287
|
+
@utility size-md {
|
|
288
|
+
width: var(--era-h-md);
|
|
289
|
+
height: var(--era-h-md);
|
|
290
|
+
}
|
|
291
|
+
@utility size-lg {
|
|
292
|
+
width: var(--era-h-lg);
|
|
293
|
+
height: var(--era-h-lg);
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## px-sm · px-md · px-lg
|
|
298
|
+
|
|
299
|
+
**Use it for:** tier-to-tier nesting padding (sp/2) — the horizontal padding of a bar or row that holds tiered controls; the named form of px-(--era-px-*).
|
|
300
|
+
|
|
301
|
+
Declared in `index.css`.
|
|
302
|
+
|
|
303
|
+
```css
|
|
304
|
+
@utility px-sm {
|
|
305
|
+
padding-inline: var(--era-px-sm);
|
|
306
|
+
}
|
|
307
|
+
@utility px-md {
|
|
308
|
+
padding-inline: var(--era-px-md);
|
|
309
|
+
}
|
|
310
|
+
@utility px-lg {
|
|
311
|
+
padding-inline: var(--era-px-lg);
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## gap-gutter · p-gutter · px-gutter · py-gutter
|
|
316
|
+
|
|
317
|
+
**Use it for:** the inter-element gap (sp/2) — flex/grid gap between sibling controls, and the matching gutter padding a scrollable list or rail owes its rows on all four sides (p-gutter on the rail = gap-gutter between its rows).
|
|
318
|
+
|
|
319
|
+
Declared in `index.css`.
|
|
320
|
+
|
|
321
|
+
```css
|
|
322
|
+
@utility gap-gutter {
|
|
323
|
+
gap: var(--era-gap);
|
|
324
|
+
}
|
|
325
|
+
@utility p-gutter {
|
|
326
|
+
padding: var(--era-gap);
|
|
327
|
+
}
|
|
328
|
+
@utility px-gutter {
|
|
329
|
+
padding-inline: var(--era-gap);
|
|
330
|
+
}
|
|
331
|
+
@utility py-gutter {
|
|
332
|
+
padding-block: var(--era-gap);
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
## p-inset-xxs · p-inset-sm · p-inset-md · px-inset-xxs · px-inset-sm · px-inset-md · py-inset-xxs · py-inset-sm · py-inset-md
|
|
337
|
+
|
|
338
|
+
**Use it for:** text-symmetric content padding — (tier − text)/2, the inset that vertically centers body text in its tier; px-inset-md is a text button's side padding, p-inset-md a code block's.
|
|
339
|
+
|
|
340
|
+
Declared in `index.css`.
|
|
341
|
+
|
|
342
|
+
```css
|
|
343
|
+
@utility p-inset-xxs {
|
|
344
|
+
padding: var(--era-inset-xxs);
|
|
345
|
+
}
|
|
346
|
+
@utility p-inset-sm {
|
|
347
|
+
padding: var(--era-inset-sm);
|
|
348
|
+
}
|
|
349
|
+
@utility p-inset-md {
|
|
350
|
+
padding: var(--era-inset-md);
|
|
351
|
+
}
|
|
352
|
+
@utility px-inset-xxs {
|
|
353
|
+
padding-inline: var(--era-inset-xxs);
|
|
354
|
+
}
|
|
355
|
+
@utility px-inset-sm {
|
|
356
|
+
padding-inline: var(--era-inset-sm);
|
|
357
|
+
}
|
|
358
|
+
@utility px-inset-md {
|
|
359
|
+
padding-inline: var(--era-inset-md);
|
|
360
|
+
}
|
|
361
|
+
@utility py-inset-xxs {
|
|
362
|
+
padding-block: var(--era-inset-xxs);
|
|
363
|
+
}
|
|
364
|
+
@utility py-inset-sm {
|
|
365
|
+
padding-block: var(--era-inset-sm);
|
|
366
|
+
}
|
|
367
|
+
@utility py-inset-md {
|
|
368
|
+
padding-block: var(--era-inset-md);
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
## px-pill-xxs · px-pill-sm
|
|
373
|
+
|
|
374
|
+
**Use it for:** pill side padding — the wider-than-vertical horizontal breathing room badge/chip text wants (glyph-advance derived, ~2× the vertical inset).
|
|
375
|
+
|
|
376
|
+
Declared in `index.css`.
|
|
377
|
+
|
|
378
|
+
```css
|
|
379
|
+
@utility px-pill-xxs {
|
|
380
|
+
padding-inline: var(--era-pill-xxs);
|
|
381
|
+
}
|
|
382
|
+
@utility px-pill-sm {
|
|
383
|
+
padding-inline: var(--era-pill-sm);
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
## px-field
|
|
388
|
+
|
|
389
|
+
**Use it for:** text-field side padding — where typed text starts in an md-tier input; the named form of px-(--era-field-px).
|
|
390
|
+
|
|
391
|
+
Declared in `index.css`.
|
|
392
|
+
|
|
393
|
+
```css
|
|
394
|
+
@utility px-field {
|
|
395
|
+
padding-inline: var(--era-field-px);
|
|
396
|
+
}
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
## p-panel · p-card · p-content
|
|
400
|
+
|
|
401
|
+
**Use it for:** optical padding for unbounded containers — p-panel for compact shells and menu-adjacent chrome, p-card for cards/dialogs/popovers, p-content for full content panels. Grows super-linearly with density so whitespace holds its perceived share as controls loosen.
|
|
402
|
+
|
|
403
|
+
Declared in `index.css`.
|
|
404
|
+
|
|
405
|
+
```css
|
|
406
|
+
@utility p-panel {
|
|
407
|
+
padding: var(--era-pad-sm);
|
|
408
|
+
}
|
|
409
|
+
@utility p-card {
|
|
410
|
+
padding: var(--era-pad-md);
|
|
411
|
+
}
|
|
412
|
+
@utility p-content {
|
|
413
|
+
padding: var(--era-content-p);
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
## p-menu
|
|
418
|
+
|
|
419
|
+
**Use it for:** menu-panel padding — the surface-owned inset (0 on flat, 2px on glass/bevel) that keeps row highlights inside a floating panel's frame; pairs with rounded-item on the rows.
|
|
420
|
+
|
|
421
|
+
Declared in `index.css`.
|
|
422
|
+
|
|
423
|
+
```css
|
|
424
|
+
@utility p-menu {
|
|
425
|
+
padding: var(--era-panel-inset);
|
|
426
|
+
}
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
## duration-base
|
|
430
|
+
|
|
431
|
+
**Use it for:** the motion axis as an explicit transition-duration — for the rare case a utility (not the transition-* default) needs to name it; 0s at data-motion="instant", longer at "extra".
|
|
432
|
+
|
|
433
|
+
Declared in `index.css`.
|
|
434
|
+
|
|
435
|
+
```css
|
|
436
|
+
@utility duration-base {
|
|
437
|
+
transition-duration: var(--era-duration);
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
189
441
|
## glass-blur
|
|
190
442
|
|
|
191
443
|
**Use it for:** 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.
|
package/dist/os/taskbar.svelte
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
floating = false,
|
|
19
19
|
pinned = [],
|
|
20
20
|
showWindows = true,
|
|
21
|
+
showWorkspaces = true,
|
|
21
22
|
commands = [],
|
|
22
23
|
hotkey = ['`', 'Escape'],
|
|
23
24
|
placeholder = 'run a command…',
|
|
@@ -42,6 +43,11 @@
|
|
|
42
43
|
/** Show the open/minimized window tabs (default true). Hidden, windows
|
|
43
44
|
* stay reachable through the command bar's `windows` view. */
|
|
44
45
|
showWindows?: boolean;
|
|
46
|
+
/** Show the multi-workspace UI (default true). Hidden, both the numbered
|
|
47
|
+
* switcher and the command bar's `workspace` view go away — a
|
|
48
|
+
* single-workspace shell. `wm.addWorkspace()` still works for consumers
|
|
49
|
+
* who drive workspaces themselves. */
|
|
50
|
+
showWorkspaces?: boolean;
|
|
45
51
|
/** Extra root commands appended to the built-in ones. */
|
|
46
52
|
commands?: CommandBarItem[];
|
|
47
53
|
/** Focus binding(s) for the command bar (default backtick + Escape). */
|
|
@@ -121,6 +127,7 @@
|
|
|
121
127
|
onSelect: () => wm.focus(w.id)
|
|
122
128
|
}))
|
|
123
129
|
};
|
|
130
|
+
if (!showWorkspaces) return [...apps, windows];
|
|
124
131
|
const workspaces: CommandBarItem = {
|
|
125
132
|
value: 'workspace',
|
|
126
133
|
label: 'workspace',
|
|
@@ -228,8 +235,9 @@
|
|
|
228
235
|
{/if}
|
|
229
236
|
|
|
230
237
|
<!-- Numbered workspace switcher, term-style on the right — appears only
|
|
231
|
-
once there's something to switch between
|
|
232
|
-
|
|
238
|
+
once there's something to switch between (and only when the bar exposes
|
|
239
|
+
workspaces at all). -->
|
|
240
|
+
{#if showWorkspaces && wm.workspaces.length > 1}
|
|
233
241
|
<div class="flex shrink-0 items-center gap-(--era-gap)">
|
|
234
242
|
{#each wm.workspaces as ws, i (ws.id)}
|
|
235
243
|
<Button
|
|
@@ -20,6 +20,11 @@ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
|
|
|
20
20
|
/** Show the open/minimized window tabs (default true). Hidden, windows
|
|
21
21
|
* stay reachable through the command bar's `windows` view. */
|
|
22
22
|
showWindows?: boolean;
|
|
23
|
+
/** Show the multi-workspace UI (default true). Hidden, both the numbered
|
|
24
|
+
* switcher and the command bar's `workspace` view go away — a
|
|
25
|
+
* single-workspace shell. `wm.addWorkspace()` still works for consumers
|
|
26
|
+
* who drive workspaces themselves. */
|
|
27
|
+
showWorkspaces?: boolean;
|
|
23
28
|
/** Extra root commands appended to the built-in ones. */
|
|
24
29
|
commands?: CommandBarItem[];
|
|
25
30
|
/** Focus binding(s) for the command bar (default backtick + Escape). */
|