@sondalab/ui-kit 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,9 +1,10 @@
1
1
  # @sondalab/ui-kit
2
2
 
3
- Sondalab design tokens as CSS custom properties (`--sl-*`). CSS-only: no components, no build step — import the stylesheets and theme via a `data-sl-theme` attribute.
3
+ Sondalab design tokens as CSS custom properties (`--sl-*`) plus a CSS-only component layer (`.sl-*`). No build step, no runtime JS — import the stylesheets and theme via a `data-sl-theme` attribute.
4
4
 
5
5
  ```css
6
6
  @import "@sondalab/ui-kit/tokens.css"; /* shared: type, spacing, radii, motion, shadow, z */
7
+ @import "@sondalab/ui-kit/components.css"; /* .sl-* components (reads role-vars, see below) */
7
8
  @import "@sondalab/ui-kit/themes/light.css"; /* [data-sl-theme="light"] surfaces, text, borders, status, accent */
8
9
  @import "@sondalab/ui-kit/themes/dark.css";
9
10
  @import "@sondalab/ui-kit/themes/high-contrast.css";
@@ -22,4 +23,44 @@ Sondalab design tokens as CSS custom properties (`--sl-*`). CSS-only: no compone
22
23
 
23
24
  **Fonts** (load separately, e.g. Google Fonts): Fraunces (display), Instrument Sans (body), Martian Mono (mono).
24
25
 
25
- Generated from the canonical `sondalab.tokens.json` — do not hand-edit the CSS.
26
+ ## Components (`components.css`)
27
+
28
+ Primitives: `.sl-eyebrow`, `.sl-tag` (`--plain`), `.sl-btn` (`--primary` / `--ghost` / `--sm`), `.sl-card` (`__title` / `__body`), `.sl-badge` (`--success` / `--warning` / `--danger` / `--info`), `.sl-field` (`__label` / `__input`), `.sl-kbd`, `.sl-code`, `.sl-link`, `.sl-rule` (`--labeled`).
29
+
30
+ Complex (composed shells — no behaviour JS; the consumer wires interaction): `.sl-callout` (`--success`/`--warning`/`--danger`/`--info`), `.sl-table` (`--numeric`; wrap in an `overflow-x:auto` container), `.sl-dialog` (visual shell for the native `<dialog>` — drive with `.showModal()`/`.close()`), `.sl-tabs` (`__list`/`__tab` — supply your own ARIA + panel switching), `.sl-tooltip` (CSS-only via `data-sl-tooltip`).
31
+
32
+ ### Colour contract — role-vars (`--slc-*`)
33
+
34
+ Components never read theme tokens directly (those resolve only under `[data-sl-theme]`). They read role-vars that default through a fallback chain to the `--sl-*` token, then to a brand literal. **Tier A** products (full `data-sl-theme`, e.g. spexr) need zero wiring — the role-vars pick up the live theme automatically. **Tier B** products (value-pinned, e.g. daos, introspect) map the role-vars **once** to their own colour layer. That block is the *entire* integration surface:
35
+
36
+ ```css
37
+ :root {
38
+ --slc-accent: var(--your-accent);
39
+ --slc-accent-hover: var(--your-accent-hover);
40
+ --slc-accent-active: var(--your-accent-active);
41
+ --slc-accent-subtle: var(--your-accent-tint); /* ~12% accent over surface */
42
+ --slc-on-accent: var(--your-on-accent); /* text on a filled accent */
43
+ --slc-surface: var(--your-surface);
44
+ --slc-raised: var(--your-raised);
45
+ --slc-overlay: var(--your-overlay); /* dialog backdrop */
46
+ --slc-text: var(--your-text);
47
+ --slc-text-secondary: var(--your-text-2);
48
+ --slc-text-muted: var(--your-text-muted);
49
+ --slc-border: var(--your-border);
50
+ --slc-border-subtle: var(--your-border-subtle);
51
+ --slc-border-strong: var(--your-border-strong);
52
+ --slc-focus: var(--your-accent);
53
+ --slc-success: var(--your-success); --slc-warning: var(--your-warning);
54
+ --slc-danger: var(--your-danger); --slc-info: var(--your-info);
55
+ }
56
+ ```
57
+
58
+ **Inversion bands.** `--slc-border` defaults to an alpha-over-canvas value; inside a band whose background is the strongest neutral (`.invert`), that alpha sits on the wrong ground and the hairline disappears. Re-derive it at the band from the band's foreground — no new token:
59
+
60
+ ```css
61
+ .invert { --slc-border: color-mix(in srgb, currentColor 22%, transparent); }
62
+ ```
63
+
64
+ The full reference implementation — every component in all three themes — is `showcase/index.html` (§04).
65
+
66
+ Generated tokens (`tokens.css`, `themes/*.css`) come from the canonical `sondalab.tokens.json` — do not hand-edit them. `components.css` is hand-authored.
@@ -0,0 +1,53 @@
1
+ # Sondalab logo assets
2
+
3
+ The Sondalab logo is **typographic** — no pictorial mark. These SVGs are the
4
+ official wordmark with the letterforms converted to **outline paths**, so they
5
+ render identically anywhere without the fonts installed.
6
+
7
+ | File | Form | Font (baked) |
8
+ |---|---|---|
9
+ | `sondalab-wordmark.svg` | primary — `sondalab.` | Fraunces, wght 500, opsz 144 |
10
+ | `sondalab-lockup.svg` | compact — `SONDA·LAB` | Martian Mono, wght 300 |
11
+ | `favicon.svg` | the mark — the amber dot alone | — |
12
+ | `app-icon.svg` | the mark on an ink tile (rounded) | — |
13
+
14
+ `favicon.svg` is the brand's accent dot (fixed `#F5A83C`) on transparent — the
15
+ tab/app icon. Wire it as `<link rel="icon" href="…/assets/favicon.svg">`.
16
+ (Claude Artifacts take an emoji favicon, not an SVG — use 🟠 there to match.)
17
+
18
+ `app-icon.svg` is the same dot on a rounded ink tile (`#0F151A`) — the maskable /
19
+ apple-touch icon where a bare transparent dot needs a shape and contrast.
20
+
21
+ ## Colour
22
+
23
+ - **Letters** use `fill="currentColor"` — inline the SVG and they inherit the
24
+ surrounding text colour, so the mark adapts to light / dark automatically.
25
+ - **The dot** (trailing `.` / middle `·`) uses `fill="var(--sl-accent-default, #F5A83C)"`
26
+ — inline with the token layer it takes the active theme accent; used as a
27
+ plain `<img>` (where CSS variables don't apply) it falls back to the brand
28
+ amber `#F5A83C`.
29
+
30
+ Inline for full theme-awareness:
31
+
32
+ ```html
33
+ <span style="color: var(--sl-text-primary)">
34
+ <!-- paste sondalab-wordmark.svg here, or load + inline it -->
35
+ </span>
36
+ ```
37
+
38
+ As a static image (dot fixed to `#F5A83C`):
39
+
40
+ ```html
41
+ <img src="@sondalab/ui-kit/assets/wordmark.svg" alt="Sondalab" height="28">
42
+ ```
43
+
44
+ ## Source of truth & regeneration
45
+
46
+ The visual reference is the identity board
47
+ (`https://claude.ai/code/artifact/abbebb7f-5778-4af6-a9b4-2b3f169ae20f`); the
48
+ type/colour spec lives in `sondalab-ui/docs/design-language.md` (L3 → Wordmark).
49
+
50
+ The paths were generated from the variable fonts (Fraunces, Martian Mono)
51
+ instanced at the weights above and shaped with HarfBuzz, then outlined with
52
+ fontTools. To regenerate after a brand-type change, re-run that outline step
53
+ against the updated axis values — do not hand-edit the path data.
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="Sondalab">
2
+ <rect width="64" height="64" rx="14" fill="#0F151A"/>
3
+ <circle cx="32" cy="32" r="13" fill="#F5A83C"/>
4
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" role="img" aria-label="Sondalab">
2
+ <circle cx="16" cy="16" r="11.5" fill="#F5A83C"/>
3
+ </svg>
@@ -0,0 +1,13 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="54.8 -855.2 6661.2 910.4" role="img" aria-label="SONDA·LAB" fill="currentColor">
2
+ <g transform="scale(1,-1)">
3
+ <path fill="currentColor" d="M192.59954833984375 204.0Q207.7994384765625 143.1995849609375 256.8995666503906 110.9993896484375Q305.99969482421875 78.7991943359375 383.80010986328125 78.7991943359375Q465.00030517578125 78.7991943359375 511.7004089355469 116.89935302734375Q558.4005126953125 154.99951171875 558.4005126953125 220.7998046875Q558.4005126953125 274.0001220703125 525.6004028320312 304.8002624511719Q492.80029296875 335.60040283203125 426.4000244140625 343.200439453125L324.4000244140625 355.200439453125Q215.40020751953125 368.60040283203125 159.90029907226562 424.30035400390625Q104.400390625 480.00030517578125 104.400390625 577.2001953125Q104.400390625 649.400146484375 139.40032958984375 702.60009765625Q174.4002685546875 755.800048828125 237.8001708984375 785.5Q301.2000732421875 815.199951171875 385.79998779296875 815.199951171875Q470.199951171875 815.199951171875 533.599853515625 786.6999816894531Q596.999755859375 758.2000122070312 633.7996826171875 704.9000244140625Q670.599609375 651.6000366210938 675.599609375 576.0H579.4004516601562Q565.2005615234375 646.0004272460938 515.1004638671875 683.6006164550781Q465.0003662109375 721.2008056640625 385.79998779296875 721.2008056640625Q300.3997802734375 721.2008056640625 251.399658203125 682.6006469726562Q202.3995361328125 644.00048828125 202.3995361328125 577.2001953125Q202.3995361328125 523.9998779296875 235.59963989257812 493.5997314453125Q268.79974365234375 463.1995849609375 334.4000244140625 454.799560546875L436.4000244140625 442.799560546875Q546.1998291015625 430.1995849609375 601.2997436523438 374.0996398925781Q656.399658203125 317.99969482421875 656.399658203125 220.7998046875Q656.399658203125 149.599853515625 622.4997253417969 96.49990844726562Q588.5997924804688 43.39996337890625 527.39990234375 14.100006103515625Q466.20001220703125 -15.199951171875 383.80010986328125 -15.199951171875Q299.20013427734375 -15.199951171875 236.00021362304688 10.800018310546875Q172.80029296875 36.79998779296875 136.40036010742188 86.0999755859375Q100.00042724609375 135.39996337890625 94.8004150390625 204.0Z"/>
4
+ <path fill="currentColor" d="M1125.0191094465317 -15.199951171875Q972.0001831054688 -15.199951171875 894.0002746582031 89.59746411682325Q816.0003662109375 194.3948794055215 816.0003662109375 399.9974274957295Q816.0003662109375 605.5999755859375 893.9811652116715 710.3999633789062Q971.9619642124055 815.199951171875 1124.9808905534683 815.199951171875Q1277.9998168945312 815.199951171875 1355.9997253417969 710.4025358831768Q1433.9996337890625 605.6051205944785 1433.9996337890625 400.0025725042705Q1433.9996337890625 194.4000244140625 1356.0188347883286 89.60003662109375Q1278.0380357875947 -15.199951171875 1125.0191094465317 -15.199951171875ZM1125.0 78.7991943359375Q1231.4002075195312 78.7991943359375 1282.9003601074219 158.09942626953125Q1334.4005126953125 237.399658203125 1334.4005126953125 400.0Q1334.4005126953125 562.600341796875 1282.9003601074219 641.9005737304688Q1231.4002075195312 721.2008056640625 1125.0 721.2008056640625Q1018.5997924804688 721.2008056640625 967.0996398925781 641.9005737304688Q915.5994873046875 562.600341796875 915.5994873046875 400.0Q915.5994873046875 237.399658203125 967.0996398925781 158.09942626953125Q1018.5997924804688 78.7991943359375 1125.0 78.7991943359375Z"/>
5
+ <path fill="currentColor" d="M1598.0003662109375 0.0V800.0H1773.3988647460938L2051.4004516601562 61.99951171875H2060.8004150390625L2057.6004638671875 225.39849853515625V800.0H2151.9996337890625V0.0H1976.6011352539062L1698.5995483398438 738.00048828125H1689.1995849609375L1692.3995361328125 575.2015380859375V0.0Z"/>
6
+ <path fill="currentColor" d="M2356.0003662109375 0.0V800.0H2588.39990234375Q2758.3997192382812 800.0 2846.199676513672 697.9999694824219Q2933.9996337890625 595.9999389648438 2933.9996337890625 400.0Q2933.9996337890625 204.800048828125 2846.199676513672 102.4000244140625Q2758.3997192382812 0.0 2588.39990234375 0.0ZM2455.5994873046875 93.9991455078125H2588.39990234375Q2709.400146484375 93.9991455078125 2771.9003295898438 171.59939575195312Q2834.4005126953125 249.19964599609375 2834.4005126953125 400.0Q2834.4005126953125 551.600341796875 2771.9003295898438 628.8005981445312Q2709.400146484375 706.0008544921875 2588.39990234375 706.0008544921875H2455.5994873046875Z"/>
7
+ <path fill="currentColor" d="M3062.8004150390625 0.0 3293.8007202148438 800.0H3456.1992797851562L3687.1995849609375 0.0H3582.00048828125L3376.7999877929688 721.6005859375H3367.6000366210938L3161.799560546875 0.0ZM3191.400390625 282.00067138671875V375.99981689453125H3559.399658203125V282.00067138671875Z"/>
8
+ <path fill="var(--sl-accent-default, #F5A83C)" d="M4125.0 316.0006103515625Q4083.0003051757812 316.0006103515625 4059.6004638671875 338.0004577636719Q4036.2006225585938 360.00030517578125 4036.2006225585938 400.0Q4036.2006225585938 439.99969482421875 4059.6004638671875 461.9995422363281Q4083.0003051757812 483.9993896484375 4125.100006103516 483.9993896484375Q4167.19970703125 483.9993896484375 4190.499542236328 461.9995422363281Q4213.799377441406 439.99969482421875 4213.799377441406 400.0Q4213.799377441406 360.00030517578125 4190.478328820431 338.0004577636719Q4167.157280199455 316.0006103515625 4125.0 316.0006103515625Z"/>
9
+ <path fill="currentColor" d="M4694.000244140625 0.0V800.0H4793.599365234375V93.9991455078125H5180.0V0Z"/>
10
+ <path fill="currentColor" d="M5312.8004150390625 0.0 5543.800720214844 800.0H5706.199279785156L5937.1995849609375 0.0H5832.00048828125L5626.799987792969 721.6005859375H5617.600036621094L5411.799560546875 0.0ZM5441.400390625 282.00067138671875V375.99981689453125H5809.399658203125V282.00067138671875Z"/>
11
+ <path fill="currentColor" d="M6138.00048828125 0.0V800.0H6393.9998779296875Q6519.199890136719 800.0 6590.999847412109 742.300048828125Q6662.7998046875 684.60009765625 6662.7998046875 584.0001220703125Q6662.7998046875 523.199951171875 6630.799713134766 479.89990234375Q6598.799621582031 436.599853515625 6540.7994384765625 420.39990234375V405.5999755859375Q6605.399597167969 387.4000244140625 6640.699676513672 338.6000061035156Q6675.999755859375 289.79998779296875 6675.999755859375 219.9998779296875Q6675.999755859375 117.19989013671875 6600.899810791016 58.599945068359375Q6525.799865722656 0.0 6393.9998779296875 0.0ZM6237.599609375 92.399169921875H6393.9998779296875Q6482.6002197265625 92.399169921875 6529.500427246094 127.49932861328125Q6576.400634765625 162.5994873046875 6576.400634765625 226.3997802734375Q6576.400634765625 290.60009765625 6529.500427246094 325.70025634765625Q6482.6002197265625 360.8004150390625 6393.9998779296875 360.8004150390625H6237.599609375ZM6237.599609375 447.9996337890625H6393.9998779296875Q6477.800231933594 447.9996337890625 6522.200439453125 481.59979248046875Q6566.600646972656 515.199951171875 6566.600646972656 577.6002197265625Q6566.600646972656 640.4005126953125 6522.200439453125 674.0006713867188Q6477.800231933594 707.600830078125 6393.9998779296875 707.600830078125H6237.599609375Z"/>
12
+ </g>
13
+ </svg>
@@ -0,0 +1,13 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="-33.0 -1558.0 6619.5 1658.0" role="img" aria-label="sondalab." fill="currentColor">
2
+ <g transform="scale(1,-1)">
3
+ <path fill="currentColor" d="M404 -1Q477 -1 520.0 37.5Q563 76 563 138Q563 181 543.25 215.25Q523.5 249.5 476.5 278.25Q429.5 307.0 348 333Q234.0 370.5 168.25 415.0Q102.5 459.5 74.75 515.25Q47 571 47 642Q47.0 763.5 129.5 829.75Q212 896 349 896Q409.5 896.0 448.5 884.25Q487.5 872.5 508.25 860.75Q529 849 535 849Q544 849 567.0 860.75Q590.0 872.5 612.25 884.25Q634.5 896.0 641 896Q644.5 896.0 647.75 894.5Q651 893 652 886L708 605Q710 598 709.0 593.5Q708 589 705 587Q702 586 699.25 587.25Q696.5 588.5 694 592Q641.0 699.5 589.0 762.5Q537.0 825.5 480.5 852.75Q424 880 357 880Q277.5 880.0 232.75 840.0Q188 800 188 733Q188 690 207.75 655.0Q227.5 620.0 278.25 590.75Q329.0 561.5 422 535Q525 505 587.75 462.0Q650.5 419.0 678.75 363.0Q707 307 707 238Q707.0 159.5 669.25 102.0Q631.5 44.5 566.5 12.75Q501.5 -19.0 419 -19Q364.5 -19.0 324.5 -3.0Q284.5 13.0 260.25 29.0Q236 45 230 45Q225 45 206.25 30.25Q187.5 15.5 167.5 0.75Q147.5 -14.0 140 -14Q136 -14 131.5 -10.25Q127.0 -6.5 125 3L79 246Q78 256 78.75 260.5Q79.5 265.0 83 267Q85.5 269.0 87.75 267.25Q90.0 265.5 92 262Q168.0 117.5 247.5 58.25Q327 -1 404 -1Z"/>
4
+ <path fill="currentColor" d="M1160.5 893.0Q1289.5 893.0 1389.5 834.5Q1489.5 776.0 1547.0 672.25Q1604.5 568.5 1604.5 433.0Q1604.5 299.0 1545.75 197.0Q1487.0 95 1384.5 37.5Q1282.0 -20 1149.5 -20.0Q1020.5 -20.0 921.0 37.25Q821.5 94.5 765.0 196.5Q708.5 298.5 708.5 433.0Q708.5 567.5 766.0 671.0Q823.5 774.5 925.5 833.75Q1027.5 893.0 1160.5 893.0ZM1208.0 -4Q1276.0 2 1321.0 56.75Q1366.0 111.5 1383.25 212.75Q1400.5 314.0 1384.5 458.5Q1368.5 604.5 1330.0 699.75Q1291.5 795.0 1234.5 839.25Q1177.5 883.5 1105.5 877.0Q1034.5 870.5 989.75 814.5Q945.0 758.5 929.75 657.5Q914.5 556.5 930.0 414Q946.0 272 985.25 176.5Q1024.5 81.0 1081.75 35.5Q1139.0 -10 1208.0 -4Z"/>
5
+ <path fill="currentColor" d="M1885.0 879V53Q1885.0 40.5 1890.75 33.0Q1896.5 25.5 1909.0 23L1968.0 13.5Q1978.0 12 1978.0 6Q1978.0 0 1970.0 0H1589.0Q1586.5 0.0 1584.25 1.75Q1582.0 3.5 1582.0 6Q1582.0 8 1584.0 9.75Q1586.0 11.5 1591.0 12.5L1653.0 23Q1666.0 25.5 1671.5 33.0Q1677.0 40.5 1677.0 52V787Q1677.0 792.5 1674.25 795.75Q1671.5 799.0 1664.5 799.0H1593.0Q1589.0 799 1587.0 801.0Q1585.0 803 1585.0 805.5Q1585.0 809 1587.25 810.5Q1589.5 812.0 1593.0 813L1856.5 886.5Q1865.0 889 1868.25 889.5Q1871.5 890.0 1875.0 890Q1880.0 890 1882.5 886.75Q1885.0 883.5 1885.0 879ZM1868.0 688.5 1859.0 698 1894.0 729.5Q1991.0 817 2061.0 855.0Q2131.0 893 2194.0 893Q2286.0 893 2337.25 834.0Q2388.5 775.0 2405.0 651L2481.5 60.0Q2483.5 44.0 2490.5 33.75Q2497.5 23.5 2513.5 21.0L2564.5 12.5Q2569.5 12.0 2571.5 10.25Q2573.5 8.5 2573.5 6.0Q2573.5 3.5 2571.5 1.75Q2569.5 0.0 2565.5 0.0H2178.0Q2169.0 0 2169.0 6Q2169.0 11 2180.0 13.5L2241.0 23Q2258.0 25.5 2264.5 35.75Q2271.0 46 2269.0 60L2200.0 630Q2188.0 719 2157.25 760.0Q2126.5 801.0 2066.0 801Q2026.0 801 1986.75 780.75Q1947.5 760.5 1902.0 719Z"/>
6
+ <path fill="currentColor" d="M3149.5 119.0V123.5V1375.0Q3149.5 1380.5 3146.75 1383.75Q3144.0 1387 3137.0 1387H3065.5Q3061.5 1387.0 3059.5 1389.0Q3057.5 1391.0 3057.5 1393.5Q3057.5 1397.0 3059.75 1398.5Q3062.0 1400 3065.5 1401.0L3329.0 1474.5Q3337.5 1477.0 3340.75 1477.5Q3344.0 1478 3347.5 1478.0Q3352.5 1478.0 3355.0 1474.75Q3357.5 1471.5 3357.5 1467.0V53.0Q3357.5 40.5 3363.25 33.0Q3369.0 25.5 3381.5 23.0L3440.5 13.5Q3446.5 13.0 3448.5 11.0Q3450.5 9.0 3450.5 6.0Q3450.5 3.5 3448.5 1.75Q3446.5 0.0 3442.5 0.0H3176.5Q3163.5 0.0 3156.5 7.5Q3149.5 15.0 3149.5 31.0ZM2511.5 412.5Q2511.5 561.5 2567.5 669.25Q2623.5 777.0 2717.0 835.0Q2810.5 893.0 2923.5 893.0Q3023.5 893.0 3089.75 852.25Q3156.0 811.5 3196.5 742.0L3179.5 734.0Q3149.0 794 3095.75 829.5Q3042.5 865.0 2969.5 865.0Q2901.0 865 2845.0 821.0Q2789.0 777 2755.75 681.75Q2722.5 586.5 2722.5 432.5Q2722.5 295.5 2751.25 205.75Q2780.0 116 2830.75 72.0Q2881.5 28.0 2947.5 28.0Q2999.0 28 3055.25 56.75Q3111.5 85.5 3163.5 152.0L3173.5 141.0Q3098.0 52 3029.25 16.0Q2960.5 -20.0 2877.5 -20.0Q2771.5 -20.0 2688.75 32.5Q2606.0 85 2558.75 182.25Q2511.5 279.5 2511.5 412.5Z"/>
7
+ <path fill="currentColor" d="M3922.5 92.5V100.5L3913.0 92V715Q3913.0 795.5 3880.5 838.25Q3848.0 881 3785.0 881Q3715.0 881 3681.5 847.0Q3648.0 813 3648.0 773V698Q3648.0 652.5 3616.75 622.25Q3585.5 592.0 3537.0 592Q3502.0 592 3479.0 614.0Q3456.0 636 3456.0 680Q3456.0 731.5 3496.25 780.75Q3536.5 830.0 3615.5 862.0Q3694.5 894.0 3809.5 894.0Q3967.0 894 4044.5 826.5Q4122.0 759 4122.0 637V112Q4122.0 74 4134.75 57.5Q4147.5 41.0 4166.5 41.0Q4184.5 41.0 4198.75 52.0Q4213.0 63 4216.0 87Q4216.5 90.5 4218.0 91.75Q4219.5 93.0 4221.0 93Q4223.5 93.0 4224.5 91.75Q4225.5 90.5 4225.5 87.0Q4225.5 69.5 4209.75 45.0Q4194.0 20.5 4159.0 1.5Q4124.0 -17.5 4066.0 -17.5Q3992.0 -17.5 3957.25 13.0Q3922.5 43.5 3922.5 92.5ZM3407.0 193Q3407.0 298.5 3494.5 364.25Q3582.0 430 3767.0 430Q3833.0 430 3875.75 417.25Q3918.5 404.5 3955.0 386L3948.0 379Q3911.5 396.0 3872.75 406.0Q3834.0 416 3786.0 416Q3703.5 416.0 3659.75 365.0Q3616.0 314 3616.0 224Q3616.0 136.5 3657.75 89.25Q3699.5 42.0 3767.0 42Q3813.0 42 3857.75 62.75Q3902.5 83.5 3932.5 123.0L3942.5 117.0Q3898.5 51.5 3822.25 16.75Q3746.0 -18 3658.0 -18Q3546.0 -18 3476.5 41.0Q3407.0 100 3407.0 193Z"/>
8
+ <path fill="currentColor" d="M4495.0 1467V53Q4495.0 40.5 4500.75 33.0Q4506.5 25.5 4519.0 23L4578.0 13.5Q4584.0 13 4586.0 11.0Q4588.0 9 4588.0 6Q4588.0 3.5 4586.0 1.75Q4584.0 0 4580.0 0H4199.0Q4196.5 0.0 4194.25 1.75Q4192.0 3.5 4192.0 6Q4192.0 8.5 4195.0 11.0Q4198.0 13.5 4205.0 14.5L4263.0 23Q4276.0 25.5 4281.5 33.0Q4287.0 40.5 4287.0 52V1375Q4287.0 1380.5 4284.25 1383.75Q4281.5 1387.0 4274.5 1387.0H4203.0Q4199.0 1387 4197.0 1389.0Q4195.0 1391 4195.0 1393.5Q4195.0 1397 4197.25 1398.5Q4199.5 1400.0 4203.0 1401L4466.5 1474.5Q4475.0 1477 4478.25 1477.5Q4481.5 1478.0 4485.0 1478Q4490.0 1478 4492.5 1474.75Q4495.0 1471.5 4495.0 1467Z"/>
9
+ <path fill="currentColor" d="M5080.5 92.5V100.5L5071.0 92V715Q5071.0 795.5 5038.5 838.25Q5006.0 881 4943.0 881Q4873.0 881 4839.5 847.0Q4806.0 813 4806.0 773V698Q4806.0 652.5 4774.75 622.25Q4743.5 592.0 4695.0 592Q4660.0 592 4637.0 614.0Q4614.0 636 4614.0 680Q4614.0 731.5 4654.25 780.75Q4694.5 830.0 4773.5 862.0Q4852.5 894.0 4967.5 894.0Q5125.0 894 5202.5 826.5Q5280.0 759 5280.0 637V112Q5280.0 74 5292.75 57.5Q5305.5 41.0 5324.5 41.0Q5342.5 41.0 5356.75 52.0Q5371.0 63 5374.0 87Q5374.5 90.5 5376.0 91.75Q5377.5 93.0 5379.0 93Q5381.5 93.0 5382.5 91.75Q5383.5 90.5 5383.5 87.0Q5383.5 69.5 5367.75 45.0Q5352.0 20.5 5317.0 1.5Q5282.0 -17.5 5224.0 -17.5Q5150.0 -17.5 5115.25 13.0Q5080.5 43.5 5080.5 92.5ZM4565.0 193Q4565.0 298.5 4652.5 364.25Q4740.0 430 4925.0 430Q4991.0 430 5033.75 417.25Q5076.5 404.5 5113.0 386L5106.0 379Q5069.5 396.0 5030.75 406.0Q4992.0 416 4944.0 416Q4861.5 416.0 4817.75 365.0Q4774.0 314 4774.0 224Q4774.0 136.5 4815.75 89.25Q4857.5 42.0 4925.0 42Q4971.0 42 5015.75 62.75Q5060.5 83.5 5090.5 123.0L5100.5 117.0Q5056.5 51.5 4980.25 16.75Q4904.0 -18 4816.0 -18Q4704.0 -18 4634.5 41.0Q4565.0 100 4565.0 193Z"/>
10
+ <path fill="currentColor" d="M5608.0 1467V76.5L5424.0 -6Q5420.5 -8.0 5416.75 -9.5Q5413.0 -11 5409.0 -11Q5405.5 -11.0 5402.75 -8.5Q5400.0 -6 5400.0 -2V1375Q5400.0 1380.5 5397.25 1383.75Q5394.5 1387.0 5387.5 1387.0H5316.0Q5312.0 1387 5310.0 1389.0Q5308.0 1391 5308.0 1393.5Q5308.0 1397 5310.25 1398.5Q5312.5 1400.0 5316.0 1401L5579.5 1474.5Q5588.0 1477 5591.25 1477.5Q5594.5 1478.0 5598.0 1478Q5603.0 1478 5605.5 1474.75Q5608.0 1471.5 5608.0 1467ZM5593.0 721 5583.0 732Q5659.0 821.5 5727.5 857.25Q5796.0 893 5879.0 893Q5985.0 893 6067.75 840.5Q6150.5 788.0 6197.75 691.0Q6245.0 594 6245.0 460.5Q6245.0 316 6192.5 207.75Q6140.0 99.5 6047.0 39.75Q5954.0 -20 5833.0 -20Q5733.0 -20 5667.0 20.75Q5601.0 61.5 5560.0 131L5577.0 139Q5607.5 79.0 5659.75 43.5Q5712.0 8 5783.0 8Q5852.0 8 5908.75 52.0Q5965.5 96.0 5999.0 191.5Q6032.5 287.0 6032.5 440.5Q6032.5 580.0 6003.75 670.75Q5975.0 761.5 5924.75 806.25Q5874.5 851.0 5809.0 851Q5758.5 851.0 5702.5 820.25Q5646.5 789.5 5593.0 721Z"/>
11
+ <path fill="var(--sl-accent-default, #F5A83C)" d="M6378.741819961297 -17.0Q6343.0 -17 6314.592105263158 1.4773159172085357Q6286.184210526316 19.95463183441707 6269.592105263158 50.51861789924058Q6253.0 81.08260396406409 6253.0 118Q6253.0 154.01420454545456 6269.75 184.75710227272728Q6286.5 215.5 6315.300156739811 233.5Q6344.100313479624 251.5 6378.909090909091 251.5Q6414.981404958678 251.5 6443.990702479339 233.25Q6473.0 215 6489.75 184.62642045454544Q6506.5 154.2528409090909 6506.5 118.17622950819673Q6506.5 81.12563675094934 6489.631147540984 50.446896587765174Q6472.762295081967 19.768156424581004 6444.164510228966 1.3840782122905022Q6415.566725375966 -17.0 6378.741819961297 -17.0Z"/>
12
+ </g>
13
+ </svg>
package/components.css ADDED
@@ -0,0 +1,394 @@
1
+ /* @sondalab/ui-kit — components.css
2
+ Hand-authored (NOT generated). CSS-only component layer on top of tokens.css.
3
+ Framework-agnostic: works in Theia widgets, React apps, and plain HTML.
4
+
5
+ ── Colour contract: role-vars (--slc-*) ─────────────────────────────────────
6
+ Components never read theme tokens (--sl-color-… / --sl-accent-…) directly,
7
+ because those resolve ONLY under [data-sl-theme] (Tier A, e.g. spexr). In
8
+ value-pinned products (Tier B: daos, introspect) they are absent.
9
+
10
+ Instead every component reads a small set of role-vars declared below. Each
11
+ defaults through a fallback chain: --sl-* token first (so Tier A products get
12
+ the live theme with ZERO wiring), then a hard brand literal (so a bare import
13
+ still renders). Tier B products MAP the role-vars ONCE to their own colour
14
+ layer — see the README recipe. That is the whole integration surface.
15
+
16
+ ── Inversion-band pitfall ───────────────────────────────────────────────────
17
+ --slc-border defaults to an alpha-over-canvas value. Inside an inversion band
18
+ (a block whose background is the strongest neutral, e.g. .invert), that alpha
19
+ sits on the wrong ground and the border vanishes. Fix at the band, not here:
20
+ .invert { --slc-border: color-mix(in srgb, currentColor 22%, transparent); }
21
+ Keeps value-equality, no new token. Any bordered component (card, table,
22
+ field, callout) inherits the fix automatically. */
23
+
24
+ :root {
25
+ /* accent */
26
+ --slc-accent: var(--sl-accent-default, #B56A0C);
27
+ --slc-accent-hover: var(--sl-accent-hover, #A05F0A);
28
+ --slc-accent-active: var(--sl-accent-active, #8A5109);
29
+ --slc-accent-subtle: var(--sl-accent-subtle, rgba(197,122,22,0.12));
30
+ --slc-on-accent: var(--sl-text-on-accent, #FFFFFF);
31
+ /* surfaces + text */
32
+ --slc-surface: var(--sl-bg-surface, #F6F1E6);
33
+ --slc-raised: var(--sl-bg-surface-raised, #FFFFFF);
34
+ --slc-overlay: var(--sl-bg-overlay, rgba(21,33,31,0.4));
35
+ --slc-text: var(--sl-text-primary, #15211F);
36
+ --slc-text-secondary:var(--sl-text-secondary, #475754);
37
+ --slc-text-muted: var(--sl-text-muted, #6E7B78);
38
+ /* lines */
39
+ --slc-border: var(--sl-border-default, rgba(21,33,31,0.16));
40
+ --slc-border-subtle: var(--sl-border-subtle, rgba(21,33,31,0.09));
41
+ --slc-border-strong: var(--sl-border-strong, rgba(21,33,31,0.28));
42
+ --slc-focus: var(--sl-focus-ring, var(--slc-accent));
43
+ /* status */
44
+ --slc-success: var(--sl-status-success, #16a34a);
45
+ --slc-warning: var(--sl-status-warning, #d97706);
46
+ --slc-danger: var(--sl-status-danger, #dc2626);
47
+ --slc-info: var(--sl-status-info, #0284c7);
48
+ }
49
+
50
+ /* Shared focus ring for keyboard nav — every interactive component uses it. */
51
+ .sl-btn:focus-visible,
52
+ .sl-link:focus-visible,
53
+ .sl-field__input:focus-visible,
54
+ .sl-tabs__tab:focus-visible,
55
+ [data-sl-tooltip]:focus-visible {
56
+ outline: var(--sl-focus-ring-width, 2px) solid var(--slc-focus);
57
+ outline-offset: var(--sl-focus-ring-offset, 2px);
58
+ border-radius: var(--sl-radius-sm, 4px);
59
+ }
60
+
61
+ /* ══ PRIMITIVES ══════════════════════════════════════════════════════════════ */
62
+
63
+ /* Eyebrow — mono uppercase micro-label above a heading. Strongest family signal. */
64
+ .sl-eyebrow {
65
+ font-family: var(--sl-font-mono, ui-monospace, monospace);
66
+ font-size: var(--sl-text-xs, 0.75rem);
67
+ font-weight: 500;
68
+ letter-spacing: 0.22em;
69
+ text-transform: uppercase;
70
+ color: var(--slc-text-muted);
71
+ }
72
+
73
+ /* Tag — accent-tinted pill with a dot glyph. Category / tier marker. */
74
+ .sl-tag {
75
+ display: inline-flex;
76
+ align-items: center;
77
+ gap: var(--sl-space-2, 0.5rem);
78
+ font-family: var(--sl-font-mono, ui-monospace, monospace);
79
+ font-size: var(--sl-text-xs, 0.75rem);
80
+ font-weight: 500;
81
+ letter-spacing: 0.16em;
82
+ text-transform: uppercase;
83
+ line-height: 1;
84
+ color: var(--slc-accent);
85
+ background: var(--slc-accent-subtle);
86
+ border: 1px solid var(--slc-accent-subtle);
87
+ border-radius: var(--sl-radius-pill, 9999px);
88
+ padding: var(--sl-space-1, 0.25rem) var(--sl-space-3, 0.75rem);
89
+ }
90
+ .sl-tag::before {
91
+ content: "";
92
+ width: 6px; height: 6px;
93
+ border-radius: 50%;
94
+ background: var(--slc-accent);
95
+ flex: none;
96
+ }
97
+ .sl-tag--plain { color: var(--slc-text-muted); background: transparent; border-color: var(--slc-border); }
98
+ .sl-tag--plain::before { background: var(--slc-text-muted); }
99
+
100
+ /* Button — primary (filled accent), ghost (bordered), and a small size. */
101
+ .sl-btn {
102
+ display: inline-flex;
103
+ align-items: center;
104
+ justify-content: center;
105
+ gap: var(--sl-space-2, 0.5rem);
106
+ font-family: var(--sl-font-sans, system-ui, sans-serif);
107
+ font-size: var(--sl-text-sm, 0.875rem);
108
+ font-weight: 600;
109
+ line-height: 1;
110
+ padding: var(--sl-space-3, 0.75rem) var(--sl-space-5, 1.5rem);
111
+ border-radius: var(--sl-radius-md, 6px);
112
+ border: 1px solid transparent;
113
+ background: transparent;
114
+ color: var(--slc-text);
115
+ cursor: pointer;
116
+ transition: background var(--sl-motion-fast, 120ms) var(--sl-motion-ease, ease),
117
+ border-color var(--sl-motion-fast, 120ms) var(--sl-motion-ease, ease),
118
+ color var(--sl-motion-fast, 120ms) var(--sl-motion-ease, ease);
119
+ }
120
+ .sl-btn:disabled { opacity: 0.5; cursor: not-allowed; }
121
+ .sl-btn--primary { background: var(--slc-accent); color: var(--slc-on-accent); }
122
+ .sl-btn--primary:hover:not(:disabled) { background: var(--slc-accent-hover); }
123
+ .sl-btn--primary:active:not(:disabled) { background: var(--slc-accent-active); }
124
+ .sl-btn--ghost { border-color: var(--slc-border); color: var(--slc-text); }
125
+ .sl-btn--ghost:hover:not(:disabled) { border-color: var(--slc-accent); color: var(--slc-accent); }
126
+ .sl-btn--sm { font-size: var(--sl-text-xs, 0.75rem); padding: var(--sl-space-2, 0.5rem) var(--sl-space-3, 0.75rem); }
127
+
128
+ /* Card — surface panel. Compose with __title / __body. */
129
+ .sl-card {
130
+ background: var(--slc-surface);
131
+ border: 1px solid var(--slc-border);
132
+ border-radius: var(--sl-radius-lg, 10px);
133
+ padding: var(--sl-space-5, 1.5rem);
134
+ }
135
+ .sl-card__title {
136
+ font-family: var(--sl-font-display, Georgia, serif);
137
+ font-size: var(--sl-text-lg, 1.125rem);
138
+ font-weight: 600;
139
+ letter-spacing: -0.01em;
140
+ color: var(--slc-text);
141
+ margin: 0 0 var(--sl-space-2, 0.5rem);
142
+ }
143
+ .sl-card__body {
144
+ font-family: var(--sl-font-sans, system-ui, sans-serif);
145
+ font-size: var(--sl-text-sm, 0.875rem);
146
+ line-height: var(--sl-line-normal, 1.5);
147
+ color: var(--slc-text-secondary);
148
+ margin: 0;
149
+ }
150
+
151
+ /* Badge — status pill. Semantic colour is independent of the accent hue. */
152
+ .sl-badge {
153
+ display: inline-flex;
154
+ align-items: center;
155
+ gap: var(--sl-space-2, 0.5rem);
156
+ font-family: var(--sl-font-mono, ui-monospace, monospace);
157
+ font-size: var(--sl-text-xs, 0.75rem);
158
+ font-weight: 500;
159
+ letter-spacing: 0.08em;
160
+ text-transform: uppercase;
161
+ line-height: 1;
162
+ color: var(--slc-text-secondary);
163
+ border: 1px solid var(--slc-border);
164
+ border-radius: var(--sl-radius-pill, 9999px);
165
+ padding: var(--sl-space-1, 0.25rem) var(--sl-space-3, 0.75rem);
166
+ }
167
+ .sl-badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
168
+ .sl-badge--success { color: var(--slc-success); border-color: color-mix(in srgb, var(--slc-success) 40%, transparent); }
169
+ .sl-badge--warning { color: var(--slc-warning); border-color: color-mix(in srgb, var(--slc-warning) 40%, transparent); }
170
+ .sl-badge--danger { color: var(--slc-danger); border-color: color-mix(in srgb, var(--slc-danger) 40%, transparent); }
171
+ .sl-badge--info { color: var(--slc-info); border-color: color-mix(in srgb, var(--slc-info) 40%, transparent); }
172
+
173
+ /* Field — label + input/textarea/select. Compose __label with __input. */
174
+ .sl-field { display: flex; flex-direction: column; gap: var(--sl-space-2, 0.5rem); }
175
+ .sl-field__label {
176
+ font-family: var(--sl-font-mono, ui-monospace, monospace);
177
+ font-size: var(--sl-text-xs, 0.75rem);
178
+ font-weight: 500;
179
+ letter-spacing: 0.12em;
180
+ text-transform: uppercase;
181
+ color: var(--slc-text-muted);
182
+ }
183
+ .sl-field__input {
184
+ font-family: var(--sl-font-sans, system-ui, sans-serif);
185
+ font-size: var(--sl-text-sm, 0.875rem);
186
+ color: var(--slc-text);
187
+ background: var(--slc-raised);
188
+ border: 1px solid var(--slc-border);
189
+ border-radius: var(--sl-radius-md, 6px);
190
+ padding: var(--sl-space-3, 0.75rem);
191
+ transition: border-color var(--sl-motion-fast, 120ms) var(--sl-motion-ease, ease);
192
+ }
193
+ .sl-field__input::placeholder { color: var(--slc-text-muted); }
194
+ .sl-field__input:hover:not(:disabled) { border-color: var(--slc-border-strong); }
195
+ .sl-field__input:disabled { opacity: 0.5; cursor: not-allowed; }
196
+ textarea.sl-field__input { resize: vertical; min-height: 4.5rem; line-height: var(--sl-line-normal, 1.5); }
197
+
198
+ /* Kbd — keyboard key. */
199
+ .sl-kbd {
200
+ display: inline-flex;
201
+ align-items: center;
202
+ font-family: var(--sl-font-mono, ui-monospace, monospace);
203
+ font-size: 0.8125em;
204
+ line-height: 1;
205
+ color: var(--slc-text-secondary);
206
+ background: var(--slc-surface);
207
+ border: 1px solid var(--slc-border);
208
+ border-bottom-width: 2px;
209
+ border-radius: var(--sl-radius-sm, 4px);
210
+ padding: 0.2em 0.45em;
211
+ }
212
+
213
+ /* Inline code. */
214
+ .sl-code {
215
+ font-family: var(--sl-font-mono, ui-monospace, monospace);
216
+ font-size: 0.875em;
217
+ color: var(--slc-accent);
218
+ background: var(--slc-accent-subtle);
219
+ border-radius: var(--sl-radius-sm, 4px);
220
+ padding: 0.12em 0.36em;
221
+ }
222
+
223
+ /* Link — underlined, accent on hover. */
224
+ .sl-link {
225
+ color: var(--slc-text);
226
+ text-decoration: underline;
227
+ text-decoration-color: var(--slc-border-strong);
228
+ text-underline-offset: 0.18em;
229
+ transition: color var(--sl-motion-fast, 120ms) var(--sl-motion-ease, ease),
230
+ text-decoration-color var(--sl-motion-fast, 120ms) var(--sl-motion-ease, ease);
231
+ }
232
+ .sl-link:hover { color: var(--slc-accent); text-decoration-color: var(--slc-accent); }
233
+
234
+ /* Rule — hairline divider. --labeled centres a caption over the line. */
235
+ .sl-rule { border: none; border-top: 1px solid var(--slc-border); margin: var(--sl-space-6, 2rem) 0; }
236
+ .sl-rule--labeled {
237
+ display: flex;
238
+ align-items: center;
239
+ gap: var(--sl-space-4, 1rem);
240
+ border: none;
241
+ margin: var(--sl-space-6, 2rem) 0;
242
+ font-family: var(--sl-font-mono, ui-monospace, monospace);
243
+ font-size: var(--sl-text-xs, 0.75rem);
244
+ letter-spacing: 0.16em;
245
+ text-transform: uppercase;
246
+ color: var(--slc-text-muted);
247
+ }
248
+ .sl-rule--labeled::before,
249
+ .sl-rule--labeled::after { content: ""; flex: 1; border-top: 1px solid var(--slc-border); }
250
+
251
+ /* ══ COMPLEX (composed shells — no behaviour JS) ═════════════════════════════ */
252
+
253
+ /* Callout — banner / admonition. The accent is a short "measure tick" on the
254
+ top edge (a ruler mark, not the ubiquitous left stripe), aligned with the
255
+ title. Variants recolour the tick; the panel is plain surface. */
256
+ .sl-callout {
257
+ position: relative;
258
+ background: var(--slc-surface);
259
+ border: 1px solid var(--slc-border);
260
+ border-radius: var(--sl-radius-md, 6px);
261
+ padding: var(--sl-space-5, 1.5rem) var(--sl-space-5, 1.5rem) var(--sl-space-4, 1rem);
262
+ }
263
+ .sl-callout::before {
264
+ content: "";
265
+ position: absolute;
266
+ top: -1px; /* sit on the top edge, over the border */
267
+ left: var(--sl-space-5, 1.5rem); /* align with the title / padding */
268
+ width: 2.75rem;
269
+ height: 3px;
270
+ background: var(--slc-accent);
271
+ border-radius: 0 0 var(--sl-radius-sm, 4px) var(--sl-radius-sm, 4px);
272
+ }
273
+ .sl-callout__title {
274
+ font-family: var(--sl-font-mono, ui-monospace, monospace);
275
+ font-size: var(--sl-text-xs, 0.75rem);
276
+ font-weight: 600;
277
+ letter-spacing: 0.12em;
278
+ text-transform: uppercase;
279
+ color: var(--slc-text);
280
+ margin: 0 0 var(--sl-space-1, 0.25rem);
281
+ }
282
+ .sl-callout__body {
283
+ font-family: var(--sl-font-sans, system-ui, sans-serif);
284
+ font-size: var(--sl-text-sm, 0.875rem);
285
+ line-height: var(--sl-line-normal, 1.5);
286
+ color: var(--slc-text-secondary);
287
+ margin: 0;
288
+ }
289
+ .sl-callout--success::before { background: var(--slc-success); }
290
+ .sl-callout--warning::before { background: var(--slc-warning); }
291
+ .sl-callout--danger::before { background: var(--slc-danger); }
292
+ .sl-callout--info::before { background: var(--slc-info); }
293
+
294
+ /* Table — shell. Wrap in a scroll container so wide tables never scroll the page:
295
+ <div style="overflow-x:auto"><table class="sl-table">…</table></div> */
296
+ .sl-table {
297
+ width: 100%;
298
+ border-collapse: collapse;
299
+ font-family: var(--sl-font-sans, system-ui, sans-serif);
300
+ font-size: var(--sl-text-sm, 0.875rem);
301
+ color: var(--slc-text);
302
+ }
303
+ .sl-table thead th {
304
+ font-family: var(--sl-font-mono, ui-monospace, monospace);
305
+ font-size: var(--sl-text-xs, 0.75rem);
306
+ font-weight: 500;
307
+ letter-spacing: 0.12em;
308
+ text-transform: uppercase;
309
+ text-align: left;
310
+ color: var(--slc-text-muted);
311
+ padding: var(--sl-space-3, 0.75rem) var(--sl-space-4, 1rem);
312
+ border-bottom: 1px solid var(--slc-border);
313
+ }
314
+ .sl-table tbody td {
315
+ padding: var(--sl-space-3, 0.75rem) var(--sl-space-4, 1rem);
316
+ border-bottom: 1px solid var(--slc-border-subtle);
317
+ }
318
+ .sl-table tbody tr:last-child td { border-bottom: none; }
319
+ .sl-table--numeric td, .sl-table--numeric th { font-variant-numeric: tabular-nums; }
320
+
321
+ /* Dialog — visual shell for the native <dialog> element (consumer wires open/close).
322
+ <dialog class="sl-dialog">…</dialog>; dialog.showModal() / .close() drive it. */
323
+ .sl-dialog {
324
+ background: var(--slc-raised);
325
+ color: var(--slc-text);
326
+ border: 1px solid var(--slc-border);
327
+ border-radius: var(--sl-radius-lg, 10px);
328
+ box-shadow: var(--sl-shadow-lg, 0 12px 32px rgba(0,0,0,0.16));
329
+ padding: var(--sl-space-6, 2rem);
330
+ max-width: 32rem;
331
+ width: calc(100% - var(--sl-space-8, 3rem));
332
+ }
333
+ .sl-dialog::backdrop { background: var(--slc-overlay); }
334
+ .sl-dialog__title {
335
+ font-family: var(--sl-font-display, Georgia, serif);
336
+ font-size: var(--sl-text-xl, 1.5rem);
337
+ font-weight: 600;
338
+ letter-spacing: -0.01em;
339
+ margin: 0 0 var(--sl-space-3, 0.75rem);
340
+ }
341
+ .sl-dialog__body { font-family: var(--sl-font-sans, system-ui, sans-serif); font-size: var(--sl-text-sm, 0.875rem); line-height: var(--sl-line-normal, 1.5); color: var(--slc-text-secondary); margin: 0 0 var(--sl-space-5, 1.5rem); }
342
+ .sl-dialog__actions { display: flex; justify-content: flex-end; gap: var(--sl-space-3, 0.75rem); }
343
+
344
+ /* Tabs — visual only. Consumer supplies ARIA + panel switching:
345
+ <div class="sl-tabs__list" role="tablist">
346
+ <button class="sl-tabs__tab" role="tab" aria-selected="true">…</button> …
347
+ </div> */
348
+ .sl-tabs__list {
349
+ display: flex;
350
+ gap: var(--sl-space-1, 0.25rem);
351
+ border-bottom: 1px solid var(--slc-border);
352
+ }
353
+ .sl-tabs__tab {
354
+ font-family: var(--sl-font-sans, system-ui, sans-serif);
355
+ font-size: var(--sl-text-sm, 0.875rem);
356
+ font-weight: 500;
357
+ color: var(--slc-text-muted);
358
+ background: transparent;
359
+ border: none;
360
+ border-bottom: 2px solid transparent;
361
+ margin-bottom: -1px;
362
+ padding: var(--sl-space-3, 0.75rem) var(--sl-space-4, 1rem);
363
+ cursor: pointer;
364
+ transition: color var(--sl-motion-fast, 120ms) var(--sl-motion-ease, ease),
365
+ border-color var(--sl-motion-fast, 120ms) var(--sl-motion-ease, ease);
366
+ }
367
+ .sl-tabs__tab:hover { color: var(--slc-text); }
368
+ .sl-tabs__tab[aria-selected="true"] { color: var(--slc-accent); border-bottom-color: var(--slc-accent); }
369
+
370
+ /* Tooltip — CSS-only. Put text in data-sl-tooltip; give the host tabindex="0"
371
+ for keyboard reveal. <span class="sl-tooltip" data-sl-tooltip="…" tabindex="0">…</span> */
372
+ .sl-tooltip { position: relative; }
373
+ .sl-tooltip::after {
374
+ content: attr(data-sl-tooltip);
375
+ position: absolute;
376
+ bottom: calc(100% + var(--sl-space-2, 0.5rem));
377
+ left: 50%;
378
+ transform: translateX(-50%);
379
+ white-space: nowrap;
380
+ font-family: var(--sl-font-sans, system-ui, sans-serif);
381
+ font-size: var(--sl-text-xs, 0.75rem);
382
+ /* Inverted chip: text tracks the surface axis so it stays opposite its own
383
+ --slc-text background in every theme (never the unrelated on-accent role). */
384
+ color: var(--slc-raised);
385
+ background: var(--slc-text);
386
+ border-radius: var(--sl-radius-sm, 4px);
387
+ padding: var(--sl-space-1, 0.25rem) var(--sl-space-3, 0.75rem);
388
+ opacity: 0;
389
+ pointer-events: none;
390
+ transition: opacity var(--sl-motion-fast, 120ms) var(--sl-motion-ease, ease);
391
+ z-index: var(--sl-z-overlay, 50);
392
+ }
393
+ .sl-tooltip:hover::after,
394
+ .sl-tooltip:focus-visible::after { opacity: 1; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sondalab/ui-kit",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Sondalab design tokens as CSS custom properties: shared grammar + per-product accent, with light / dark / high-contrast themes.",
5
5
  "license": "MIT",
6
6
  "author": "marcellobarile",
@@ -8,15 +8,26 @@
8
8
  "type": "module",
9
9
  "exports": {
10
10
  "./tokens.css": "./tokens.css",
11
+ "./components.css": "./components.css",
11
12
  "./themes/light.css": "./themes/light.css",
12
13
  "./themes/dark.css": "./themes/dark.css",
13
- "./themes/high-contrast.css": "./themes/high-contrast.css"
14
+ "./themes/high-contrast.css": "./themes/high-contrast.css",
15
+ "./assets/wordmark.svg": "./assets/sondalab-wordmark.svg",
16
+ "./assets/lockup.svg": "./assets/sondalab-lockup.svg",
17
+ "./assets/favicon.svg": "./assets/favicon.svg",
18
+ "./assets/app-icon.svg": "./assets/app-icon.svg"
14
19
  },
15
20
  "files": [
16
21
  "tokens.css",
22
+ "components.css",
17
23
  "themes/light.css",
18
24
  "themes/dark.css",
19
25
  "themes/high-contrast.css",
26
+ "assets/sondalab-wordmark.svg",
27
+ "assets/sondalab-lockup.svg",
28
+ "assets/favicon.svg",
29
+ "assets/app-icon.svg",
30
+ "assets/README.md",
20
31
  "README.md"
21
32
  ]
22
33
  }