@signal9/era-ui 2.26.0 → 2.27.1

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.
@@ -36,7 +36,10 @@
36
36
  }
37
37
 
38
38
  /* Shared interactive-state recipe: quiet focus, disabled affordance.
39
- * Equivalent to `focus:outline-none disabled:cursor-not-allowed disabled:opacity-50`. */
39
+ * Equivalent to `focus:outline-none disabled:cursor-not-allowed disabled:opacity-50`.
40
+ *
41
+ * @use the focus/disabled recipe every era control carries — put it on a custom
42
+ * interactive element instead of hand-writing focus/disabled variants. */
40
43
  @utility era-interactive {
41
44
  &:focus {
42
45
  outline: none;
@@ -54,7 +57,11 @@
54
57
  * "extra" — matching every other era transition. Font-agnostic: it styles
55
58
  * decoration + colour only, so it reads correctly in mono, sans, or serif, and
56
59
  * the 0.2em offset scales with the type size. Keyboard focus mirrors hover so
57
- * the affordance is reachable without a pointer. */
60
+ * the affordance is reachable without a pointer.
61
+ *
62
+ * @use understated, motion-aware inline text link — the canonical style for a
63
+ * link in body copy or prose; prefer it over a hand-rolled underline or
64
+ * `Button variant="link"` (which is a control, not running text). */
58
65
  @utility era-link {
59
66
  /* The text is bright at rest and never changes — the link reads as a link
60
67
  * before you touch it. Only the UNDERLINE reacts: a faint half-strength-muted
@@ -71,7 +78,10 @@
71
78
  }
72
79
 
73
80
  /* Scrollable but chromeless — hides the scrollbar while keeping wheel / touch /
74
- * drag scrolling (e.g. an overflowing tab strip in a small pane handle). */
81
+ * drag scrolling (e.g. an overflowing tab strip in a small pane handle).
82
+ *
83
+ * @use hide the scrollbar on an overflowing strip or rail while keeping it
84
+ * scrollable — for a scroll region that should show its bar, use ScrollArea. */
75
85
  @utility scrollbar-none {
76
86
  scrollbar-width: none;
77
87
  &::-webkit-scrollbar {
@@ -91,16 +101,29 @@
91
101
  * Where text-box is supported it fully determines the box, so the two
92
102
  * declarations never fight. Worst-case residual: 0.44px.
93
103
  *
94
- * The one hard rule concerns overflow clipping, and it is HEIGHT-conditional.
95
- * On an AUTO-height element that also clips — a `truncate` child, a
96
- * <textarea>, an auto-height <input> trim-both collapses the box to the
97
- * x-height band (~7.5px at 14px) and the clip slices off every ascender, cap,
98
- * and descender (text renders as a chopped middle stripe): NEVER do that.
99
- * A FIXED-height control is the intended home, and is safe: the explicit
100
- * `h-(--era-*)` overrides the collapse, so a single-line <input> (Input,
101
- * command-input) and clipping display tokens (KV) correctly carry it. For
102
- * truncating text, put the trim on the fixed-height ROW and let the child
103
- * center via the row's items-center.
104
+ * The hard rules concern overflow clipping, and there are TWO of them.
105
+ *
106
+ * 1. NEVER on a NATIVE EDITABLE — <input>, <textarea>, <select>. These clip to
107
+ * a UA-owned inner editor box that IS the trimmed line box, so a fixed
108
+ * height does NOT hold it open: whatever you type gets its ascenders and
109
+ * descenders sliced off (a "d" renders as an "o"). This rule used to read
110
+ * the other way round it claimed a fixed-height <input> was the trim's
111
+ * intended home and the Input component shipped chopped text as a result.
112
+ * A tier-height input centres its own text; it needs no trim.
113
+ *
114
+ * 2. NEVER on an AUTO-height element that clips — a `truncate` child, an
115
+ * auto-height box with overflow-hidden. With no height to hold it open the
116
+ * box collapses to the x-height band (~7.5px at 14px) and the clip chops the
117
+ * glyphs into a middle stripe. Put the trim on the fixed-height ROW instead
118
+ * and let the child centre via the row's items-center.
119
+ *
120
+ * A fixed-height NON-editable element is the safe home: the ink overflows the
121
+ * trimmed LINE box but stays inside the padding box, which is what actually
122
+ * clips. Both rules are enforced at runtime by typography/collapsed-text-trim.
123
+ *
124
+ * @use vertically center single-line control text (a label beside an icon, a
125
+ * button's own text) without a translateY nudge — fixed-height, non-editable
126
+ * elements only; see era-text-trim-caps for ALL-CAPS strings.
104
127
  */
105
128
  @utility era-text-trim {
106
129
  line-height: 1;
@@ -108,7 +131,10 @@
108
131
  }
109
132
 
110
133
  /* ALL-CAPS single-line text (kbd hints, acronym badges): the x-height band
111
- * misjudges caps-only strings — cap/alphabetic edges are the right box. */
134
+ * misjudges caps-only strings — cap/alphabetic edges are the right box.
135
+ *
136
+ * @use the era-text-trim variant for ALL-CAPS single-line strings (kbd hints,
137
+ * acronym badges) — never use it for mixed-case text. */
112
138
  @utility era-text-trim-caps {
113
139
  line-height: 1;
114
140
  text-box: trim-both cap alphabetic;
@@ -118,7 +144,10 @@
118
144
  * "working…" label treatment in streaming UIs). Timing derives from the motion
119
145
  * axis (10× --era-duration ≈ 1.5s at normal, 2.6s at extra); at instant the
120
146
  * duration is 0s and the sweep freezes on its base frame — plain muted text —
121
- * so reduced-motion and data-motion="instant" both kill it for free. */
147
+ * so reduced-motion and data-motion="instant" both kill it for free.
148
+ *
149
+ * @use the in-progress text treatment — put it on a "working…" / "thinking…"
150
+ * label while a task streams, instead of a spinner beside the text. */
122
151
  @utility era-shimmer {
123
152
  background: linear-gradient(
124
153
  110deg,
@@ -118,7 +118,11 @@
118
118
  }
119
119
 
120
120
  /* Tailwind v4 cannot resolve var() inside backdrop-blur-[], so the filter
121
- * is a registered utility, gated to glass subtrees. */
121
+ * is a registered utility, gated to glass subtrees.
122
+ *
123
+ * @use the backdrop blur for a floating panel (popover, dialog, taskbar) — it
124
+ * applies only inside a data-surface="glass" subtree and is inert elsewhere,
125
+ * so it is safe to leave on a panel that renders under every surface. */
122
126
  @utility glass-blur {
123
127
  [data-surface='glass'] & {
124
128
  backdrop-filter: blur(var(--era-blur)) saturate(var(--era-saturate));
@@ -16,7 +16,11 @@
16
16
  bind:this={ref}
17
17
  bind:value
18
18
  class={cn(
19
- 'flex h-(--era-h-md) w-full era-interactive rounded-(--era-rd-md) bg-(--era-surface-bg-elevated) px-(--era-inset-md) text-body era-text-trim text-fg shadow-(--era-shadow-well) placeholder:text-muted hover:bg-(--era-highlight) focus:bg-(--era-highlight)',
19
+ // No era-text-trim here: an <input> clips to a UA-owned inner editor box that
20
+ // IS the trimmed line box, so the trim slices the ascenders and descenders off
21
+ // what you type (a "d" renders as an "o"). The fixed tier height centres the
22
+ // text on its own. See the utility's note in styles/index.css.
23
+ 'flex h-(--era-h-md) w-full era-interactive rounded-(--era-rd-md) bg-(--era-surface-bg-elevated) px-(--era-inset-md) text-body text-fg shadow-(--era-shadow-well) placeholder:text-muted hover:bg-(--era-highlight) focus:bg-(--era-highlight)',
20
24
  className
21
25
  )}
22
26
  {...restProps}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signal9/era-ui",
3
- "version": "2.26.0",
3
+ "version": "2.27.1",
4
4
  "scripts": {
5
5
  "dev": "vite dev --host",
6
6
  "build": "vite build && npm run prepack",
@@ -65,7 +65,8 @@
65
65
  },
66
66
  "./css": "./dist/era-ui.css",
67
67
  "./styles/raw": "./dist/styles/index.css",
68
- "./styles/themes": "./dist/styles/themes.css"
68
+ "./styles/themes": "./dist/styles/themes.css",
69
+ "./utilities.json": "./dist/generated-docs/utilities.json"
69
70
  },
70
71
  "peerDependencies": {
71
72
  "svelte": "^5.0.0",
package/skill/SKILL.md CHANGED
@@ -115,6 +115,23 @@ motion-axis-aware for free.
115
115
  - Headings balance and prose wraps pretty automatically — don't re-add
116
116
  `text-balance`/`text-pretty` except on non-semantic prose elements.
117
117
 
118
+ ## CSS utilities (classes, not components)
119
+
120
+ Not everything era exposes is a component — these ride along with the stylesheet
121
+ and need no import. Reach for one before hand-rolling the same styling or bending
122
+ a component into the role. Full reference: `/utilities.md`; machine-readable list:
123
+ `/utilities.json` (or `@sig-nine/era-ui/utilities.json`).
124
+
125
+ | Class | Use it for |
126
+ | -------------------- | ---------------------------------------------------------------------------------------------------------------------- |
127
+ | `era-link` | inline text link in body copy/prose — NOT `Button variant="link"` (that's a control) and never a hand-rolled underline |
128
+ | `era-interactive` | the focus/disabled recipe on a custom control (every era wrapper carries it) |
129
+ | `era-text-trim` | ink-centering single-line control text beside an icon; fixed-height elements only |
130
+ | `era-text-trim-caps` | the same for ALL-CAPS strings (kbd hints, acronym badges) |
131
+ | `era-shimmer` | a "working…" / streaming label — motion-aware, dies at `instant` and under reduced-motion |
132
+ | `scrollbar-none` | an overflowing strip that scrolls with no visible bar (ScrollArea is for when the bar IS the design) |
133
+ | `glass-blur` | backdrop blur on a floating panel; inert outside a `data-surface="glass"` subtree |
134
+
118
135
  ## Composing the library
119
136
 
120
137
  ```svelte