@kolkrabbi/kol-theme 0.36.0 → 0.38.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
@@ -21,6 +21,17 @@ Cascade order is load-bearing — `kol-theme` must come after Tailwind so its co
21
21
 
22
22
  All KOL rule CSS lives in the `components` cascade layer, so your Tailwind utility classes always win over KOL chrome (`<Input className="hidden sm:block">` behaves as written). Your own unlayered CSS wins over everything KOL ships.
23
23
 
24
+ ## The `@source` contract — required for every KOL package that ships JSX
25
+
26
+ Tailwind v4 **does not scan `node_modules`**, so layout utilities emitted inside KOL components never generate unless you point the scanner at each package's source. Without these lines components **silently degrade** — no error, no warning, just missing layout/motion (a frozen ThemeToggle roll, a collapsed AppShell grid). Paste one line per installed KOL package, next to the imports above:
27
+
28
+ ```css
29
+ @source "../node_modules/@kolkrabbi/kol-component/src";
30
+ @source "../node_modules/@kolkrabbi/kol-framework/src";
31
+ ```
32
+
33
+ (Adjust the relative path to your CSS file's location. Component-load-bearing *chrome* lives in this package's CSS and needs no `@source` — the contract covers the remaining per-render utilities.)
34
+
24
35
  ## Fonts
25
36
 
26
37
  The typography CSS references the brand fonts at absolute paths (`/fonts/Right-Grotesk/…`, `/fonts/jetbrains-mono/…`). **The package does not ship the font files** — your app must serve them from `/fonts/` (e.g. drop them in your `public/` dir). The showcase in this repo does exactly that. Without them, type falls back to system fonts.
@@ -1012,3 +1012,26 @@ a.kol-icon-frame {
1012
1012
  border-radius: 0;
1013
1013
  padding: 0;
1014
1014
  }
1015
+
1016
+ /* The ROLL mechanics — .kol-roll (ComponentTailwindSourceTrap, 2026-08-12).
1017
+ * These were Tailwind utilities emitted in ThemeToggle's JSX (overflow-hidden,
1018
+ * transition-transform, duration-500, ease-in-out) — and Tailwind never scans
1019
+ * node_modules, so any consumer without the @source lines got a SILENTLY
1020
+ * static glyph: visible, clickable, no travel, no coin-roll, no error.
1021
+ * A component's own moving parts live HERE, in the CSS it ships — the
1022
+ * consumer's scanner owes it nothing. Widths/transforms stay inline in JSX
1023
+ * (they are per-render geometry, not chrome). */
1024
+ .kol-roll {
1025
+ position: relative;
1026
+ display: inline-block;
1027
+ overflow: hidden;
1028
+ }
1029
+ .kol-roll-strip {
1030
+ display: flex;
1031
+ transition: transform 500ms ease-in-out;
1032
+ }
1033
+ .kol-roll-slot {
1034
+ display: inline-flex;
1035
+ line-height: 0;
1036
+ transition: transform 500ms ease-in-out;
1037
+ }
@@ -472,11 +472,20 @@
472
472
  border: 1px solid var(--kol-fg-04);
473
473
  border-radius: var(--kol-radius-sm);
474
474
  overflow: hidden;
475
- }
476
-
477
- /* Sizes mirror .kol-btn-{sm,md,lg} exactly: cell padding per size (below) +
478
- * mono type (12/14/16) applied on the cell in JSX. Height is padding-driven,
479
- * so a strip matches a Button of the same size. md is the base. */
475
+ /* The button-height LAW (2026-08-12): the strip's OUTER height is PINNED
476
+ * to the .kol-btn ladder — 26 / 32 / 40 — regardless of what a cell holds
477
+ * (icon or text) and regardless of variant (the filled variant drops the
478
+ * group border, so padding-driven height ran 2px short the bug that
479
+ * forced the pin). Same principle as .kol-btn-icon's pinned square:
480
+ * the box never moves. */
481
+ box-sizing: border-box;
482
+ height: 32px; /* md — .kol-btn-md */
483
+ }
484
+
485
+ /* Sizes mirror .kol-btn-{sm,md,lg} exactly: pinned height above + cell
486
+ * padding per size (below) + mono type (12/14/16) applied in JSX. */
487
+ .kol-seg--sm { height: 26px; }
488
+ .kol-seg--lg { height: 40px; }
480
489
  .kol-seg--sm .kol-seg-cell { padding: 4px 12px; }
