@apliteni/apliteni-ui 0.33.0 → 0.34.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.
@@ -52,9 +52,13 @@
52
52
  transition: width var(--dur-med) var(--ease);
53
53
  }
54
54
  /* Each block of the rail keeps the open column while the box closes over it. The
55
- nav declares its own; these are the two that are not the nav. */
56
- .ui-app__head,
57
- .ui-app__user { width: var(--ui-nav-col); flex: none; }
55
+ nav declares its own; these are the three that are not the nav. Scoped to the rail,
56
+ because the topbar layout draws the reader's block in its band instead and a column
57
+ the rail's width is no measurement for a box on a 52px line.
58
+ why: docs/specification.md#the-page-shell */
59
+ .ui-app__rail > .ui-app__head,
60
+ .ui-app__rail > .ui-app__user,
61
+ .ui-app__rail > .ui-app__foot { width: var(--ui-nav-col); flex: none; }
58
62
  /* The rail's hover WAS --surface-2, so moving the rail onto it would have made
59
63
  hovering a row do nothing. The danger row and the current row are left out by
60
64
  name, because this rule outranks the states nav.css writes for them.
@@ -105,7 +109,7 @@
105
109
  smallest of three weak signals doing the most work, so it grows with the row. */
106
110
  /* Re-tuned at #295, which took the light rail down a step with the page. Below 720px
107
111
  the glyph is the whole row, so it is held at text grade rather than at 1.4.11's bar —
108
- stories/apps/shell-states.test.js:1340 `a resting glyph is dimmer but still legible`. */
112
+ stories/apps/shell-states.test.js:1400 `a resting glyph is dimmer but still legible`. */
109
113
  .ui-app__rail .ui-nav__ic svg { opacity: 0.66; }
110
114
  .ui-app__rail .ui-nav__item.is-active .ui-nav__ic svg,
111
115
  .ui-app__rail .ui-nav__item.is-current .ui-nav__ic svg { opacity: 1; stroke: currentColor; } /* motion: still — the glyph brightens with its row, whose own highlight already transitions */
@@ -128,6 +132,18 @@
128
132
  padding-top: var(--space-5);
129
133
  border-top: 1px solid var(--border);
130
134
  }
135
+ /* The other thing that can close a rail: where the reader's block is in the band,
136
+ the fold's control takes its place under the same rule.
137
+ why: docs/specification.md#the-page-shell */
138
+ .ui-app__foot {
139
+ display: flex;
140
+ align-items: center;
141
+ padding-top: var(--space-5);
142
+ border-top: 1px solid var(--border);
143
+ }
144
+ /* On the glyph column from the first frame, so the fold moves it nowhere — the ride
145
+ along the closing edge belongs to the head band, where the mark holds that column. */
146
+ .ui-app__foot > .ui-app__fold-row { margin-inline-start: 0; }
131
147
  /* The avatar is the reader block's own glyph, so half the difference between the
132
148
  glyph column and itself is the inset that centres it on the line every glyph above
133
149
  it stands on. The arithmetic and not the 5.5 it comes to: both numbers are declared
@@ -231,17 +247,29 @@
231
247
  where the control arrives: below 720px the toggle is not drawn, so the 720px block
232
248
  gives the lockup back rather than leaving an empty band with a hairline under it.
233
249
  why: docs/specification.md#the-page-shell */
234
- :where(.ui-app.is-collapsed) .ui-app__fold-row { inset-inline-start: calc(var(--ui-nav-strip) - var(--ui-nav-col)); }
235
- :where(.ui-app.is-collapsed) .ui-app__brand { opacity: 0; visibility: hidden; pointer-events: none; }
250
+ :where(.ui-app.is-collapsed) .ui-app__head > .ui-app__fold-row { inset-inline-start: calc(var(--ui-nav-strip) - var(--ui-nav-col)); }
251
+ /* …and only in the layout where something arrives on the mark's column. In the
252
+ topbar layout the toggle is at the rail's foot, nothing lands where the mark
253
+ stands, and a lockup faded out there leaves a band with nothing in it and its
254
+ hairline still under it — the defect the 720px block below exists to avoid. So
255
+ that layout keeps the mark and lets the shared rule above fold away its words.
256
+ why: docs/specification.md#the-page-shell */
257
+ :where(.ui-app:not(.ui-app--topbar).is-collapsed) .ui-app__brand { opacity: 0; visibility: hidden; pointer-events: none; }
236
258
  :where(.ui-app.is-collapsed) .ui-app__rail .ui-nav__sub { margin-inline-start: 0; padding-inline-start: 0; border-inline-start-width: 0; }
