@sableui/react 0.17.0 → 0.19.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/AGENTS.md +10 -3
- package/CHANGELOG.md +235 -0
- package/README.md +11 -4
- package/bin/sable.mjs +266 -30
- package/dist/{_contract-CDa9-NdB.d.ts → _contract-DlklV0Im.d.ts} +2 -2
- package/dist/activity-DT8VK9fx.d.ts +25 -0
- package/dist/adapters/github.d.ts +41 -0
- package/dist/adapters/github.js +24 -0
- package/dist/blocks/index.d.ts +1 -1
- package/dist/components/activity-heatmap/activity-heatmap.js +420 -0
- package/dist/components/activity-heatmap/activity-heatmap.meta.js +142 -0
- package/dist/components/activity-heatmap/index.js +9 -0
- package/dist/components/avatar/avatar.js +16 -7
- package/dist/components/avatar/avatar.meta.js +43 -10
- package/dist/components/avatar/avatar.variants.js +26 -2
- package/dist/components/code-block/code-block.js +5 -3
- package/dist/components/code-block/code-block.meta.js +6 -0
- package/dist/components/collapsible/collapsible.js +6 -5
- package/dist/components/collapsible/collapsible.meta.js +14 -5
- package/dist/components/data-table/data-table.js +132 -45
- package/dist/components/data-table/data-table.meta.js +63 -4
- package/dist/components/date-picker/date-picker.js +13 -6
- package/dist/components/date-picker/date-picker.meta.js +22 -0
- package/dist/components/dialog/dialog.js +25 -5
- package/dist/components/dialog/dialog.meta.js +26 -5
- package/dist/components/media-image/media-image.js +3 -1
- package/dist/components/media-image/media-image.meta.js +15 -1
- package/dist/components/media-tile/media-tile.js +13 -1
- package/dist/components/media-tile/media-tile.meta.js +10 -0
- package/dist/components/menu/menu.js +2 -0
- package/dist/components/menu/menu.meta.js +2 -2
- package/dist/components/page-header/page-header.js +9 -4
- package/dist/components/page-header/page-header.meta.js +26 -1
- package/dist/components/panel-group/panel-group.js +17 -1
- package/dist/components/panel-group/panel-group.meta.js +43 -3
- package/dist/components/pill/pill.meta.js +15 -6
- package/dist/components/pill/pill.variants.js +1 -0
- package/dist/components/search-input/search-input.js +30 -5
- package/dist/components/search-input/search-input.meta.js +29 -4
- package/dist/components/section-header/section-header.js +27 -17
- package/dist/components/section-header/section-header.meta.js +27 -5
- package/dist/components/sheet/sheet.js +15 -3
- package/dist/components/sheet/sheet.meta.js +2 -2
- package/dist/components/side-nav/side-nav.variants.js +8 -3
- package/dist/components/sidebar/index.js +4 -0
- package/dist/components/sidebar/sidebar.js +90 -11
- package/dist/components/sidebar/sidebar.meta.js +38 -4
- package/dist/components/table/table.js +7 -3
- package/dist/components/tabs/tabs.js +10 -2
- package/dist/components/tabs/tabs.meta.js +4 -0
- package/dist/components/workspace/workspace.js +13 -3
- package/dist/components/workspace/workspace.meta.js +109 -1
- package/dist/file-hashes.json +94 -80
- package/dist/foundations/typography.js +13 -0
- package/dist/icon/Icon.js +21 -2
- package/dist/icon/index.d.ts +36 -1
- package/dist/icon/index.js +5 -0
- package/dist/icon/names.js +240 -0
- package/dist/icon-sets/reicon.js +41 -1
- package/dist/index.d.ts +540 -75
- package/dist/index.js +18 -1
- package/dist/layout/AspectBox.js +2 -5
- package/dist/layout/Bleed.js +10 -6
- package/dist/layout/Center.js +11 -3
- package/dist/layout/Columns.js +6 -3
- package/dist/layout/Grid.js +14 -6
- package/dist/layout/GridOverlay.js +7 -7
- package/dist/layout/Region.js +18 -3
- package/dist/layout/Row.js +27 -20
- package/dist/layout/Spacer.js +13 -2
- package/dist/layout/SplitPane.js +1 -1
- package/dist/layout/Stack.js +25 -18
- package/dist/layout/index.d.ts +57 -6
- package/dist/lib/chart/activity.js +32 -0
- package/dist/lib/chart/calendar.js +67 -0
- package/dist/lib/chart/chart-tooltip.js +2 -2
- package/dist/lib/chart/heat.js +55 -0
- package/dist/lib/cn.js +1 -0
- package/dist/lib/focus-return.js +53 -0
- package/dist/lib/taxonomy.js +1 -0
- package/dist/lib/use-media-query.js +41 -0
- package/dist/{meta-DX5r5wQL.d.ts → meta-Dfm9AExe.d.ts} +6 -0
- package/dist/patterns/dashboard-page.js +23 -17
- package/dist/patterns/index.d.ts +7 -2
- package/dist/patterns/index.js +5 -1
- package/dist/patterns/tracker-page.js +392 -0
- package/dist/patterns/tracker-page.meta.js +40 -0
- package/dist/presets/index.d.ts +1 -1
- package/dist/styles.css +301 -188
- package/dist/{theme-provider-BydfM5Z0.d.ts → theme-provider-BUBealk_.d.ts} +1 -1
- package/dist/themes/_contract.js +9 -1
- package/dist/themes/atelier/index.d.ts +1 -1
- package/dist/themes/ember/index.d.ts +1 -1
- package/dist/themes/index.d.ts +2 -2
- package/dist/themes/meridian/index.d.ts +1 -1
- package/dist/themes/poppy/index.d.ts +1 -1
- package/dist/themes/prism/index.d.ts +1 -1
- package/dist/themes/sable/index.d.ts +1 -1
- package/dist/themes/verdant/index.d.ts +1 -1
- package/llms/components/activity-heatmap.md +133 -0
- package/llms/components/avatar.md +32 -9
- package/llms/components/code-block.md +1 -0
- package/llms/components/collapsible.md +12 -4
- package/llms/components/data-table.md +40 -3
- package/llms/components/date-picker.md +15 -1
- package/llms/components/dialog.md +34 -3
- package/llms/components/media-image.md +12 -0
- package/llms/components/media-tile.md +21 -0
- package/llms/components/menu.md +1 -1
- package/llms/components/page-header.md +16 -1
- package/llms/components/panel-group.md +34 -2
- package/llms/components/pill.md +24 -5
- package/llms/components/search-input.md +37 -4
- package/llms/components/section-header.md +28 -4
- package/llms/components/sheet.md +2 -2
- package/llms/components/sidebar.md +17 -4
- package/llms/components/tabs.md +1 -0
- package/llms/components/workspace.md +81 -1
- package/llms/foundations/typography.md +4 -1
- package/llms/layout/aspect-box.md +1 -1
- package/llms/layout/bleed.md +1 -1
- package/llms/layout/center.md +1 -1
- package/llms/layout/columns.md +1 -1
- package/llms/layout/grid.md +1 -1
- package/llms/layout/region.md +1 -1
- package/llms/layout/row.md +9 -1
- package/llms/layout/spacer.md +1 -1
- package/llms/layout/split-pane.md +1 -1
- package/llms/layout/stack.md +1 -1
- package/llms/patterns/dashboard-page.md +18 -15
- package/llms/patterns/tracker-page.md +450 -0
- package/llms/reference/token-intent.md +3 -1
- package/llms/reference/utilities.md +4 -1
- package/llms/tasks/auditing-an-app.md +35 -1
- package/llms/tasks/building-a-page.md +3 -2
- package/llms/tasks/building-a-tool.md +101 -5
- package/llms/tasks/building-with-sable.md +11 -3
- package/llms/tasks/creating-a-preset.md +9 -0
- package/llms/tasks/getting-started.md +10 -3
- package/llms/tasks/using-presets.md +1 -2
- package/llms-full.txt +1215 -89
- package/llms.txt +11 -9
- package/package.json +7 -1
- package/registry.json +1021 -70
- package/scripts/adoption.mjs +252 -0
- package/scripts/agent-setup.mjs +110 -18
- package/scripts/app-css.mjs +129 -0
- package/scripts/grade.mjs +178 -2
- package/scripts/lint-rules.mjs +126 -0
- package/scripts/wiring.mjs +2 -1
- package/skills/entry/SKILL.md +1 -1
- package/skills/sable/SKILL.md +64 -6
- package/skills/sable/agents/openai.yaml +1 -1
- package/targets/ios.json +9 -0
package/dist/styles.css
CHANGED
|
@@ -203,6 +203,17 @@
|
|
|
203
203
|
See DESIGN.md → Layering.
|
|
204
204
|
========================================================================== */
|
|
205
205
|
|
|
206
|
+
/* The mobile bar height BottomNav, AppHeader, AppShell's bottom padding and
|
|
207
|
+
Workspace's bottomNav row share. In the base layer so a theme or an app that
|
|
208
|
+
declares its own (unlayered) wins; declared here because only the Sable
|
|
209
|
+
theme did, and AppShell reads it with no fallback, so under every other
|
|
210
|
+
theme its calc() was invalid and the padding under a BottomNav vanished. */
|
|
211
|
+
@layer base {
|
|
212
|
+
:root {
|
|
213
|
+
--nav-height: 56px;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
206
217
|
:root {
|
|
207
218
|
--z-sticky: 30; /* sticky in-content chrome: table headers, sticky banners */
|
|
208
219
|
--z-nav: 40; /* app chrome: AppHeader, Sidebar, BottomNav, status banners */
|
|
@@ -298,6 +309,12 @@
|
|
|
298
309
|
Routed through a --theme-* hook rather than hardcoded, so a theme can still
|
|
299
310
|
choose its own button shape without fighting this scope. */
|
|
300
311
|
--button-radius: var(--theme-button-radius, 9999px);
|
|
312
|
+
|
|
313
|
+
/* Table geometry. Unset here so Table's own fallbacks (h-10 head, py-2.5
|
|
314
|
+
cells, on the spacing scale) apply — and declared, for the same symmetry:
|
|
315
|
+
a comfortable form nested in a compact tool gets the page table back. */
|
|
316
|
+
--table-head-h: initial;
|
|
317
|
+
--table-cell-py: initial;
|
|
301
318
|
}
|
|
302
319
|
|
|
303
320
|
/* Workspace register — measured from the Figma and Paper editors (2026-07-26),
|
|
@@ -337,6 +354,30 @@
|
|
|
337
354
|
--tree-rail: 8px;
|
|
338
355
|
--tree-column: 18px;
|
|
339
356
|
--tree-indent: 18px;
|
|
357
|
+
|
|
358
|
+
/* Table geometry: a head row on the sm rung and one baseline step of block
|
|
359
|
+
padding, so a 16px ui line makes a 32px row — Linear's list row, and the
|
|
360
|
+
size a table in a tool panel was being forced to by hand (thirteen
|
|
361
|
+
consumer rules overriding th/td heights, padding and size in one app). */
|
|
362
|
+
--table-head-h: var(--control-sm);
|
|
363
|
+
--table-cell-py: calc(var(--spacing) * 2);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/* A finger is not a denser pointer. The compact ladder is measured from mouse-
|
|
367
|
+
driven editors (Figma, Paper), where a 24px target is aimed with a cursor; on
|
|
368
|
+
a phone or tablet the same tool chrome needs the page register's targets, so
|
|
369
|
+
on a coarse pointer compact keeps its type, radius and panel geometry and
|
|
370
|
+
takes the comfortable ladder's heights. Without this, every Workspace app
|
|
371
|
+
re-tuned `--control-*` by hand below some breakpoint — and a breakpoint is
|
|
372
|
+
the wrong question: a touch laptop is wide, a phone with a mouse is narrow. */
|
|
373
|
+
@media (pointer: coarse) {
|
|
374
|
+
[data-density="compact"] {
|
|
375
|
+
--control-xs: 28px;
|
|
376
|
+
--control-sm: 32px;
|
|
377
|
+
--control-md: 40px;
|
|
378
|
+
--control-cta: 44px;
|
|
379
|
+
--control-lg: 48px;
|
|
380
|
+
}
|
|
340
381
|
}
|
|
341
382
|
|
|
342
383
|
/* ==========================================================================
|
|
@@ -348,6 +389,13 @@
|
|
|
348
389
|
Paper's entire panel ladder spans 249 → 242 → 238 (3-7 RGB units) and lets a
|
|
349
390
|
1px low-contrast edge do the structural work. In this register hairlines carry
|
|
350
391
|
structure INSTEAD of tonal steps — the reverse of the page register's rule.
|
|
392
|
+
|
|
393
|
+
Every mix here is `in oklab`, never `in oklch`. These blend a near-neutral
|
|
394
|
+
surface with its ink, so there is no hue worth interpolating, and oklch
|
|
395
|
+
loses it: measured in Chrome, `color-mix(in oklch, #141519 97%, #e4e5ea)`
|
|
396
|
+
resolves to `oklch(0.218 0.008 none)` and paints a missing hue as 0°, a
|
|
397
|
+
brown cast on a cool graphite preset's canvas. Bundled themes write oklch
|
|
398
|
+
and never showed it; presets and apps write hex.
|
|
351
399
|
========================================================================== */
|
|
352
400
|
|
|
353
401
|
/* Declared on every element that can re-declare the base colors, not just
|
|
@@ -361,32 +409,32 @@
|
|
|
361
409
|
/* The work surface. NOT `background`: the artboard is the subject, not the
|
|
362
410
|
page behind the UI. Pulled a touch away from the page so docked panels can
|
|
363
411
|
sit above it without a border. */
|
|
364
|
-
--canvas: var(--theme-canvas, color-mix(in
|
|
412
|
+
--canvas: var(--theme-canvas, color-mix(in oklab, var(--background) 97%, var(--foreground)));
|
|
365
413
|
--canvas-foreground: var(--theme-canvas-foreground, var(--foreground));
|
|
366
414
|
|
|
367
415
|
/* Docked chrome, one compressed step off the canvas. */
|
|
368
416
|
--panel: var(--theme-panel, var(--background));
|
|
369
417
|
--panel-foreground: var(--theme-panel-foreground, var(--foreground));
|
|
370
|
-
--panel-raised: var(--theme-panel-raised, color-mix(in
|
|
418
|
+
--panel-raised: var(--theme-panel-raised, color-mix(in oklab, var(--background) 94%, var(--foreground)));
|
|
371
419
|
|
|
372
420
|
/* A compact control docked in a panel: the xs field rung and a field-style
|
|
373
421
|
button. Mixed from the panel it sits in, a further step under the pointer.
|
|
374
422
|
It used to borrow the canvas tone (3% ink), which measured 1.04:1 against
|
|
375
423
|
a dark panel: the field all but vanished. 9% is what a shipped inspector
|
|
376
424
|
settled on (1.15:1 dark, 1.25:1 light). */
|
|
377
|
-
--panel-field: var(--theme-panel-field, color-mix(in
|
|
378
|
-
--panel-field-hover: var(--theme-panel-field-hover, color-mix(in
|
|
425
|
+
--panel-field: var(--theme-panel-field, color-mix(in oklab, var(--panel) 91%, var(--panel-foreground)));
|
|
426
|
+
--panel-field-hover: var(--theme-panel-field-hover, color-mix(in oklab, var(--panel) 88%, var(--panel-foreground)));
|
|
379
427
|
|
|
380
428
|
/* The structural edge. Alpha-based so it holds over any surface beneath it. */
|
|
381
|
-
--hairline: var(--theme-hairline, color-mix(in
|
|
382
|
-
--hairline-strong: var(--theme-hairline-strong, color-mix(in
|
|
429
|
+
--hairline: var(--theme-hairline, color-mix(in oklab, transparent 93%, var(--foreground)));
|
|
430
|
+
--hairline-strong: var(--theme-hairline-strong, color-mix(in oklab, transparent 86%, var(--foreground)));
|
|
383
431
|
|
|
384
432
|
/* The edge of a FLOATING surface (popover, menu, select, tooltip, a floating
|
|
385
433
|
panel). Lighter than `--border` on purpose: the shadow carries the
|
|
386
434
|
elevation, and a full hairline plus a shadow stacks into a dark outline.
|
|
387
435
|
Alpha-based, so it defines the shape on a same-colour page in light mode
|
|
388
436
|
and reads as a faint lit edge in dark mode, where shadows barely show. */
|
|
389
|
-
--border-floating: var(--theme-border-floating, color-mix(in
|
|
437
|
+
--border-floating: var(--theme-border-floating, color-mix(in oklab, transparent 92%, var(--foreground)));
|
|
390
438
|
|
|
391
439
|
/* The text field: its fill and its outline. Outlined on the card by default;
|
|
392
440
|
a theme fills its fields instead with `--theme-field: var(--muted)` and
|
|
@@ -399,7 +447,7 @@
|
|
|
399
447
|
the gap around the raised main panel. One step off the rail toward its ink,
|
|
400
448
|
because most themes paint the rail the page's colour and the panel would
|
|
401
449
|
otherwise sit on its own colour. */
|
|
402
|
-
--shell-ground: var(--theme-shell-ground, color-mix(in
|
|
450
|
+
--shell-ground: var(--theme-shell-ground, color-mix(in oklab, var(--sidebar) 97%, var(--sidebar-foreground)));
|
|
403
451
|
|
|
404
452
|
/* Status and tone colours at graphic strength: a meter's fill, a segmented
|
|
405
453
|
bar, a status dot, a chart series, a soft tint. The label fill is dark
|
|
@@ -493,7 +541,7 @@
|
|
|
493
541
|
2px,
|
|
494
542
|
round(
|
|
495
543
|
nearest,
|
|
496
|
-
calc(var(--type-body-md-size, 0.9375rem) * var(--type-body-md-leading, 1.55) * var(--leading-scale) / var(--baseline-split)),
|
|
544
|
+
calc(var(--type-body-md-size, 0.9375rem) * var(--type-base, 16) / 16 * var(--type-body-md-leading, 1.55) * var(--leading-scale) / var(--baseline-split)),
|
|
497
545
|
1px
|
|
498
546
|
)
|
|
499
547
|
);
|
|
@@ -527,39 +575,62 @@
|
|
|
527
575
|
--leading-scale, so Airy opens the text itself; display, heading and label
|
|
528
576
|
leading is a shape the theme chose and only snaps. The `ui-*` tier is
|
|
529
577
|
already whole px on its own 4px grid (the workspace register).
|
|
578
|
+
|
|
579
|
+
── The base size: one number rebuilds the scale ───────────────────────────
|
|
580
|
+
Every page tier is authored on a 16px base (1rem is title-lg; body-md is
|
|
581
|
+
15/16 of it). `--type-base` is that base as a unitless px number, so
|
|
582
|
+
`--type-base: 14` rebuilds the whole scale at 14: each tier keeps its ratio
|
|
583
|
+
to the base, the headings stay a heading's distance from the body, and the
|
|
584
|
+
baseline step (and with it `--spacing`) follows the body down. It is the
|
|
585
|
+
standard "set the base font size" knob, scoped to type and rhythm: unlike
|
|
586
|
+
changing the root font-size, it leaves the control ladder and every rem the
|
|
587
|
+
app wrote itself where they were.
|
|
588
|
+
|
|
589
|
+
Applied where the size is USED — `calc(var(--type-<tier>-size, <rem>) *
|
|
590
|
+
var(--type-base, 16) / 16)` — not where a theme declares it, so it scales a
|
|
591
|
+
theme's own tier values and a consumer's per-tier overrides alike, and works
|
|
592
|
+
on any element: set it on :root, a `[data-sable-theme]` scope or a preset
|
|
593
|
+
(`tokens.shared["type-base"]`) and the spacing follows too; on any other
|
|
594
|
+
subtree the type rescales and the rhythm stays the page's. Unitless, because
|
|
595
|
+
CSS cannot divide one length by another: `14`, never `14px`.
|
|
596
|
+
|
|
597
|
+
The `ui-*` tiers do NOT take it. They are absolute px measured from tool
|
|
598
|
+
chrome (Figma, Paper) and sit on their own 4px grid; the compact register's
|
|
599
|
+
`min(page, ui)` remaps already follow a smaller base down, so a 13px-base app
|
|
600
|
+
still never gets chrome type larger than its page type.
|
|
530
601
|
========================================================================== */
|
|
531
602
|
|
|
532
603
|
@utility text-display-4xl {
|
|
533
604
|
font-family: var(--font-display, var(--font-sans));
|
|
534
|
-
font-size: var(--type-display-4xl-size, clamp(4.5rem, 12vw, 12rem));
|
|
605
|
+
font-size: calc(var(--type-display-4xl-size, clamp(4.5rem, 12vw, 12rem)) * var(--type-base, 16) / 16);
|
|
535
606
|
font-weight: var(--type-display-4xl-weight, 800);
|
|
536
607
|
line-height: round(nearest, calc(var(--type-display-4xl-leading, 0.9) * 1em), var(--baseline-step, 0.25rem));
|
|
537
608
|
letter-spacing: var(--type-display-4xl-tracking, -0.05em);
|
|
538
609
|
}
|
|
539
610
|
@utility text-display-3xl {
|
|
540
611
|
font-family: var(--font-display, var(--font-sans));
|
|
541
|
-
font-size: var(--type-display-3xl-size, 6rem);
|
|
612
|
+
font-size: calc(var(--type-display-3xl-size, 6rem) * var(--type-base, 16) / 16);
|
|
542
613
|
font-weight: var(--type-display-3xl-weight, 700);
|
|
543
614
|
line-height: round(nearest, calc(var(--type-display-3xl-leading, 0.95) * 1em), var(--baseline-step, 0.25rem));
|
|
544
615
|
letter-spacing: var(--type-display-3xl-tracking, -0.045em);
|
|
545
616
|
}
|
|
546
617
|
@utility text-display-2xl {
|
|
547
618
|
font-family: var(--font-display, var(--font-sans));
|
|
548
|
-
font-size: var(--type-display-2xl-size, 4.5rem);
|
|
619
|
+
font-size: calc(var(--type-display-2xl-size, 4.5rem) * var(--type-base, 16) / 16);
|
|
549
620
|
font-weight: var(--type-display-2xl-weight, 700);
|
|
550
621
|
line-height: round(nearest, calc(var(--type-display-2xl-leading, 1) * 1em), var(--baseline-step, 0.25rem));
|
|
551
622
|
letter-spacing: var(--type-display-2xl-tracking, -0.04em);
|
|
552
623
|
}
|
|
553
624
|
@utility text-display-xl {
|
|
554
625
|
font-family: var(--font-display, var(--font-sans));
|
|
555
|
-
font-size: var(--type-display-xl-size, 3.75rem);
|
|
626
|
+
font-size: calc(var(--type-display-xl-size, 3.75rem) * var(--type-base, 16) / 16);
|
|
556
627
|
font-weight: var(--type-display-xl-weight, 700);
|
|
557
628
|
line-height: round(nearest, calc(var(--type-display-xl-leading, 1.05) * 1em), var(--baseline-step, 0.25rem));
|
|
558
629
|
letter-spacing: var(--type-display-xl-tracking, -0.035em);
|
|
559
630
|
}
|
|
560
631
|
@utility text-display-lg {
|
|
561
632
|
font-family: var(--font-display, var(--font-sans));
|
|
562
|
-
font-size: var(--type-display-lg-size, 3rem);
|
|
633
|
+
font-size: calc(var(--type-display-lg-size, 3rem) * var(--type-base, 16) / 16);
|
|
563
634
|
font-weight: var(--type-display-lg-weight, 700);
|
|
564
635
|
line-height: round(nearest, calc(var(--type-display-lg-leading, 1.1) * 1em), var(--baseline-step, 0.25rem));
|
|
565
636
|
letter-spacing: var(--type-display-lg-tracking, -0.03em);
|
|
@@ -567,28 +638,28 @@
|
|
|
567
638
|
|
|
568
639
|
@utility text-heading-1 {
|
|
569
640
|
font-family: var(--font-display, var(--font-sans));
|
|
570
|
-
font-size: var(--type-heading-1-size, 2.25rem);
|
|
641
|
+
font-size: calc(var(--type-heading-1-size, 2.25rem) * var(--type-base, 16) / 16);
|
|
571
642
|
font-weight: var(--type-heading-weight, 600);
|
|
572
643
|
line-height: round(nearest, calc(var(--type-heading-1-leading, 1.15) * 1em), var(--baseline-step, 0.25rem));
|
|
573
644
|
letter-spacing: var(--type-heading-1-tracking, -0.025em);
|
|
574
645
|
}
|
|
575
646
|
@utility text-heading-2 {
|
|
576
647
|
font-family: var(--font-display, var(--font-sans));
|
|
577
|
-
font-size: var(--type-heading-2-size, 1.75rem);
|
|
648
|
+
font-size: calc(var(--type-heading-2-size, 1.75rem) * var(--type-base, 16) / 16);
|
|
578
649
|
font-weight: var(--type-heading-weight, 600);
|
|
579
650
|
line-height: round(nearest, calc(var(--type-heading-2-leading, 1.2) * 1em), var(--baseline-step, 0.25rem));
|
|
580
651
|
letter-spacing: var(--type-heading-2-tracking, -0.02em);
|
|
581
652
|
}
|
|
582
653
|
@utility text-heading-3 {
|
|
583
654
|
font-family: var(--font-display, var(--font-sans));
|
|
584
|
-
font-size: var(--type-heading-3-size, 1.375rem);
|
|
655
|
+
font-size: calc(var(--type-heading-3-size, 1.375rem) * var(--type-base, 16) / 16);
|
|
585
656
|
font-weight: var(--type-heading-weight, 600);
|
|
586
657
|
line-height: round(nearest, calc(var(--type-heading-3-leading, 1.25) * 1em), var(--baseline-step, 0.25rem));
|
|
587
658
|
letter-spacing: var(--type-heading-3-tracking, -0.015em);
|
|
588
659
|
}
|
|
589
660
|
@utility text-heading-4 {
|
|
590
661
|
font-family: var(--font-display, var(--font-sans));
|
|
591
|
-
font-size: var(--type-heading-4-size, 1.125rem);
|
|
662
|
+
font-size: calc(var(--type-heading-4-size, 1.125rem) * var(--type-base, 16) / 16);
|
|
592
663
|
font-weight: var(--type-heading-weight, 600);
|
|
593
664
|
line-height: round(nearest, calc(var(--type-heading-4-leading, 1.3) * 1em), var(--baseline-step, 0.25rem));
|
|
594
665
|
letter-spacing: var(--type-heading-4-tracking, -0.01em);
|
|
@@ -603,13 +674,13 @@
|
|
|
603
674
|
(a trading desk, an operator console) needs its own body/label/mono sizes,
|
|
604
675
|
and pinning them in a page's own <style> block is a patch, not a theme. */
|
|
605
676
|
@utility text-title-lg {
|
|
606
|
-
font-size: var(--type-title-lg-size, 1rem);
|
|
677
|
+
font-size: calc(var(--type-title-lg-size, 1rem) * var(--type-base, 16) / 16);
|
|
607
678
|
font-weight: var(--type-title-weight, 600);
|
|
608
679
|
line-height: round(nearest, calc(var(--type-title-leading, 1.4) * var(--leading-scale, 1) * 1em), var(--baseline-step, 0.25rem));
|
|
609
680
|
letter-spacing: var(--type-title-tracking, -0.01em);
|
|
610
681
|
}
|
|
611
682
|
@utility text-title-sm {
|
|
612
|
-
font-size: var(--type-title-sm-size, 0.875rem);
|
|
683
|
+
font-size: calc(var(--type-title-sm-size, 0.875rem) * var(--type-base, 16) / 16);
|
|
613
684
|
font-weight: var(--type-title-weight, 600);
|
|
614
685
|
line-height: round(nearest, calc(var(--type-title-leading, 1.4) * var(--leading-scale, 1) * 1em), var(--baseline-step, 0.25rem));
|
|
615
686
|
letter-spacing: var(--type-title-sm-tracking, -0.005em);
|
|
@@ -628,20 +699,20 @@
|
|
|
628
699
|
`pretty` costs layout work over many lines to fix a break nobody reads as an
|
|
629
700
|
error. Ledes are short by definition, so the cost is bounded here. */
|
|
630
701
|
@utility text-body-lg {
|
|
631
|
-
font-size: var(--type-body-lg-size, 1.0625rem);
|
|
702
|
+
font-size: calc(var(--type-body-lg-size, 1.0625rem) * var(--type-base, 16) / 16);
|
|
632
703
|
font-weight: var(--type-body-lg-weight, 400);
|
|
633
704
|
line-height: round(nearest, calc(var(--type-body-lg-leading, 1.6) * var(--leading-scale, 1) * 1em), var(--baseline-step, 0.25rem));
|
|
634
705
|
letter-spacing: var(--type-body-lg-tracking, -0.005em);
|
|
635
706
|
text-wrap: pretty;
|
|
636
707
|
}
|
|
637
708
|
@utility text-body-md {
|
|
638
|
-
font-size: var(--type-body-md-size, 0.9375rem);
|
|
709
|
+
font-size: calc(var(--type-body-md-size, 0.9375rem) * var(--type-base, 16) / 16);
|
|
639
710
|
font-weight: var(--type-body-md-weight, 400);
|
|
640
711
|
line-height: round(nearest, calc(var(--type-body-md-leading, 1.55) * var(--leading-scale, 1) * 1em), var(--baseline-step, 0.25rem));
|
|
641
712
|
letter-spacing: var(--type-body-md-tracking, -0.005em);
|
|
642
713
|
}
|
|
643
714
|
@utility text-body-sm {
|
|
644
|
-
font-size: var(--type-body-sm-size, 0.8125rem);
|
|
715
|
+
font-size: calc(var(--type-body-sm-size, 0.8125rem) * var(--type-base, 16) / 16);
|
|
645
716
|
font-weight: var(--type-body-sm-weight, 400);
|
|
646
717
|
line-height: round(nearest, calc(var(--type-body-sm-leading, 1.5) * var(--leading-scale, 1) * 1em), var(--baseline-step, 0.25rem));
|
|
647
718
|
letter-spacing: var(--type-body-sm-tracking, 0);
|
|
@@ -650,7 +721,7 @@
|
|
|
650
721
|
dense table cells, and metadata. Same size as text-caption but with body
|
|
651
722
|
leading: caption is tuned for one-line annotation, body-xs for wrapping. */
|
|
652
723
|
@utility text-body-xs {
|
|
653
|
-
font-size: var(--type-body-xs-size, 0.75rem);
|
|
724
|
+
font-size: calc(var(--type-body-xs-size, 0.75rem) * var(--type-base, 16) / 16);
|
|
654
725
|
font-weight: var(--type-body-xs-weight, 400);
|
|
655
726
|
line-height: round(nearest, calc(var(--type-body-xs-leading, 1.5) * var(--leading-scale, 1) * 1em), var(--baseline-step, 0.25rem));
|
|
656
727
|
letter-spacing: var(--type-body-xs-tracking, 0);
|
|
@@ -678,7 +749,7 @@
|
|
|
678
749
|
@utility sable-list {
|
|
679
750
|
list-style: disc;
|
|
680
751
|
padding-inline-start: 1.25em;
|
|
681
|
-
font-size: var(--type-body-md-size, 0.9375rem);
|
|
752
|
+
font-size: calc(var(--type-body-md-size, 0.9375rem) * var(--type-base, 16) / 16);
|
|
682
753
|
line-height: round(nearest, calc(var(--type-body-md-leading, 1.55) * var(--leading-scale, 1) * 1em), var(--baseline-step, 0.25rem));
|
|
683
754
|
color: var(--foreground);
|
|
684
755
|
& > li + li {
|
|
@@ -692,7 +763,7 @@
|
|
|
692
763
|
@utility sable-list-numbered {
|
|
693
764
|
list-style: decimal;
|
|
694
765
|
padding-inline-start: 1.5em;
|
|
695
|
-
font-size: var(--type-body-md-size, 0.9375rem);
|
|
766
|
+
font-size: calc(var(--type-body-md-size, 0.9375rem) * var(--type-base, 16) / 16);
|
|
696
767
|
line-height: round(nearest, calc(var(--type-body-md-leading, 1.55) * var(--leading-scale, 1) * 1em), var(--baseline-step, 0.25rem));
|
|
697
768
|
color: var(--foreground);
|
|
698
769
|
& > li + li {
|
|
@@ -714,12 +785,12 @@
|
|
|
714
785
|
/* The values' type and ink live on the list and the <dd>s inherit them, so a
|
|
715
786
|
text-* utility on a <dd> (text-success, text-mono-md) simply wins. The term
|
|
716
787
|
and the wrapping rules sit in :where(), which adds no specificity. */
|
|
717
|
-
font-size: var(--type-body-md-size, 0.9375rem);
|
|
788
|
+
font-size: calc(var(--type-body-md-size, 0.9375rem) * var(--type-base, 16) / 16);
|
|
718
789
|
line-height: round(nearest, calc(var(--type-body-md-leading, 1.55) * var(--leading-scale, 1) * 1em), var(--baseline-step, 0.25rem));
|
|
719
790
|
letter-spacing: var(--type-body-md-tracking, -0.005em);
|
|
720
791
|
color: var(--foreground);
|
|
721
792
|
& > :where(dt) {
|
|
722
|
-
font-size: var(--type-label-md-size, 0.75rem);
|
|
793
|
+
font-size: calc(var(--type-label-md-size, 0.75rem) * var(--type-base, 16) / 16);
|
|
723
794
|
font-weight: var(--type-label-md-weight, 600);
|
|
724
795
|
line-height: round(nearest, calc(var(--type-label-md-leading, 1.2) * 1em), var(--baseline-step, 0.25rem));
|
|
725
796
|
letter-spacing: var(--type-label-md-tracking, 0);
|
|
@@ -738,19 +809,19 @@
|
|
|
738
809
|
}
|
|
739
810
|
|
|
740
811
|
@utility text-label-lg {
|
|
741
|
-
font-size: var(--type-label-lg-size, 0.875rem);
|
|
812
|
+
font-size: calc(var(--type-label-lg-size, 0.875rem) * var(--type-base, 16) / 16);
|
|
742
813
|
font-weight: var(--type-label-lg-weight, 600);
|
|
743
814
|
line-height: round(nearest, calc(var(--type-label-lg-leading, 1.25) * 1em), var(--baseline-step, 0.25rem));
|
|
744
815
|
letter-spacing: var(--type-label-lg-tracking, -0.005em);
|
|
745
816
|
}
|
|
746
817
|
@utility text-label-md {
|
|
747
|
-
font-size: var(--type-label-md-size, 0.75rem);
|
|
818
|
+
font-size: calc(var(--type-label-md-size, 0.75rem) * var(--type-base, 16) / 16);
|
|
748
819
|
font-weight: var(--type-label-md-weight, 600);
|
|
749
820
|
line-height: round(nearest, calc(var(--type-label-md-leading, 1.2) * 1em), var(--baseline-step, 0.25rem));
|
|
750
821
|
letter-spacing: var(--type-label-md-tracking, 0);
|
|
751
822
|
}
|
|
752
823
|
@utility text-label-sm {
|
|
753
|
-
font-size: var(--type-label-sm-size, 0.6875rem);
|
|
824
|
+
font-size: calc(var(--type-label-sm-size, 0.6875rem) * var(--type-base, 16) / 16);
|
|
754
825
|
font-weight: var(--type-label-sm-weight, 600);
|
|
755
826
|
line-height: round(nearest, calc(var(--type-label-sm-leading, 1.2) * 1em), var(--baseline-step, 0.25rem));
|
|
756
827
|
letter-spacing: var(--type-label-sm-tracking, 0);
|
|
@@ -760,14 +831,14 @@
|
|
|
760
831
|
it (Label `eyebrow`) rather than getting caps from the smallest label. The
|
|
761
832
|
transform stays a themeable hook for a theme that wants caps here. */
|
|
762
833
|
@utility text-label-xs {
|
|
763
|
-
font-size: var(--type-label-xs-size, 0.6875rem);
|
|
834
|
+
font-size: calc(var(--type-label-xs-size, 0.6875rem) * var(--type-base, 16) / 16);
|
|
764
835
|
font-weight: var(--type-label-xs-weight, 600);
|
|
765
836
|
line-height: round(nearest, calc(var(--type-label-xs-leading, 1.2) * 1em), var(--baseline-step, 0.25rem));
|
|
766
837
|
letter-spacing: var(--type-label-xs-tracking, 0.01em);
|
|
767
838
|
text-transform: var(--type-label-xs-transform, none);
|
|
768
839
|
}
|
|
769
840
|
@utility text-caption {
|
|
770
|
-
font-size: var(--type-caption-size, 0.75rem);
|
|
841
|
+
font-size: calc(var(--type-caption-size, 0.75rem) * var(--type-base, 16) / 16);
|
|
771
842
|
font-weight: var(--type-caption-weight, 400);
|
|
772
843
|
line-height: round(nearest, calc(var(--type-caption-leading, 1.4) * var(--leading-scale, 1) * 1em), var(--baseline-step, 0.25rem));
|
|
773
844
|
letter-spacing: var(--type-caption-tracking, 0);
|
|
@@ -778,7 +849,7 @@
|
|
|
778
849
|
via TYPE_OVERLINE_TOKENS (see _contract.ts); `--type-overline-transform`
|
|
779
850
|
lets a theme opt out of all-caps rather than hardcoding `uppercase`. */
|
|
780
851
|
@utility text-overline {
|
|
781
|
-
font-size: var(--type-overline-size, 0.75rem);
|
|
852
|
+
font-size: calc(var(--type-overline-size, 0.75rem) * var(--type-base, 16) / 16);
|
|
782
853
|
font-weight: var(--type-overline-weight, 600);
|
|
783
854
|
line-height: round(nearest, calc(var(--type-overline-leading, 1.2) * 1em), var(--baseline-step, 0.25rem));
|
|
784
855
|
letter-spacing: var(--type-overline-tracking, 0.08em);
|
|
@@ -790,7 +861,7 @@
|
|
|
790
861
|
the technical voice) rather than a heading tier — headings stay semantic. */
|
|
791
862
|
@utility text-mono-xl {
|
|
792
863
|
font-family: var(--font-mono);
|
|
793
|
-
font-size: var(--type-mono-xl-size, 1.75rem);
|
|
864
|
+
font-size: calc(var(--type-mono-xl-size, 1.75rem) * var(--type-base, 16) / 16);
|
|
794
865
|
font-weight: var(--type-mono-xl-weight, 500);
|
|
795
866
|
line-height: round(nearest, calc(var(--type-mono-xl-leading, 1.15) * 1em), var(--baseline-step, 0.25rem));
|
|
796
867
|
letter-spacing: var(--type-mono-xl-tracking, -0.01em);
|
|
@@ -798,7 +869,7 @@
|
|
|
798
869
|
}
|
|
799
870
|
@utility text-mono-lg {
|
|
800
871
|
font-family: var(--font-mono);
|
|
801
|
-
font-size: var(--type-mono-lg-size, 1.25rem);
|
|
872
|
+
font-size: calc(var(--type-mono-lg-size, 1.25rem) * var(--type-base, 16) / 16);
|
|
802
873
|
font-weight: var(--type-mono-lg-weight, 500);
|
|
803
874
|
line-height: round(nearest, calc(var(--type-mono-lg-leading, 1.25) * 1em), var(--baseline-step, 0.25rem));
|
|
804
875
|
letter-spacing: var(--type-mono-lg-tracking, 0);
|
|
@@ -806,7 +877,7 @@
|
|
|
806
877
|
}
|
|
807
878
|
@utility text-mono-md {
|
|
808
879
|
font-family: var(--font-mono);
|
|
809
|
-
font-size: var(--type-mono-md-size, 0.8125rem);
|
|
880
|
+
font-size: calc(var(--type-mono-md-size, 0.8125rem) * var(--type-base, 16) / 16);
|
|
810
881
|
font-weight: var(--type-mono-md-weight, 400);
|
|
811
882
|
line-height: round(nearest, calc(var(--type-mono-md-leading, 1.5) * var(--leading-scale, 1) * 1em), var(--baseline-step, 0.25rem));
|
|
812
883
|
letter-spacing: var(--type-mono-md-tracking, 0);
|
|
@@ -817,7 +888,7 @@
|
|
|
817
888
|
`font-mono text-caption` recomposition. */
|
|
818
889
|
@utility text-mono-caption {
|
|
819
890
|
font-family: var(--font-mono);
|
|
820
|
-
font-size: var(--type-mono-caption-size, 0.75rem);
|
|
891
|
+
font-size: calc(var(--type-mono-caption-size, 0.75rem) * var(--type-base, 16) / 16);
|
|
821
892
|
font-weight: var(--type-mono-caption-weight, 400);
|
|
822
893
|
line-height: round(nearest, calc(var(--type-mono-caption-leading, 1.4) * var(--leading-scale, 1) * 1em), var(--baseline-step, 0.25rem));
|
|
823
894
|
letter-spacing: var(--type-mono-caption-tracking, 0);
|
|
@@ -825,7 +896,7 @@
|
|
|
825
896
|
}
|
|
826
897
|
@utility text-mono-sm {
|
|
827
898
|
font-family: var(--font-mono);
|
|
828
|
-
font-size: var(--type-mono-sm-size, 0.6875rem);
|
|
899
|
+
font-size: calc(var(--type-mono-sm-size, 0.6875rem) * var(--type-base, 16) / 16);
|
|
829
900
|
font-weight: var(--type-mono-sm-weight, 500);
|
|
830
901
|
line-height: round(nearest, calc(var(--type-mono-sm-leading, 1.2) * 1em), var(--baseline-step, 0.25rem));
|
|
831
902
|
letter-spacing: var(--type-mono-sm-tracking, 0.02em);
|
|
@@ -932,6 +1003,20 @@
|
|
|
932
1003
|
letter-spacing: 0.005em;
|
|
933
1004
|
}
|
|
934
1005
|
|
|
1006
|
+
/* The title of what a panel or inspector is showing — the open issue, the
|
|
1007
|
+
selected object. One step above ui-md on the chrome ladder (10 / 11 / 12 /
|
|
1008
|
+
14): far enough above its 12px description to lead without weight alone,
|
|
1009
|
+
short of the 16px page title so it still reads as chrome. Linear's issue
|
|
1010
|
+
peek, Figma's selection header and Paper's inspector title all sit at
|
|
1011
|
+
13-15px. On a 20px leading, the ui grid's next 4px step. Compact `text-title-lg`
|
|
1012
|
+
resolves here, so a page-register title dropped into a panel lands on it. */
|
|
1013
|
+
@utility text-ui-title {
|
|
1014
|
+
font-size: var(--type-ui-title-size, 14px);
|
|
1015
|
+
font-weight: var(--type-ui-title-weight, 600);
|
|
1016
|
+
line-height: var(--type-ui-title-leading, 20px);
|
|
1017
|
+
letter-spacing: -0.005em;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
935
1020
|
/* The reading variant — descriptions and help text inside chrome. */
|
|
936
1021
|
@utility text-ui-body {
|
|
937
1022
|
font-size: var(--type-ui-md-size, 12px);
|
|
@@ -1599,6 +1684,17 @@
|
|
|
1599
1684
|
========================================================================== */
|
|
1600
1685
|
[data-density="compact"] {
|
|
1601
1686
|
/*
|
|
1687
|
+
* The remap stops at a comfortable boundary. A reading view inside a tool —
|
|
1688
|
+
* an issue's overview, a settings form — is wrapped in
|
|
1689
|
+
* `<Density value="comfortable">` to get page type back, and the descendant
|
|
1690
|
+
* selectors alone still matched it, so the wrapper restored the control
|
|
1691
|
+
* ladder and left the prose at 11px. `:not(compact comfortable *)` rather
|
|
1692
|
+
* than `@scope (compact) to (comfortable)`: @scope would be the exact tool,
|
|
1693
|
+
* but a browser without it (Safari < 17.4, older Firefox — inside Tailwind
|
|
1694
|
+
* v4's support range) drops the whole block, and the register's type with
|
|
1695
|
+
* it. Limit: a compact scope nested inside that comfortable one gets page
|
|
1696
|
+
* type too, a third level of nesting nothing ships.
|
|
1697
|
+
*
|
|
1602
1698
|
* Every value is `min(page, workspace)`, so the register can only ever
|
|
1603
1699
|
* COMPRESS. Without it these grow on some apps: the page tiers are `rem`
|
|
1604
1700
|
* and the workspace tiers are absolute px, so at a 14px root
|
|
@@ -1606,72 +1702,82 @@
|
|
|
1606
1702
|
* tool panel — a "denser" register rendering larger text than the page it
|
|
1607
1703
|
* sits beside. `min()` makes that impossible at any root size.
|
|
1608
1704
|
*/
|
|
1609
|
-
& .text-body-lg {
|
|
1610
|
-
font-size: min(1.0625rem, var(--type-ui-md-size, 12px));
|
|
1705
|
+
& .text-body-lg:not([data-density="compact"] [data-density="comfortable"], [data-density="compact"] [data-density="comfortable"] *) {
|
|
1706
|
+
font-size: min(calc(1.0625rem * var(--type-base, 16) / 16), var(--type-ui-md-size, 12px));
|
|
1611
1707
|
line-height: var(--type-ui-leading, 16px);
|
|
1612
1708
|
}
|
|
1613
|
-
& .text-body-md {
|
|
1614
|
-
font-size: min(0.9375rem, var(--type-ui-md-size, 12px));
|
|
1709
|
+
& .text-body-md:not([data-density="compact"] [data-density="comfortable"], [data-density="compact"] [data-density="comfortable"] *) {
|
|
1710
|
+
font-size: min(calc(0.9375rem * var(--type-base, 16) / 16), var(--type-ui-md-size, 12px));
|
|
1615
1711
|
line-height: var(--type-ui-leading, 16px);
|
|
1616
1712
|
}
|
|
1617
|
-
& .text-body-sm {
|
|
1618
|
-
font-size: min(0.8125rem, var(--type-ui-sm-size, 11px));
|
|
1713
|
+
& .text-body-sm:not([data-density="compact"] [data-density="comfortable"], [data-density="compact"] [data-density="comfortable"] *) {
|
|
1714
|
+
font-size: min(calc(0.8125rem * var(--type-base, 16) / 16), var(--type-ui-sm-size, 11px));
|
|
1619
1715
|
line-height: var(--type-ui-leading, 16px);
|
|
1620
1716
|
}
|
|
1621
|
-
& .text-body-xs,
|
|
1622
|
-
& .text-caption {
|
|
1623
|
-
font-size: min(0.75rem, var(--type-ui-sm-size, 11px));
|
|
1717
|
+
& .text-body-xs:not([data-density="compact"] [data-density="comfortable"], [data-density="compact"] [data-density="comfortable"] *),
|
|
1718
|
+
& .text-caption:not([data-density="compact"] [data-density="comfortable"], [data-density="compact"] [data-density="comfortable"] *) {
|
|
1719
|
+
font-size: min(calc(0.75rem * var(--type-base, 16) / 16), var(--type-ui-sm-size, 11px));
|
|
1624
1720
|
line-height: var(--type-ui-leading, 16px);
|
|
1625
1721
|
}
|
|
1626
|
-
& .text-label-lg {
|
|
1627
|
-
font-size: min(0.875rem, var(--type-ui-md-size, 12px));
|
|
1722
|
+
& .text-label-lg:not([data-density="compact"] [data-density="comfortable"], [data-density="compact"] [data-density="comfortable"] *) {
|
|
1723
|
+
font-size: min(calc(0.875rem * var(--type-base, 16) / 16), var(--type-ui-md-size, 12px));
|
|
1628
1724
|
font-weight: var(--type-ui-md-weight, 500);
|
|
1629
1725
|
line-height: var(--type-ui-leading, 16px);
|
|
1630
1726
|
}
|
|
1631
|
-
& .text-label-md {
|
|
1632
|
-
font-size: min(0.75rem, var(--type-ui-md-size, 12px));
|
|
1727
|
+
& .text-label-md:not([data-density="compact"] [data-density="comfortable"], [data-density="compact"] [data-density="comfortable"] *) {
|
|
1728
|
+
font-size: min(calc(0.75rem * var(--type-base, 16) / 16), var(--type-ui-md-size, 12px));
|
|
1633
1729
|
font-weight: var(--type-ui-md-weight, 500);
|
|
1634
1730
|
line-height: var(--type-ui-leading, 16px);
|
|
1635
1731
|
}
|
|
1636
1732
|
/* The list utilities carry their own type, so they follow the same tiers:
|
|
1637
1733
|
items and values as body-md, terms as label-md. */
|
|
1638
|
-
& :is(.sable-list, .sable-list-numbered, .sable-list-dl) {
|
|
1639
|
-
font-size: min(0.9375rem, var(--type-ui-md-size, 12px));
|
|
1734
|
+
& :is(.sable-list, .sable-list-numbered, .sable-list-dl):not([data-density="compact"] [data-density="comfortable"], [data-density="compact"] [data-density="comfortable"] *) {
|
|
1735
|
+
font-size: min(calc(0.9375rem * var(--type-base, 16) / 16), var(--type-ui-md-size, 12px));
|
|
1640
1736
|
line-height: var(--type-ui-leading, 16px);
|
|
1641
1737
|
}
|
|
1642
|
-
& .sable-list-dl > :where(dt) {
|
|
1643
|
-
font-size: min(0.75rem, var(--type-ui-md-size, 12px));
|
|
1738
|
+
& .sable-list-dl > :where(dt):not([data-density="compact"] [data-density="comfortable"], [data-density="compact"] [data-density="comfortable"] *) {
|
|
1739
|
+
font-size: min(calc(0.75rem * var(--type-base, 16) / 16), var(--type-ui-md-size, 12px));
|
|
1644
1740
|
font-weight: var(--type-ui-md-weight, 500);
|
|
1645
1741
|
line-height: var(--type-ui-leading, 16px);
|
|
1646
1742
|
}
|
|
1647
|
-
& .text-label-sm,
|
|
1648
|
-
& .text-label-xs {
|
|
1649
|
-
font-size: min(0.6875rem, var(--type-ui-micro-size, 10px));
|
|
1743
|
+
& .text-label-sm:not([data-density="compact"] [data-density="comfortable"], [data-density="compact"] [data-density="comfortable"] *),
|
|
1744
|
+
& .text-label-xs:not([data-density="compact"] [data-density="comfortable"], [data-density="compact"] [data-density="comfortable"] *) {
|
|
1745
|
+
font-size: min(calc(0.6875rem * var(--type-base, 16) / 16), var(--type-ui-micro-size, 10px));
|
|
1650
1746
|
font-weight: var(--type-ui-micro-weight, 450);
|
|
1651
1747
|
line-height: 14px;
|
|
1652
1748
|
}
|
|
1653
|
-
& .text-title-sm {
|
|
1654
|
-
font-size: min(0.875rem, var(--type-ui-md-size, 12px));
|
|
1749
|
+
& .text-title-sm:not([data-density="compact"] [data-density="comfortable"], [data-density="compact"] [data-density="comfortable"] *) {
|
|
1750
|
+
font-size: min(calc(0.875rem * var(--type-base, 16) / 16), var(--type-ui-md-size, 12px));
|
|
1655
1751
|
font-weight: var(--type-ui-section-weight, 550);
|
|
1656
1752
|
line-height: var(--type-ui-leading, 16px);
|
|
1657
1753
|
}
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1754
|
+
/* title-lg names the thing a panel is about (the issue open in an inspector,
|
|
1755
|
+
the selected layer), so it takes the ui TITLE tier rather than ui-md. On
|
|
1756
|
+
ui-md it measured 12px/550 against a 12px description beneath it — the
|
|
1757
|
+
title and its own body the same size, hierarchy carried by weight alone. */
|
|
1758
|
+
& .text-title-lg:not([data-density="compact"] [data-density="comfortable"], [data-density="compact"] [data-density="comfortable"] *) {
|
|
1759
|
+
font-size: min(calc(1rem * var(--type-base, 16) / 16), var(--type-ui-title-size, 14px));
|
|
1760
|
+
font-weight: var(--type-ui-title-weight, 600);
|
|
1761
|
+
line-height: var(--type-ui-title-leading, 20px);
|
|
1662
1762
|
}
|
|
1663
1763
|
}
|
|
1664
1764
|
|
|
1665
1765
|
/* ==========================================================================
|
|
1666
1766
|
Layout — responsive grid spans + split panes.
|
|
1667
1767
|
|
|
1668
|
-
The fluid layout primitives (Region, Grid, Stack…)
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1768
|
+
The fluid layout primitives (Region, Grid, Stack…) put their layout in
|
|
1769
|
+
classes (`flex`, `grid`, `items-*`, `px-(--page-inset)`) and pass dynamic
|
|
1770
|
+
values as inline CSS custom properties that those classes read, so any value
|
|
1771
|
+
works without Tailwind scanning a class. Never an inline `display`, `gap` or
|
|
1772
|
+
padding: inline style beats every utility, and `<Row className="hidden
|
|
1773
|
+
md:flex">` silently did nothing. Breakpoint-aware layout can't be inline (a
|
|
1774
|
+
style attribute has no media queries), so `Col` and `SplitPane` set
|
|
1775
|
+
per-breakpoint CSS custom properties inline and these rules resolve them
|
|
1776
|
+
mobile-first. The rules sit in `@layer components` so a utility in the
|
|
1777
|
+
caller's `className` (`hidden`, `lg:grid-cols-3`, `gap-8`) still wins.
|
|
1778
|
+
Breakpoints match Tailwind's defaults (sm 40 / md 48 / lg 64 / xl 80 /
|
|
1779
|
+
2xl 96 rem) so they line up with the `lg:*` visibility utilities the
|
|
1780
|
+
app-shell components already use.
|
|
1675
1781
|
========================================================================== */
|
|
1676
1782
|
|
|
1677
1783
|
/* Each element owns its breakpoint values. Custom properties inherit, so a
|
|
@@ -1679,18 +1785,20 @@
|
|
|
1679
1785
|
Grid inside `Columns count={{ lg: 12 }}` drew 12 tracks at lg. Resetting
|
|
1680
1786
|
them here makes an unset one invalid, so the fallback chain below runs on the
|
|
1681
1787
|
element itself; the values it was given are inline and win over this. */
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1788
|
+
@layer components {
|
|
1789
|
+
[data-sable-col] {
|
|
1790
|
+
--col-span-base: initial; --col-span-sm: initial; --col-span-md: initial;
|
|
1791
|
+
--col-span-lg: initial; --col-span-xl: initial; --col-span-2xl: initial;
|
|
1792
|
+
--col-start-base: initial; --col-start-sm: initial; --col-start-md: initial;
|
|
1793
|
+
--col-start-lg: initial; --col-start-xl: initial; --col-start-2xl: initial;
|
|
1794
|
+
}
|
|
1795
|
+
[data-sable-grid-cols] {
|
|
1796
|
+
--cols-base: initial; --cols-sm: initial; --cols-md: initial;
|
|
1797
|
+
--cols-lg: initial; --cols-xl: initial; --cols-2xl: initial;
|
|
1798
|
+
}
|
|
1799
|
+
[data-sable-split] {
|
|
1800
|
+
--split-gap: initial;
|
|
1801
|
+
}
|
|
1694
1802
|
}
|
|
1695
1803
|
|
|
1696
1804
|
/* Toasts keep clear of an open Sheet's actions. A right sheet's pinned footer
|
|
@@ -1698,9 +1806,16 @@
|
|
|
1698
1806
|
top-right one.
|
|
1699
1807
|
- Where there is room, a stack on the sheet's side moves beside it. The sheet
|
|
1700
1808
|
publishes its real width (--sable-sheet-right-w / -left-w) while mounted.
|
|
1701
|
-
- On a narrower screen the sheet leaves no room beside it
|
|
1702
|
-
|
|
1703
|
-
header.
|
|
1809
|
+
- On a narrower screen the sheet leaves no room beside it and both of its
|
|
1810
|
+
edges hold controls: a footer of actions (a composer, Check out) and a
|
|
1811
|
+
header with its close button. So every stack — any position, either side
|
|
1812
|
+
— moves to the top and drops below a PROTECTED INSET: the sheet's padding
|
|
1813
|
+
plus one control row, which clears a padded SheetHeader with a close
|
|
1814
|
+
button and a 48px bar alike. It then covers the top of the sheet's
|
|
1815
|
+
scrolling content, never an action. The first version moved bottom stacks
|
|
1816
|
+
to the top edge itself, straight over the close button, and an app worked
|
|
1817
|
+
around it by switching to bottom-center — over its composer's send button.
|
|
1818
|
+
A sheet whose header is taller sets `--sable-sheet-top-inset` on <html>.
|
|
1704
1819
|
- A bottom sheet sends a bottom stack to the top, a top sheet sends a top
|
|
1705
1820
|
stack to the bottom, at any width.
|
|
1706
1821
|
A stack that moves to the other edge re-anchors its stacked toasts too: they
|
|
@@ -1715,13 +1830,11 @@
|
|
|
1715
1830
|
}
|
|
1716
1831
|
}
|
|
1717
1832
|
@media (width < 52rem) {
|
|
1718
|
-
:root:has([data-sable-sheet="right"][data-open]) [data-sable-toast-viewport]
|
|
1719
|
-
|
|
1720
|
-
top: calc(var(--spacing) * 4);
|
|
1833
|
+
:root:has(:is([data-sable-sheet="right"], [data-sable-sheet="left"])[data-open]) [data-sable-toast-viewport] {
|
|
1834
|
+
top: var(--sable-sheet-top-inset, calc(var(--spacing) * 8 + var(--control-md)));
|
|
1721
1835
|
bottom: auto;
|
|
1722
1836
|
}
|
|
1723
|
-
:root:has([data-sable-sheet="right"][data-open]) [data-sable-toast-viewport][data-position
|
|
1724
|
-
:root:has([data-sable-sheet="left"][data-open]) [data-sable-toast-viewport][data-position="bottom-left"] [data-sable-toast-stacked] {
|
|
1837
|
+
:root:has(:is([data-sable-sheet="right"], [data-sable-sheet="left"])[data-open]) [data-sable-toast-viewport][data-position^="bottom"] [data-sable-toast-stacked] {
|
|
1725
1838
|
top: 0;
|
|
1726
1839
|
bottom: auto;
|
|
1727
1840
|
transform-origin: top;
|
|
@@ -1761,126 +1874,126 @@
|
|
|
1761
1874
|
}
|
|
1762
1875
|
}
|
|
1763
1876
|
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
grid-column: var(--col-start, auto) / span var(--col-span, 1);
|
|
1768
|
-
--col-span: var(--col-span-base, 1);
|
|
1769
|
-
--col-start: var(--col-start-base, auto);
|
|
1770
|
-
}
|
|
1771
|
-
@media (width >= 40rem) {
|
|
1877
|
+
@layer components {
|
|
1878
|
+
/* `Col span={{ base, md, lg }}` / `start={…}` — each breakpoint resolves to the
|
|
1879
|
+
most specific value defined at or below it (mobile-first cascade). */
|
|
1772
1880
|
[data-sable-col] {
|
|
1773
|
-
|
|
1774
|
-
--col-
|
|
1881
|
+
grid-column: var(--col-start, auto) / span var(--col-span, 1);
|
|
1882
|
+
--col-span: var(--col-span-base, 1);
|
|
1883
|
+
--col-start: var(--col-start-base, auto);
|
|
1884
|
+
}
|
|
1885
|
+
@media (width >= 40rem) {
|
|
1886
|
+
[data-sable-col] {
|
|
1887
|
+
--col-span: var(--col-span-sm, var(--col-span-base, 1));
|
|
1888
|
+
--col-start: var(--col-start-sm, var(--col-start-base, auto));
|
|
1889
|
+
}
|
|
1775
1890
|
}
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1891
|
+
@media (width >= 48rem) {
|
|
1892
|
+
[data-sable-col] {
|
|
1893
|
+
--col-span: var(--col-span-md, var(--col-span-sm, var(--col-span-base, 1)));
|
|
1894
|
+
--col-start: var(--col-start-md, var(--col-start-sm, var(--col-start-base, auto)));
|
|
1895
|
+
}
|
|
1781
1896
|
}
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1897
|
+
@media (width >= 64rem) {
|
|
1898
|
+
[data-sable-col] {
|
|
1899
|
+
--col-span: var(--col-span-lg, var(--col-span-md, var(--col-span-sm, var(--col-span-base, 1))));
|
|
1900
|
+
--col-start: var(--col-start-lg, var(--col-start-md, var(--col-start-sm, var(--col-start-base, auto))));
|
|
1901
|
+
}
|
|
1787
1902
|
}
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1903
|
+
@media (width >= 80rem) {
|
|
1904
|
+
[data-sable-col] {
|
|
1905
|
+
--col-span: var(--col-span-xl, var(--col-span-lg, var(--col-span-md, var(--col-span-sm, var(--col-span-base, 1)))));
|
|
1906
|
+
--col-start: var(--col-start-xl, var(--col-start-lg, var(--col-start-md, var(--col-start-sm, var(--col-start-base, auto)))));
|
|
1907
|
+
}
|
|
1793
1908
|
}
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1909
|
+
@media (width >= 96rem) {
|
|
1910
|
+
[data-sable-col] {
|
|
1911
|
+
--col-span: var(--col-span-2xl, var(--col-span-xl, var(--col-span-lg, var(--col-span-md, var(--col-span-sm, var(--col-span-base, 1))))));
|
|
1912
|
+
--col-start: var(--col-start-2xl, var(--col-start-xl, var(--col-start-lg, var(--col-start-md, var(--col-start-sm, var(--col-start-base, auto))))));
|
|
1913
|
+
}
|
|
1799
1914
|
}
|
|
1800
|
-
}
|
|
1801
1915
|
|
|
1802
|
-
/* `Columns count` / `Grid cols` as a breakpoint map — set per-breakpoint --cols-*
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
[data-sable-grid-cols] {
|
|
1806
|
-
display: grid;
|
|
1807
|
-
grid-template-columns: repeat(var(--cols, var(--grid-columns)), minmax(0, 1fr));
|
|
1808
|
-
--cols: var(--cols-base, var(--grid-columns));
|
|
1809
|
-
}
|
|
1810
|
-
@media (width >= 40rem) {
|
|
1916
|
+
/* `Columns count` / `Grid cols` as a breakpoint map — set per-breakpoint --cols-*
|
|
1917
|
+
props inline; resolved mobile-first into the track's column count, so a grid
|
|
1918
|
+
thins to fewer columns on small screens (e.g. 2 → 6 → 12). */
|
|
1811
1919
|
[data-sable-grid-cols] {
|
|
1812
|
-
|
|
1920
|
+
grid-template-columns: repeat(var(--cols, var(--grid-columns)), minmax(0, 1fr));
|
|
1921
|
+
--cols: var(--cols-base, var(--grid-columns));
|
|
1813
1922
|
}
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1923
|
+
@media (width >= 40rem) {
|
|
1924
|
+
[data-sable-grid-cols] {
|
|
1925
|
+
--cols: var(--cols-sm, var(--cols-base, var(--grid-columns)));
|
|
1926
|
+
}
|
|
1818
1927
|
}
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
--cols-lg,
|
|
1824
|
-
var(--cols-md, var(--cols-sm, var(--cols-base, var(--grid-columns))))
|
|
1825
|
-
);
|
|
1928
|
+
@media (width >= 48rem) {
|
|
1929
|
+
[data-sable-grid-cols] {
|
|
1930
|
+
--cols: var(--cols-md, var(--cols-sm, var(--cols-base, var(--grid-columns))));
|
|
1931
|
+
}
|
|
1826
1932
|
}
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
--cols: var(
|
|
1831
|
-
--cols-xl,
|
|
1832
|
-
var(
|
|
1933
|
+
@media (width >= 64rem) {
|
|
1934
|
+
[data-sable-grid-cols] {
|
|
1935
|
+
--cols: var(
|
|
1833
1936
|
--cols-lg,
|
|
1834
1937
|
var(--cols-md, var(--cols-sm, var(--cols-base, var(--grid-columns))))
|
|
1835
|
-
)
|
|
1836
|
-
|
|
1938
|
+
);
|
|
1939
|
+
}
|
|
1837
1940
|
}
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
--cols: var(
|
|
1842
|
-
--cols-2xl,
|
|
1843
|
-
var(
|
|
1941
|
+
@media (width >= 80rem) {
|
|
1942
|
+
[data-sable-grid-cols] {
|
|
1943
|
+
--cols: var(
|
|
1844
1944
|
--cols-xl,
|
|
1845
1945
|
var(
|
|
1846
1946
|
--cols-lg,
|
|
1847
1947
|
var(--cols-md, var(--cols-sm, var(--cols-base, var(--grid-columns))))
|
|
1848
1948
|
)
|
|
1849
|
-
)
|
|
1850
|
-
|
|
1949
|
+
);
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
@media (width >= 96rem) {
|
|
1953
|
+
[data-sable-grid-cols] {
|
|
1954
|
+
--cols: var(
|
|
1955
|
+
--cols-2xl,
|
|
1956
|
+
var(
|
|
1957
|
+
--cols-xl,
|
|
1958
|
+
var(
|
|
1959
|
+
--cols-lg,
|
|
1960
|
+
var(--cols-md, var(--cols-sm, var(--cols-base, var(--grid-columns))))
|
|
1961
|
+
)
|
|
1962
|
+
)
|
|
1963
|
+
);
|
|
1964
|
+
}
|
|
1851
1965
|
}
|
|
1852
|
-
}
|
|
1853
1966
|
|
|
1854
|
-
/* `SplitPane collapseBelow="lg"` — a single stacked column below the breakpoint;
|
|
1855
|
-
|
|
1856
|
-
[data-sable-split] {
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
grid-template-columns: 1fr;
|
|
1860
|
-
}
|
|
1861
|
-
@media (width >= 40rem) {
|
|
1862
|
-
[data-sable-split][data-collapse="sm"] {
|
|
1863
|
-
grid-template-columns: var(--split-primary, 1fr) var(--split-secondary, 1fr);
|
|
1967
|
+
/* `SplitPane collapseBelow="lg"` — a single stacked column below the breakpoint;
|
|
1968
|
+
a two-column track (primary:secondary fr ratio) at or above it. */
|
|
1969
|
+
[data-sable-split] {
|
|
1970
|
+
gap: var(--split-gap, var(--grid-gutter));
|
|
1971
|
+
grid-template-columns: 1fr;
|
|
1864
1972
|
}
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1973
|
+
@media (width >= 40rem) {
|
|
1974
|
+
[data-sable-split][data-collapse="sm"] {
|
|
1975
|
+
grid-template-columns: var(--split-primary, 1fr) var(--split-secondary, 1fr);
|
|
1976
|
+
}
|
|
1869
1977
|
}
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1978
|
+
@media (width >= 48rem) {
|
|
1979
|
+
[data-sable-split][data-collapse="md"] {
|
|
1980
|
+
grid-template-columns: var(--split-primary, 1fr) var(--split-secondary, 1fr);
|
|
1981
|
+
}
|
|
1874
1982
|
}
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1983
|
+
@media (width >= 64rem) {
|
|
1984
|
+
[data-sable-split][data-collapse="lg"] {
|
|
1985
|
+
grid-template-columns: var(--split-primary, 1fr) var(--split-secondary, 1fr);
|
|
1986
|
+
}
|
|
1879
1987
|
}
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1988
|
+
@media (width >= 80rem) {
|
|
1989
|
+
[data-sable-split][data-collapse="xl"] {
|
|
1990
|
+
grid-template-columns: var(--split-primary, 1fr) var(--split-secondary, 1fr);
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
@media (width >= 96rem) {
|
|
1994
|
+
[data-sable-split][data-collapse="2xl"] {
|
|
1995
|
+
grid-template-columns: var(--split-primary, 1fr) var(--split-secondary, 1fr);
|
|
1996
|
+
}
|
|
1884
1997
|
}
|
|
1885
1998
|
}
|
|
1886
1999
|
|
|
@@ -2043,7 +2156,7 @@
|
|
|
2043
2156
|
@utility checkerboard {
|
|
2044
2157
|
background-image: repeating-conic-gradient(
|
|
2045
2158
|
var(--panel) 0% 25%,
|
|
2046
|
-
var(--checkerboard-alt, color-mix(in
|
|
2159
|
+
var(--checkerboard-alt, color-mix(in oklab, var(--panel) 88%, var(--foreground)))
|
|
2047
2160
|
0% 50%
|
|
2048
2161
|
);
|
|
2049
2162
|
background-size: var(--checkerboard-size, 16px) var(--checkerboard-size, 16px);
|