481
490
  .kol-seg--lg .kol-seg-cell { padding: 8px 20px; }
482
491
 
@@ -490,7 +499,11 @@
490
499
  border: none;
491
500
  cursor: pointer;
492
501
  white-space: nowrap;
493
- color: var(--kol-fg-meta);
502
+ /* OPAQUE rest paint (estate opaque-icons law, 2026-08-12): cells host
503
+ * icon labels, and alpha ink (--kol-fg-meta) compounds where strokes
504
+ * overlap — oq-48 reads identical on the resting surface but stays
505
+ * opaque. Hover/active use fg-emphasis, which is full ink (no alpha). */
506
+ color: var(--kol-oq-48);
494
507
  transition: color var(--kol-transition-base),
495
508
  background-color var(--kol-transition-base);
496
509
  }
@@ -509,10 +522,12 @@
509
522
  outline-offset: -2px;
510
523
  }
511
524
 
512
- /* Filled variant — the segmented state law (2026-08-12): every cell is a
513
- * FILLED TILE (input surface tone) with 1px transparent gaps never an
514
- * outline shell around the group; the outlined treatment marks ONLY the
515
- * selected cell (inset ring). Group radius clips the outer tile corners. */
525
+ /* Filled variant — the CORRECTED segmented state law (2026-08-12, second
526
+ * ruling SegmentedFilledStateFix): the SELECTED cell is the DARK FILLED
527
+ * tile (input surface tone) + bright glyph — the dark state IS the selection
528
+ * marker. Unselected cells are QUIET: transparent, dim, hover brightens.
529
+ * NO outline ring, ever. (The 0.36.0 first reading — always-tiled cells +
530
+ * inset ring on selected — was the inversion this block repeals.) */
516
531
  .kol-seg--filled {
517
532
  border: none;
518
533
  gap: 1px;
@@ -520,14 +535,22 @@
520
535
  }
521
536
 
522
537
  .kol-seg--filled .kol-seg-cell {
523
- background: var(--kol-surface-secondary);
538
+ background: transparent;
539
+ /* the dark tile rounds itself (SegBar reference geometry) */
540
+ border-radius: var(--kol-radius-sm);
524
541
  }
525
542
 
526
543
  .kol-seg--filled .kol-seg-cell + .kol-seg-cell { border-left: none; }
527
544
 
528
545
  .kol-seg--filled .kol-seg-cell.is-active {
529
546
  background: var(--kol-surface-secondary);
530
- box-shadow: inset 0 0 0 1px var(--kol-fg-24);
547
+ color: var(--kol-fg-emphasis);
548
+ }
549
+
550
+ /* Tonal variant (2026-08-12, user ask): same quiet-unselected law, but the
551
+ * clicked cell marks itself on the tertiary tone. */
552
+ .kol-seg--tonal .kol-seg-cell.is-active {
553
+ background: var(--kol-surface-tertiary);
531
554
  color: var(--kol-fg-emphasis);
532
555
  }
533
556
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kolkrabbi/kol-theme",
3
- "version": "0.36.0",
3
+ "version": "0.38.0",
4
4
  "description": "KOL (Kolkrabbi) design-system tokens + base CSS — brand-neutral. The canonical token/cascade layer every other KOL package and consumer builds on.",
5
5
  "license": "MIT",
6
6
  "type": "module",