237
259
  :where(.ui-app.is-collapsed) .ui-app__rail .ui-nav__item:not(:has(.ui-nav__ic))::after { opacity: 0.62; }
238
260
  /* The label IS the chip. `fixed` is the fallback placement, out of the rail's own
239
261
  clip; the @supports branch below pins it to the row and is the only one that
240
262
  survives a scroll. The toggle's selector is unscoped, because it is wordless at
241
- both widths. why: docs/specification.md#the-page-shell */
263
+ both widths.
264
+
265
+ It floats by role — a readout placed over the page for as long as a pointer
266
+ rests on a row — so it takes the floating treatment the hover readout takes,
267
+ which is the same shape on the same step: the two-step edge and the drops.
268
+ why: docs/specification.md#the-page-shell
269
+ why: docs/specification.md#elevation */
242
270
  :where(.ui-app.is-collapsed) .ui-app__rail .ui-nav__item:is(:hover, :focus-visible) > .ui-nav__label,
243
271
  :where(.ui-app.is-collapsed) .ui-app__rail .ui-app__user-trigger:is(:hover, :focus-visible) > .ui-app__who,
244
- .ui-app__rail .ui-app__fold:is(:hover, :focus-visible) > .ui-nav__label { position: fixed; left: calc(var(--ui-rail-w) + var(--space-2)); z-index: var(--z-dropdown); width: max-content; max-width: 15rem; margin-block: -7px; padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--radius-xs); background: var(--surface-3); color: var(--strong); box-shadow: var(--shadow-md); opacity: 1; pointer-events: none; }
272
+ .ui-app__rail .ui-app__fold:is(:hover, :focus-visible) > .ui-nav__label { position: fixed; left: calc(var(--ui-rail-w) + var(--space-2)); z-index: var(--z-dropdown); width: max-content; max-width: 15rem; margin-block: -7px; padding: 6px 10px; border: 1px solid var(--border-strong); box-shadow: inset 0 0 0 1px var(--elev-edge, var(--border)), var(--elev-drop); border-radius: var(--radius-xs); background: var(--surface-3); color: var(--strong); opacity: 1; pointer-events: none; }
245
273
  @supports (anchor-name: --a) and (anchor-scope: --a) {
246
274
  .ui-app.is-collapsed,
247
275
  .ui-app:has(.ui-app__fold) { anchor-scope: --ui-rail; }
@@ -271,6 +299,80 @@
271
299
  margin-inline: auto;
272
300
  padding: 40px clamp(24px, 4vw, 56px) 72px;
273
301
  }
