Skip to content
7 changes: 7 additions & 0 deletions .changeset/neutral-surfaces-scale.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@tailor-platform/app-shell": minor
---

Add a `--backdrop` colour token and the `bg-backdrop` utility for the dim layer behind modals. `Dialog`, `Sheet` and the CsvImporter drawer use it instead of `bg-black/50`. The value is the same (black at 50%), so nothing changes on screen. Override `--backdrop` on `:root` to change every backdrop at once.

In the default palette, the surface, border and brand colours now read the internal gray scale, a white step, and white alpha steps. All colours are unchanged. If your code reads these tokens with `getComputedStyle(...).getPropertyValue()`, the string is now the step's notation, for example `#171717` instead of `rgba(23, 23, 23, 1)`. The `cream` and `bloom` palettes are not changed.
11 changes: 11 additions & 0 deletions decisions/semantic-color-roles.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,14 @@ The component variant names (`Badge` and `Alert` `error`, Badge `neutral`) are p
- Alert description text is the same colour as the Alert title in the default palette.
- Consumers who override `--status-*` or `--alert-*` keep working for their own `bg-status-*` and `bg-alert-*` utilities, which read those tokens. The shipped components (Badge, Alert, CsvImporter, MetricCard — its trend colours were literal `green-600` / `red-600` before) read the roles, not `--status-*` or `--alert-*`. To recolour them, override the roles (`--{intent}-*`); overriding `--status-*` or `--alert-*` no longer changes the components. `--status-*` and `--alert-*` remain for existing consumer code and are not used by components any more.
- cream, bloom and `_template.css` values are not edited. The header comments now list `--{intent}-{role}` among the inherited tokens.

## Update 2026-10-12: default surfaces, white and alpha scales

The default palette's surfaces and brand tokens read scale steps. For the default palette, this supersedes "all surfaces stay literal" and "Gray has no alpha steps" under Hue scales, and the second item under "Out of scope".

