@apliteni/apliteni-ui 0.100.0 → 0.103.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apliteni/apliteni-ui",
3
- "version": "0.100.0",
3
+ "version": "0.103.0",
4
4
  "workspaces": [
5
5
  "react"
6
6
  ],
@@ -36,10 +36,10 @@
36
36
  --tap-clear-y: 0px;
37
37
  }
38
38
  @media (max-width: 560px) and (pointer: coarse) {
39
- :where(.ui-seg button, .ui-tabs__tab, .ui-dropdown__trigger, .ui-toast__action, .ui-drawer__close, .ui-snippet__copy, .ui-footer__social, .ui-datepicker__opt) {
39
+ :where(.ui-seg button, .ui-tabs__tab, .ui-dropdown__trigger, .ui-toast__action, .ui-drawer__close, .ui-snippet__copy, .ui-footer__social, .ui-app__search, .toggle, .ui-datepicker__opt) {
40
40
  position: relative;
41
41
  }
42
- :where(.ui-btn, .ui-seg button, .ui-tabs__tab, .ui-dropdown__trigger, .ui-toast__action, .ui-drawer__close, .ui-snippet__copy, .ui-footer__social, .ui-switch, .ui-datepicker__opt)::after {
42
+ :where(.ui-btn, .ui-seg button, .ui-tabs__tab, .ui-dropdown__trigger, .ui-toast__action, .ui-drawer__close, .ui-snippet__copy, .ui-footer__social, .ui-switch, .ui-datepicker__opt, .ui-app__search, .toggle)::after {
43
43
  content: "";
44
44
  position: absolute;
45
45
  left: 50%;
@@ -133,6 +133,11 @@
133
133
  --tap-clear-x: var(--tap-gap);
134
134
  --tap-clear-y: var(--tap-gap);
135
135
  }
136
+ .ui-app__bar,
137
+ .topbar__in {
138
+ --tap-clear-x: var(--space-3, 12px);
139
+ --tap-clear-y: var(--space-3, 12px);
140
+ }
136
141
  }
137
142
 
138
143
  /* ../src/styles/tooltip.css */
@@ -872,12 +877,6 @@
872
877
  .ui-react-app .ui-app__bar {
873
878
  padding-inline: var(--space-4);
874
879
  }
875
- .ui-react-app .ui-app__search {
876
- min-width: 0;
877
- }
878
- .ui-react-app .ui-app__search kbd {
879
- display: none;
880
- }
881
880
  .ui-react-app .ui-app__bar > .ui-app__brand {
882
881
  display: none;
883
882
  }
@@ -776,6 +776,10 @@ type AppShellProps = {
776
776
  lede?: string;
777
777
  actions?: ReactNode;
778
778
  bandControl?: ReactNode;
779
+ /** The band trigger's words. Below 560px the shell draws `searchShortLabel` instead;
780
+ * both stay the button's name, which does not change with the viewport. */
781
+ searchLabel?: string;
782
+ searchShortLabel?: string;
779
783
  account: {
780
784
  name: string;
781
785
  email: string;
@@ -787,7 +791,7 @@ type AppShellProps = {
787
791
  /** Spread linkProps onto the router link, including children and onClick. */
788
792
  renderLink?: (section: AppShellSection, linkProps: ComponentPropsWithoutRef<'a'>) => ReactNode;
789
793
  };
790
- declare function AppShell({ sections, pathname, title, children, word, brand, brandHref, width, back, lede, actions, bandControl, account, onSignOut, defaultCollapsed, palette, renderLink }: AppShellProps): react.JSX.Element;
794
+ declare function AppShell({ sections, pathname, title, children, word, brand, brandHref, width, back, lede, actions, bandControl, account, onSignOut, searchLabel, searchShortLabel, defaultCollapsed, palette, renderLink }: AppShellProps): react.JSX.Element;
791
795
 
792
796
  type EmptyStateVariant = 'first-run' | 'no-matches' | 'not-found' | 'not-yet-built';
793
797
  type EmptyStateProps = {
@@ -3407,6 +3407,8 @@ function AppShell({
3407
3407
  bandControl,
3408
3408
  account,
3409
3409
  onSignOut,
3410
+ searchLabel = "Search or run a command\u2026",
3411
+ searchShortLabel = "Search",
3410
3412
  defaultCollapsed = false,
3411
3413
  palette,
3412
3414
  renderLink
@@ -3514,7 +3516,8 @@ function AppShell({
3514
3516
  !navigable && lockup,
3515
3517
  /* @__PURE__ */ jsxs29("button", { type: "button", className: "ui-app__search", "aria-haspopup": "dialog", onClick: () => setSearch(true), children: [
3516
3518
  /* @__PURE__ */ jsx34("span", { className: "ui-app__search-ic", children: /* @__PURE__ */ jsx34(Icon, { name: "search" }) }),
3517
- /* @__PURE__ */ jsx34("span", { className: "ui-app__search-txt", children: "Search or run a command\u2026" }),
3519
+ /* @__PURE__ */ jsx34("span", { className: "ui-app__search-txt", children: searchLabel }),
3520
+ /* @__PURE__ */ jsx34("span", { className: "ui-app__search-short", "aria-hidden": "true", children: searchShortLabel }),
3518
3521
  /* @__PURE__ */ jsx34("kbd", { className: "ui-cmdk__key", children: paletteHotkey() })
3519
3522
  ] }),
3520
3523
  /* @__PURE__ */ jsx34("span", { className: "ui-app__bar-gap" }),
@@ -91,12 +91,17 @@ const toWidth = (v) => (v === 'wide' ? 'wide' : 'centered');
91
91
 
92
92
  // `search: 'palette-id'`, or the same id in `{ palette }` with a placeholder beside
93
93
  // it. No palette to open, no field — the argument `signOutHref` takes.
94
- // why: docs/components.md#the-page-shell
94
+ // `shortLabel` is the word the band draws below 560px, where the sentence used to
95
+ // truncate mid-word. why: docs/components.md#the-page-shell
95
96
  const toSearch = (v) => {
96
97
  const given = typeof v === 'string' ? { palette: v } : (isRecord(v) && !Array.isArray(v) ? v : null);
97
98
  const palette = given && typeof given.palette === 'string' ? given.palette.trim() : '';
98
99
  if (!palette) return null;
99
- return { palette, placeholder: str(given.placeholder) || 'Search or run a command…' };
100
+ return {
101
+ palette,
102
+ placeholder: str(given.placeholder) || 'Search or run a command…',
103
+ shortLabel: str(given.shortLabel) || 'Search',
104
+ };
100
105
  };
101
106
 
102
107
  // `maxWidth` lands inside a style attribute, so a length is all this accepts — a number
@@ -236,10 +241,13 @@ function readerBlock({ name, email }, signOutHref, { band = false } = {}) {
236
241
  // A field to look at, a button to press. `data-cmdk-open` and the cap's class are the
237
242
  // palette's own, and the cap is NOT aria-hidden: it is half the button's name.
238
243
  // why: docs/components.md#the-page-shell
239
- const searchField = ({ palette, placeholder }) =>
244
+ // The short word repeats the sentence, so it is `aria-hidden`: the sentence and the
245
+ // cap are the name at every width, and layout.css clips rather than drops them.
246
+ const searchField = ({ palette, placeholder, shortLabel }) =>
240
247
  `<button type="button" class="ui-app__search" data-cmdk-open="${esc(palette)}" aria-haspopup="dialog">`
241
248
  + `<span class="ui-app__search-ic" aria-hidden="true">${icon('search')}</span>`
242
249
  + `<span class="ui-app__search-txt">${esc(placeholder)}</span>`
250
+ + `<span class="ui-app__search-short" aria-hidden="true">${esc(shortLabel)}</span>`
243
251
  + `<kbd class="ui-cmdk__key" data-palette-hotkey>${esc(paletteHotkey())}</kbd>`
244
252
  + `</button>`;
245
253
 
@@ -119,7 +119,7 @@
119
119
  resting step. */
120
120
  /* Re-tuned at #295, which took the light rail down a step with the page. Below 720px
121
121
  the glyph is the whole row, so it is held at text grade rather than at 1.4.11's bar —
122
- stories/apps/shell-states.test.js:1597 `a resting glyph is dimmer but still legible`. */
122
+ stories/apps/shell-states.test.js:1704 `a resting glyph is dimmer but still legible`. */
123
123
  .ui-app__rail .ui-nav__ic svg { opacity: 0.66; }
124
124
 
125
125
  /* A destructive row of the rail is a navigation row and rests like one; the danger
@@ -404,11 +404,26 @@
404
404
  .ui-app__search-txt { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
405
405
  /* The other half of the name, so it never gives way. */
406
406
  .ui-app__search kbd { flex: none; }
407
+ /* The one word the phone band draws instead of the sentence. Above 560px the
408
+ sentence fits and this is a second copy of it, so it is not drawn.
409
+ why: docs/components.md#the-page-shell */
410
+ .ui-app__search-short { display: none; }
407
411
 
408
412
  /* The mark alone — no room for two lines on a 52px row. No rule over it, since the
409
413
  band's hairline is under the whole of it, and no column, since this is not the rail.
410
414
  why: docs/components.md#the-page-shell */
411
415
  .ui-app__user--bar { flex: none; padding-top: 0; border-top: 0; }
416
+ /* The switch is a 34px square and stays one: the trigger above is the thing on this
417
+ band that gives way, and a flex item with the default shrink does not wait its
418
+ turn. Measured at 390 with a control beside the trigger, the React band's switch
419
+ drew 19x34 and the strategy topbar's drew 28.47x34 — a square glyph plate squashed,
420
+ and a tap zone the sheet could only clamp to 29 or 39.
421
+ Pinning the strategy topbar's half of this rule does not make its row narrower: it
422
+ moves a 5.53px shortfall onto the account block's trailing gutter instead, because
423
+ nothing before it in that row has width to spare. topbar.css's --space-2 comment
424
+ names that choice and the gutter it leaves.
425
+ why: docs/components.md#the-page-shell */
426
+ .ui-app__bar .toggle, .topbar__in .toggle { flex: none; }
412
427
  .ui-app__user--bar .ui-app__av { margin-inline-start: 0; }
413
428
  /* Crumb, then the title block. At --space-2 the crumb sat 8px off the h1 and
414
429
  the h1 8px off its subtitle, so all three ranks read as one. */
@@ -518,6 +533,31 @@
518
533
  .ui-app__main .ui-card__row { flex-wrap: wrap; gap: var(--space-3); }
519
534
  }
520
535
 
536
+ /* -- The band's search at one column --------------------------------------- */
537
+ /* The band holds the trigger, the reader's mark and whatever the page puts between
538
+ them, so the sentence broke mid-word — "Search or run a co…". The short word takes
539
+ its place. Neither the sentence nor the cap is `display: none`: both are inside
540
+ the button's accessible name — the cap by Artur's call on #308 — so they are
541
+ clipped the way `.ui-sr` in loading.css clips, and the name holds at every width.
542
+ why: docs/components.md#the-page-shell */
543
+ @media (max-width: 560px) {
544
+ .ui-app__search-txt,
545
+ .ui-app__search kbd {
546
+ position: absolute;
547
+ width: 1px;
548
+ height: 1px;
549
+ margin: -1px;
550
+ padding: 0;
551
+ overflow: hidden;
552
+ clip-path: inset(50%);
553
+ white-space: nowrap;
554
+ border: 0;
555
+ }
556
+ /* It gives way before the band does: at a large font scale the word ellipsises
557
+ rather than pushing the reader's mark off the row. */
558
+ .ui-app__search-short { display: block; flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
559
+ }
560
+
521
561
  /* -- Auth card (sign-in / consent) — centered, glowing --------------------- */
522
562
  .ui-auth {
523
563
  min-height: 100vh;
@@ -56,6 +56,8 @@
56
56
  .ui-drawer__close,
57
57
  .ui-snippet__copy,
58
58
  .ui-footer__social,
59
+ .ui-app__search,
60
+ .toggle,
59
61
  /* Already relative in react/src/DatePicker.css — restated because this
60
62
  gate reads the kit's own sheets and cannot see that one, and a carrier
61
63
  whose containing block it cannot find is a layer that measures against
@@ -75,7 +77,9 @@
75
77
  .ui-snippet__copy,
76
78
  .ui-footer__social,
77
79
  .ui-switch,
78
- .ui-datepicker__opt
80
+ .ui-datepicker__opt,
81
+ .ui-app__search,
82
+ .toggle
79
83
  )::after {
80
84
  content: "";
81
85
  position: absolute;
@@ -215,4 +219,24 @@
215
219
  --tap-clear-x: var(--tap-gap);
216
220
  --tap-clear-y: var(--tap-gap);
217
221
  }
222
+
223
+ /* Two 52px rows, each holding a control the kit draws under the floor: the
224
+ shell band's palette trigger, 37.05 tall once the phone band swaps its
225
+ sentence for the short word, and the theme switch at 34 square on both.
226
+ Neither row opens anything — the room is already in it, which is why these
227
+ two declare a clearance and no gap. Across, 6px a side against the band's
228
+ own 12px gap and the topbar's 8 below 560px, where this layer exists — not
229
+ the topbar's 14 above that step, where it does not. 6px a side crosses the
230
+ topbar's 4px midline by 1px, which does not mis-tap: neither neighbour on
231
+ that row carries a layer of its own. Down, the row's leftover height is 7.4px
232
+ above and below the trigger and 9 around the switch, where a 44px layer
233
+ needs 3.5 and 5. The rows keep their height, their gaps and their paint.
234
+ #486
235
+
236
+ --space-3 rather than --tap-gap, which is what every row above declares:
237
+ 20 claims 10px a side and the trigger has 7.4. The clamp would still stop
238
+ at 44 today and be a number that is not true, which is what the browser
239
+ half fails a container for. */
240
+ .ui-app__bar,
241
+ .topbar__in { --tap-clear-x: var(--space-3, 12px); --tap-clear-y: var(--space-3, 12px); }
218
242
  }
@@ -246,12 +246,31 @@
246
246
  /* One column, and the band is at its tightest. The row is already full at 390,
247
247
  and at the gap above this one the account avatar stood from 365 to 397 and was
248
248
  cut at the screen edge — the one control on this screen that opens the account
249
- area. Packed to --space-2 the band needs 352 of the 362 it has there, so the
250
- avatar is whole with the band's own gutter beside it. 320 is still short of the
251
- room these controls want, which stays #558.
249
+ area. Packed to --space-2 and a flat 14px trailing gutter the band needs 367.53
250
+ of the 362px it has there, a 5.53px shortfall, because layout.css now pins the
251
+ theme switch to a full 34px square so it keeps the tap floor it was given.
252
+ The wordmark, the Deck/Text switch and the version label are each already at
253
+ the width their own text needs, and the switch must not shrink again, so the
254
+ account block's trailing gutter is what gives — but a FLAT 14px gutter has no
255
+ fallback below the width it was sized for: at 375 it has already given every
256
+ one of its 14px and the row is still 6.53px short, so the avatar was cut and
257
+ the page gained 7px of horizontal scroll (#486 review round 2), worse again
258
+ at 320.
259
+ Both carry a share now, continuously, rather than the gutter alone holding a
260
+ fixed budget: the gutter still narrows first, from 14px at 390 down to 0 by
261
+ 381.53px of available row width, and once it is spent the inter-control gap
262
+ takes the rest, from --space-2 down to its own floor of --space-1. 381.53px is
263
+ this row's own fixed width minus its gutter's full 14px — not a general
264
+ formula, a number that belongs to this composition's own wordmark, switch and
265
+ version label. The avatar is whole and the page carries no horizontal scroll
266
+ down to 375px. 320 still falls 41.53px short with both all the way down,
267
+ which stays #558; it is 5px better than main's own 46.53px there, not solved.
252
268
  why: docs/foundations.md#breakpoints */
253
269
  @media (max-width: 560px) {
254
- .topbar__in { gap: var(--space-2); }
270
+ .topbar__in {
271
+ gap: clamp(var(--space-1), calc(var(--space-2) - (381.53px - 100vw) / 5), var(--space-2));
272
+ padding-right: clamp(0px, calc(100vw - 381.53px), 14px);
273
+ }
255
274
  }
256
275
 
257
276
  /* Account — avatar + dropdown. Gated: hidden until the app confirms a session