302
+ /* The whole of the difference: `centered` is the rule above and `wide` takes its cap
303
+ off. `maxWidth` is the number under either name. why: docs/specification.md#widths */
304
+ .ui-app__main--wide { max-width: var(--ui-app-main, none); }
305
+
306
+ /* -- The topbar layout ----------------------------------------------------- */
307
+ /* The band stands BESIDE the rail, not across the top of both, which is the
308
+ arrangement where the rail's head band and the band close at the same height — what
309
+ the three heights below are for. Level, not one continuous stroke: the rail insets
310
+ its own rule, and in light that half is 1.009:1 on the rail's ground.
311
+ why: docs/specification.md#the-second-layout */
312
+ .ui-app { --ui-app-band: 52px; }
313
+ .ui-app__well { display: flex; flex-direction: column; min-width: 0; }
314
+ .ui-app__bar {
315
+ display: flex;
316
+ align-items: center;
317
+ gap: var(--space-3);
318
+ height: var(--ui-app-band);
319
+ flex: none;
320
+ padding-inline: clamp(24px, 4vw, 56px);
321
+ background: var(--bg);
322
+ border-bottom: 1px solid var(--border);
323
+ /* Sticky for the reason the rail beside it is: chrome that scrolls away is chrome
324
+ you scroll back up for. */
325
+ position: sticky;
326
+ top: 0;
327
+ z-index: var(--z-sticky);
328
+ }
329
+ .ui-app__bar-gap { flex: 1 1 auto; }
330
+ /* The rail's two bands take the band's height, so the rule under the head lands on
331
+ the line the band's own rule lands on. The rail gives up its top inset to buy it. */
332
+ .ui-app--topbar > .ui-app__rail { padding-top: 0; }
333
+ .ui-app--topbar > .ui-app__rail > .ui-app__head { height: var(--ui-app-band); padding-bottom: 0; }
334
+ .ui-app--topbar > .ui-app__rail > .ui-app__foot { height: var(--ui-app-band); padding-top: 0; }
335
+
336
+ /* Drawn as a field, behaving as a button. The ladder is the field's — the sunken
337
+ step, the hairline and the radius src/styles/input.css:20 `.ui-input` sets — because
338
+ what it looks like is the point. It gives way before anything else on the band.
339
+ why: docs/specification.md#the-page-shell */
340
+ .ui-app__search {
341
+ display: flex;
342
+ align-items: center;
343
+ gap: var(--space-2);
344
+ flex: 0 1 var(--panel-sm);
345
+ min-width: 0;
346
+ padding: 7px 10px;
347
+ /* A family alone leaves the browser's leading behind: `font: inherit` first, then
348
+ the one step this row takes. why: CONTRIBUTING.md#button-chrome-ledgers */
349
+ font: inherit;
350
+ font-size: var(--text-sm);
351
+ text-align: start;
352
+ color: var(--muted);
353
+ background: var(--surface-2);
354
+ border: 1px solid var(--border);
355
+ border-radius: var(--radius-md);
356
+ cursor: pointer;
357
+ transition: border-color var(--dur-med) var(--ease), color var(--dur-med) var(--ease);
358
+ }
359
+ .ui-app__search:hover { border-color: var(--border-strong); color: var(--strong); }
360
+ /* The same glyph the palette draws in its own search box, at the same box and the
361
+ same stroke: the trigger and the thing it opens are not two search marks.
362
+ src/styles/command-palette.css:107 `.ui-cmdk__search-ic svg` */
363
+ .ui-app__search-ic { display: flex; flex: none; }
364
+ .ui-app__search-ic svg { width: 17px; height: 17px; stroke: currentColor; fill: none; stroke-width: 2.2; }
365
+ /* Part of the button's name, so it is squeezed rather than dropped: an ellipsis
366
+ still leaves the whole string in the tree. */
367
+ .ui-app__search-txt { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
368
+ /* The other half of the name, so it never gives way. */
369
+ .ui-app__search kbd { flex: none; }
370
+
371
+ /* The mark alone — no room for two lines on a 52px row. No rule over it, since the
372
+ band's hairline is under the whole of it, and no column, since this is not the rail.
373
+ why: docs/specification.md#the-page-shell */
374
+ .ui-app__user--bar { flex: none; padding-top: 0; border-top: 0; }
375
+ .ui-app__user--bar .ui-app__av { margin-inline-start: 0; }
274
376
  /* Crumb, then the title block. At --space-2 the crumb sat 8px off the h1 and
275
377
  the h1 8px off its subtitle, so all three ranks read as one. */
276
378
  .ui-app__main .ui-nav--crumbs { margin-bottom: var(--space-5); }
@@ -315,6 +417,11 @@
315
417
  .ui-app { --ui-rail-w: calc(var(--ui-nav-strip) + 2 * var(--space-4) + var(--ui-rail-rule)); }
316
418
  /* The strip is the only layout this width has, so there is nothing to fold. */
317
419
  .ui-app__rail .ui-app__fold-row { display: none; }
420
+ /* …and the foot goes with it, for the reason the head band does below: in the
421
+ topbar layout that box holds the toggle and nothing else, so at this width it is
422
+ padding and a hairline drawn over nothing. Scoped to the shell's own rail, like
423
+ every other rule in this block. why: docs/specification.md#the-page-shell */
424
+ .ui-app__rail .ui-app__foot { display: none; }
318
425
  /* …and with it the band, when the band has nothing else in it: a head with no
319
426
  wordmark is the toggle alone, so at this width it is padding and a hairline
320
427
  drawn over nothing. The reader's fold cannot take this rule — there the toggle
@@ -343,7 +450,7 @@
343
450
  .ui-app__rail .ui-nav__item,
344
451
  .ui-app__rail .ui-app__user-trigger { min-height: 44px; }
345
452
  .ui-app__rail .ui-nav__item:is(:hover, :focus-visible) > .ui-nav__label,
346
- .ui-app__rail .ui-app__user-trigger:is(:hover, :focus-visible) > .ui-app__who { position: fixed; left: calc(var(--ui-rail-w) + var(--space-2)); z-index: var(--z-dropdown); width: max-content; max-width: 15rem; margin-block: -7px; padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--radius-xs); background: var(--surface-3); color: var(--strong); box-shadow: var(--shadow-md); opacity: 1; pointer-events: none; }
453
+ .ui-app__rail .ui-app__user-trigger:is(:hover, :focus-visible) > .ui-app__who { position: fixed; left: calc(var(--ui-rail-w) + var(--space-2)); z-index: var(--z-dropdown); width: max-content; max-width: 15rem; margin-block: -7px; padding: 6px 10px; border: 1px solid var(--border-strong); box-shadow: inset 0 0 0 1px var(--elev-edge, var(--border)), var(--elev-drop); border-radius: var(--radius-xs); background: var(--surface-3); color: var(--strong); opacity: 1; pointer-events: none; }
347
454
  @supports (anchor-name: --a) and (anchor-scope: --a) {
348
455
  .ui-app { anchor-scope: --ui-rail; }
349
456
  .ui-app__rail { anchor-name: --ui-rail; }
@@ -26,7 +26,10 @@
26
26
  max-width: var(--prose-caption);
27
27
  padding: var(--space-2) var(--space-3);
28
28
  background: var(--ui-tip-bg);
29
- border: 1px solid var(--border);
29
+ /* The two-step edge and the drop: --border-strong outside, --border one pixel
30
+ inside it, then the broad faint drop. why: docs/specification.md#elevation */
31
+ border: 1px solid var(--border-strong);
32
+ box-shadow: inset 0 0 0 1px var(--elev-edge, var(--border)), var(--elev-drop);
30
33
  border-radius: var(--radius-sm);
31
34
  font-family: var(--font-sans);
32
35
  font-size: var(--text-xs);
@@ -123,7 +123,10 @@
123
123
  left: 0;
124
124
  min-width: 266px;
125
125
  background: var(--bg-elevated); /* the floating step — see dropdown.css. #295 */
126
- border: 1px solid var(--border);
126
+ /* The two-step edge and the drop: --border-strong outside, --border one pixel
127
+ inside it, then the broad faint drop. why: docs/specification.md#elevation */
128
+ border: 1px solid var(--border-strong);
129
+ box-shadow: inset 0 0 0 1px var(--elev-edge, var(--border)), var(--elev-drop);
127
130
  border-radius: 16px;
128
131
  padding: 6px;
129
132
  opacity: 0;
@@ -177,7 +180,8 @@
177
180
  transition: background var(--dur-fast) var(--ease);
178
181
  }