- New primitives, declared once with gray because they are the same in both modes: `--primitive-white` and `--primitive-{white,black}-a1` to `-a12`. The alpha values are Radix `whiteA` / `blackA` (0.05, 0.1, 0.15, 0.2, 0.3, then 0.1 steps to 0.9, and 0.95). They are not bridged, like the other primitives.
- In `default.css`, every BRAND and SYSTEM colour with an exact step now reads it. Light: background, sidebar and primary foreground 50, secondary and muted 100, sidebar border 200, primary and secondary foreground 900, the other foregrounds 950, card and popover white. Dark: primary 200, secondary, popover and muted 800, card and primary foreground 900, background and sidebar 950, the other foregrounds 50, border and sidebar border white a2, input white a3. No values change: every token resolves to the same colour as before in light and dark mode.
- White is its own step. The light page is gray 50 and cards are white; putting cards on gray 50 would remove the difference.
- New role `--backdrop`, `var(--primitive-black-a7)` (50%) in both modes, bridged as `bg-backdrop`. `Dialog`, `Sheet` and the CsvImporter drawer use it instead of `bg-black/50`; the value is the same. The name follows the CSS `::backdrop` pseudo-element and the Base UI `Backdrop` part. It is not `overlay`, because `--z-overlay` already names the modal layer, which holds both the backdrop and the popup.
- `--accent`, the shadows, the chart colours and `--destructive` stay literal. They have no matching step.
- `cream`, `bloom` and `_template.css` keep their own literal values. The header comments now list `--backdrop` among the inherited tokens.
16 changes: 8 additions & 8 deletions docs-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@
"hashes": {
"typeSurface": "b1614970f950ceb6",
"outline": "bda40376d6e3e008",
"snapshot": "b845d4c54453b0f0",
"snapshot": "ac70f5a7004d3bab",
"outputMd": "ec6a0ac098d1d87a",
"examples": "934c52d4e8761404"
}
Expand Down Expand Up @@ -1049,9 +1049,9 @@
"symbols": [],
"hashes": {
"typeSurface": null,
"outline": "45dcfe4383a87ea9",
"outline": "36cdcfab060a0d1c",
"snapshot": null,
"outputMd": "2fa0b6a249d8bd4f",
"outputMd": "86fe04e370ecdff5",
"examples": null
}
},
Expand Down Expand Up @@ -1186,7 +1186,7 @@
"hashes": {
"typeSurface": "e760949efcbe4c38",
"outline": "464d91acc48f7c9d",
"snapshot": "40d15c3f1003fdb0",
"snapshot": "2c9114c5a81198be",
"outputMd": "1f81ebd562c50371",
"examples": "b0eebb8c5e2219dc"
}
Expand Down Expand Up @@ -1304,9 +1304,9 @@
"symbols": [],
"hashes": {
"typeSurface": null,
"outline": "e63d837190e71ff1",
"outline": "18061fd0dd60d63d",
"snapshot": null,
"outputMd": "112b43c697d30369",
"outputMd": "bce2991c993061b6",
"examples": "4d19f4f688e0f0ac"
}
},
Expand Down Expand Up @@ -1676,7 +1676,7 @@
"packages/core/skills/app-shell-patterns/references/concepts/modules-and-resources.md": "bf15b5460f22d165",
"packages/core/skills/app-shell-patterns/references/concepts/routing-navigation.md": "8034c7f885994b29",
"packages/core/skills/app-shell-patterns/references/concepts/sidebar-navigation.md": "e342ef02dc2b9b86",
"packages/core/skills/app-shell-patterns/references/concepts/styling-theming.md": "112b43c697d30369",
"packages/core/skills/app-shell-patterns/references/concepts/styling-theming.md": "bce2991c993061b6",
"packages/core/skills/app-shell-patterns/references/components/action-panel.md": "71794d4b561e4d4b",
"packages/core/skills/app-shell-patterns/references/components/activity-card.md": "4f386e49380fb0b0",
"packages/core/skills/app-shell-patterns/references/components/ai-chat.md": "824d1aa36bb7f194",
Expand Down Expand Up @@ -1756,7 +1756,7 @@
"packages/core/skills/app-shell-patterns/references/patterns/interaction-toast.md": "f68bdab855730f48",
"packages/core/skills/app-shell-patterns/references/patterns/list-dense-scan.md": "916baa3cd2b9cbf1",
"packages/core/skills/app-shell-patterns/references/pages/document-detail.md": "717ef4e7ae835aff",
"packages/core/skills/app-shell-patterns/references/migrations.md": "013c3fef2303b096",
"packages/core/skills/app-shell-patterns/references/migrations.md": "1918f794d1bd4e99",
"packages/core/skills/app-shell-patterns/SKILL.md": "526decbfd2db6555"
}
}
5 changes: 5 additions & 0 deletions docs-src/concepts/styling-theming.docs.outline.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,14 @@ Colors follow shadcn-style semantic naming: a surface token and its matching `-f
| `--border` | hairlines, dividers | `border-border` |
| `--input` | form control borders | `border-input` |
| `--ring` | focus rings | `ring-ring` / `outline-ring` |
| `--backdrop` | dim layer behind a modal | `bg-backdrop` |

Surfaces are named by **role**, not by depth — there is no numbered `surface-1/2/3` ladder, and no third tier of body text below `muted-foreground`. Stack depth with `background` → `card` → `muted` plus a border or shadow, and reach for `popover` when the surface actually floats.

`--backdrop` is the dim layer behind `Dialog` and `Sheet` (black at 50% in both modes). Use `bg-backdrop` for your own modal layers instead of `bg-black/50`. Palettes inherit it; override it on `:root` to change every backdrop at once.

In the default palette, the surface, text and line tokens in this table read the internal gray scale, a white step, and white alpha steps (dark-mode lines), so their values match the gray used across the palette. `--backdrop` reads a black alpha step, and `--ring` is mixed from `--primary`. The other palettes set their own values.

#### Brand & action

| Token | Use | Tailwind |
Expand Down
2 changes: 1 addition & 1 deletion docs-src/guides/migrations.docs.outline.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ body {

Toggle dark mode and confirm a real surface changes: inspect a `Card` and watch its computed `background-color` go from `rgb(255, 255, 255)` to `rgb(23, 23, 23)` on the default palette.

Reading the token directly also works — `getComputedStyle(document.documentElement).getPropertyValue("--card")` returns the winning declaration, so a stale copy shows up as its own value. Just compare against the authored notation: AppShell writes `rgba(23, 23, 23, 1)`, not `#171717`, and the computed value preserves that form.
Reading the token directly also works — `getComputedStyle(document.documentElement).getPropertyValue("--card")` returns the winning declaration, so a stale copy shows up as its own value. Compare against the value the default palette resolves to: in dark mode `--card` returns `#171717`, the gray step it reads. (Releases before the default palette moved onto its colour scales returned `rgba(23, 23, 23, 1)`.) A copy in your own CSS shows up in the notation you wrote.

## 1.5.0: `loader` removed from file-based page definitions

Expand Down
5 changes: 5 additions & 0 deletions docs/concepts/styling-theming.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/migrations.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading