@fiestaboard/ui 5.8.0 → 5.9.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
@@ -32,10 +32,10 @@ FiestaUI ships **no compiled utility CSS**. The consuming app runs Tailwind v4 a
32
32
  @source "../node_modules/@fiestaboard/ui/dist";
33
33
  ```
34
34
 
35
- - `theme.css` carries the design tokens (`@theme inline`, `:root` / `.dark` custom properties), the base layer, the component animation keyframes, and the `dark` custom variant.
35
+ - `theme.css` carries the design tokens (`@theme inline`, `:root` / `.dark, [data-theme="dark"]` custom properties), the base layer, the component animation keyframes, and the `dark` custom variant.
36
36
  - `fonts.css` is the **opt-in** font registration (`@fontsource-variable/archivo` + `@fontsource-variable/spline-sans-mono` `@font-face` rules, ~70 KB fetched for a Latin-only page). Import it alongside `theme.css` unless your app supplies the faces itself — e.g. via `next/font`, a CDN, or a self-hosted subset. If you self-host, skip `fonts.css` and register faces named `"Archivo Variable"` / `"Spline Sans Mono Variable"` (the names `theme.css`'s `--font-sans-stack` / `--font-mono-stack` tokens reference); without either, the tokens degrade gracefully to the system font stack.
37
37
  - The `@source` line is **mandatory** — Tailwind v4 does not scan `node_modules` by default, and without it component styles silently vanish. Adjust the relative path to wherever your CSS file lives.
38
- - Dark mode is class-based: toggle the `dark` class on `<html>`. FiestaUI only defines the variant; your app owns the toggle.
38
+ - Dark mode responds to **either** signal, and they are equivalent: the `dark` **class** or a `data-theme="dark"` **attribute**. Put whichever your host already toggles on `<html>` — or on any ancestor, to theme just that subtree. FiestaUI only defines the variant; your app owns the toggle. Hosts that stamp the attribute natively (Docusaurus, Astro, Nuxt Color Mode) therefore need no adapter. The pair is left unqualified, at specificity 0-1-0, so a pipeline that appends its own `:root` blocks after `theme.css` (Docusaurus's wide-gamut P3 pass does) still has to raise specificity on its side.
39
39
 
40
40
  ### Typeface
41
41
 
package/dist/theme.css CHANGED
@@ -9,14 +9,55 @@
9
9
  * @import "@fiestaboard/ui/theme.css"; skip fonts.css if you self-host
10
10
  * @source "../node_modules/@fiestaboard/ui/dist";
11
11
  *
12
- * Dark mode is class-based: toggle the `dark` class on <html>.
12
+ * Dark mode is signalled two ways, and they are equivalent: the `dark` CLASS
13
+ * or a `data-theme="dark"` ATTRIBUTE, on <html> or on any ancestor of the
14
+ * subtree you want themed. Toggle whichever your host already toggles.
15
+ *
13
16
  * Values are copied verbatim from FiestaBoard app/globals.css — visual
14
17
  * parity with the app is the contract; do not reformat or "improve"
15
18
  * token values here without a parity check on the consumer side.
16
19
  */
17
20
  @import "tw-animate-css";
18
21
 
19
- @custom-variant dark (&:is(.dark *));
22
+ /* ============================================================
23
+ * DARK MODE HAS TWO SPELLINGS (#228 item 6).
24
+ *
25
+ * `.dark` is what a Tailwind/shadcn host stamps; `[data-theme="dark"]` is
26
+ * what Docusaurus, Astro, Nuxt Color Mode and several static-site themes
27
+ * stamp natively. Matching both means a host that already has a theme
28
+ * switcher needs no adapter — no class to mirror, no JS to sync.
29
+ *
30
+ * fiestaboard.github.io is the consumer that forced this. It could not stamp
31
+ * `.dark` (Docusaurus owns the attribute and re-stamps it pre-paint), so its
32
+ * `scripts/build-fiestaui-css.mjs` regex-rewrote every compiled `.dark`
33
+ * selector in this file into the attribute form after Tailwind ran — a
34
+ * rewrite that has to track how Tailwind chooses to compile us. 4.0.0 already
35
+ * broke it once: `color-mix()` token values made Tailwind hoist part of the
36
+ * block below into an `@supports` fragment, and a rewrite that assumed one
37
+ * block left `--brand-hover` silently stuck on its fallback.
38
+ *
39
+ * THE PAIRING IS ALL-OR-NOTHING. A half-applied change is worse than none: a
40
+ * consumer's rewrite would then be transforming one half of this file and
41
+ * leaving the other half alone, which reads as working right up until the
42
+ * unpaired half is the one that matters. `dark-selector-pairing.test.mjs`
43
+ * asserts that every dark-scoped selector here carries both spellings.
44
+ *
45
+ * Two things this deliberately does NOT do:
46
+ *
47
+ * - It does not qualify with `html`. `.dark`/`[data-theme="dark"]` are
48
+ * 0-1-0, the same as `:root`, so source order decides — which is correct
49
+ * for a scoped subtree (a dark card on a light page) and is the reason
50
+ * the pair is written unqualified. A consumer whose pipeline APPENDS
51
+ * `:root` blocks after this file (Docusaurus's wide-gamut P3 pass does
52
+ * exactly that) still has to raise specificity itself. Matching the
53
+ * attribute shrinks that consumer's rewrite; it does not delete it.
54
+ * - It does not make the selector configurable. CSS has no parameter to
55
+ * configure, so "configurable" would mean a build step and a config file
56
+ * for what is otherwise a `cp`. Matching both spellings covers the hosts
57
+ * that exist at zero cost to every consumer; a third spelling can join
58
+ * this list the day something needs it.
59
+ * ============================================================ */
60
+ @custom-variant dark (&:is(.dark *, [data-theme="dark"] *));
20
61
 
21
62
  @theme inline {
22
63
  --color-background: var(--background);
@@ -465,10 +506,10 @@
465
506
  * pins the "New" badge to hexes with `!important`, which is a hex fork of
466
507
  * a token pair and a real maintenance defect — a fork stops tracking a
467
508
  * retune here — but it is theme-AWARE (`.newBadge` plus a
468
- * `[data-theme="dark"] .newBadge`, and their build widens every compiled
469
- * `.dark` selector to that attribute), so the light pigment never lands on
470
- * a dark fill. Both halves clear AA on their own fills: 6.49:1 light,
471
- * 7.52:1 dark. It is redundant, not broken. Dropping it downstream is a
509
+ * `[data-theme="dark"] .newBadge`, an attribute this file now matches
510
+ * directly see the @custom-variant note at the top), so the light pigment
511
+ * never lands on a dark fill. Both halves clear AA on their own fills:
512
+ * 6.49:1 light, 7.52:1 dark. It is redundant, not broken. Dropping it downstream is a
472
513
  * cleanup, not a fix, and it does not close #231.
473
514
  *
474
515
  * Opaque fills (mixing the tint into --background instead of compositing
@@ -817,7 +858,9 @@
817
858
  --z-confetti: 9999;
818
859
  }
819
860
 
820
- .dark {
861
+ /* Both dark spellings — see the @custom-variant note at the top (#228). */
862
+ .dark,
863
+ [data-theme="dark"] {
821
864
  color-scheme: dark; /* see the note in :root (#160) */
822
865
  /* Hue lock applies here too: same six hues, same hue angles as :root.
823
866
  Only lightness moves. Surfaces carry the same warm cast at hue 73, and
@@ -1337,7 +1380,8 @@ html[data-board-switch="backward"]::view-transition-new(board-page) {
1337
1380
  --accent-foreground: var(--sidebar-foreground);
1338
1381
  --border: color-mix(in oklch, var(--sidebar-foreground) 16%, transparent);
1339
1382
  }
1340
- .dark .sidebar-gradient-horizontal {
1383
+ .dark .sidebar-gradient-horizontal,
1384
+ [data-theme="dark"] .sidebar-gradient-horizontal {
1341
1385
  color: oklch(1 0 0);
1342
1386
  --foreground: oklch(1 0 0);
1343
1387
  --sidebar-accent: oklch(1 0 0 / 24%);
@@ -1496,7 +1540,8 @@ html[data-board-switch="backward"]::view-transition-new(board-page) {
1496
1540
  The hover keeps the same recipe as its resting form, lifted 14% -> 24%
1497
1541
  (4.54:1 dark rail, 5.05:1 dark page, 1.29:1 light page). */
1498
1542
  @media (prefers-contrast: more) {
1499
- .dark {
1543
+ .dark,
1544
+ [data-theme="dark"] {
1500
1545
  --nav-active: oklch(0.86 0.115 73);
1501
1546
  }
1502
1547
  :root {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fiestaboard/ui",
3
- "version": "5.8.0",
3
+ "version": "5.9.0",
4
4
  "description": "FiestaUI — the FiestaBoard design system. React components on Base UI with Tailwind v4 design tokens.",
5
5
  "license": "MIT",
6
6
  "repository": {