179
182
  /* The menu is raised, so a hovered row takes the step ABOVE it — see
180
- src/styles/dropdown.css:130. why: docs/specification.md#elevation */
183
+ src/styles/dropdown.css:155 `.ui-dropdown__item:hover`.
184
+ why: docs/specification.md#elevation */
181
185
  .vopt:hover { background: var(--surface-3); }
182
186
  .vopt .vname { font-family: var(--font-sans); font-size: 12.5px; color: var(--strong); font-weight: 600; letter-spacing: 0.01em; }
183
187
  .vopt .vmeta { font-size: 11px; color: var(--muted); margin-top: 2px; }
@@ -222,7 +226,10 @@
222
226
  right: 0; top: 44px;
223
227
  width: 252px;
224
228
  background: var(--bg-elevated); /* the floating step — see dropdown.css. #295 */
225
- border: 1px solid var(--border);
229
+ /* The two-step edge and the drop: --border-strong outside, --border one pixel
230
+ inside it, then the broad faint drop. why: docs/specification.md#elevation */
231
+ border: 1px solid var(--border-strong);
232
+ box-shadow: inset 0 0 0 1px var(--elev-edge, var(--border)), var(--elev-drop);
226
233
  border-radius: 14px;
227
234
  overflow: hidden;
228
235
  opacity: 0;
@@ -133,9 +133,10 @@
133
133
  --pink: #e97ca5;
134
134
  --amber: #ffcf6a;
135
135
 
136
- /* The elevation ladder, bottom to top. Nothing casts; a surface says how high it is
137
- with its step and with the hairline around it, and --muted caps how far the ladder
138
- can go. why: docs/specification.md#elevation */
136
+ /* The elevation ladder, bottom to top. A surface says how high it is with its step and
137
+ with the hairline around it, and --muted caps how far the ladder can go. Nothing casts
138
+ below the floating step; the floating step itself adds --elev-drop under its inner
139
+ line and nothing else in the kit does. why: docs/specification.md#elevation */
139
140
  --bg: #0e0d14;
140
141
  --surface-2: #161520; /* SUNKEN — fields, tracks, disabled, code */
141
142
  --surface: #211e2d; /* the card */
@@ -214,9 +215,10 @@
214
215
  --signal-solid-info: var(--cyan);
215
216
  --signal-solid-neutral: var(--muted);
216
217
 
217
- /* DEPRECATED since #295: the kit casts no shadow anywhere. Published still, so a
218
- consumer reading one gets nothing rather than an unresolved var(), and a consumer who
219
- wants a cast shadow sets them. Nothing in src/ reads them.
218
+ /* DEPRECATED since #295: no surface below the floating step casts, and the floating
219
+ step reads --elev-drop rather than any of these. Published still, so a consumer
220
+ reading one gets nothing rather than an unresolved var(), and a consumer who wants a
221
+ cast shadow sets them. Nothing in src/ reads them.
220
222
 
221
223
  A transparent shadow, not `none`, because these are read in a LIST. The kit's own
222
224
  pre-0.32 pattern was `box-shadow: var(--shadow-lg), var(--ring)`, and `none` is only
@@ -239,6 +241,18 @@
239
241
  --shadow-ink: #000000;
240
242
  --sheen: #ffffff;
241
243
 
244
+ /* The drops of the floating treatment, in Primer's --shadow-floating-* order:
245
+ the inner half of the two-step edge, then these. The line is NOT in this
246
+ token and cannot be — a var() inside a custom property is substituted on the
247
+ element that DECLARES it, so an --elev-edge read here resolves at :root and
248
+ nothing below could re-point it. A floating surface writes the pair itself:
249
+ box-shadow: inset 0 0 0 1px var(--elev-edge, var(--border)), var(--elev-drop);
250
+ Dark spends 62% / 50% of the ink and reaches 1.20 at the drop's core, having
251
+ nowhere to go on a near-black page. why: docs/specification.md#elevation */
252
+ --elev-drop:
253
+ 0 14px 30px -12px color-mix(in srgb, var(--shadow-ink) 62%, transparent),
254
+ 0 3px 9px -4px color-mix(in srgb, var(--shadow-ink) 50%, transparent);
255
+
242
256
  /* Backdrop that dims the page behind an overlay (drawer, modal, composer). */
243
257
  --scrim: rgba(0, 0, 0, 0.58);
244
258
 
@@ -345,6 +359,13 @@
345
359
  --shadow-ink: #1e1e32;
346
360
  --sheen: #ffffff;
347
361
 
362
+ /* 18% / 10% against dark's 62% / 50%. Light's ink is #1e1e32 on a card at
363
+ #f8f9fc, and 18% is what puts the drop core at #d1d2d8 — 1.44, the strongest
364
+ separation either theme gets. why: docs/specification.md#elevation */
365
+ --elev-drop:
366
+ 0 14px 30px -12px color-mix(in srgb, var(--shadow-ink) 18%, transparent),
367
+ 0 3px 9px -4px color-mix(in srgb, var(--shadow-ink) 10%, transparent);
368
+
348
369
  --scrim: rgba(20, 22, 40, 0.38);
349
370
 
350
371
  --grad-from: var(--purple-light);