You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Stage 5 theming maturity (web): portal variable channels and re-exports.
6
+
7
+
- Split theme-scope CSS vars into `semanticVars` (replaced by nested `theme`/`colorScheme`) and `customVars` (component hooks that inherit through named children into portals).
8
+
- Re-export `generateScale`, `generatePairedPalette`, `checkThemeContrast`, and related types from `@reactive/silk`.
9
+
- Document the frozen public component CSS-variable list via `silkComponentVarMeta` / `formatComponentVarDocsTable`.
Stage 2 (visual primitives & forms): `Surface`, `Card`, `Heading`, `Badge`, status primitives, `Field`/`Input`/`Textarea`, Radix-backed form controls, token audit (`success`, elevation shadows, contrast), SettingsForm fixture, and [pre-1.0 API policy](docs/API_POLICY.md). Stage 1 layout vocabulary remains. The staged plan is in [docs/ROADMAP.md](docs/ROADMAP.md); the project charter is [docs/PRINCIPLES.md](docs/PRINCIPLES.md).
20
+
Stage 5 (theming maturity): `generatePairedPalette` / `generateScale`, `checkThemeContrast`, nested portal variable channels, TenantGallery + ThemePlayground in docs, frozen public component CSS-var list. Prior stages shipped layout, visual/forms, interaction primitives, and composites. The staged plan is in [docs/ROADMAP.md](docs/ROADMAP.md); the project charter is [docs/PRINCIPLES.md](docs/PRINCIPLES.md).
21
21
22
22
## Packages
23
23
@@ -89,10 +89,13 @@ export function App() {
89
89
}
90
90
```
91
91
92
-
Custom / tenant themes use the style-attribute path:
92
+
Custom / tenant themes use the style-attribute path. For brand seeds with paired light/dark:
|`red` / `green`| Built-in defaults, or `dangerSeedHex` / `successSeedHex`|
69
+
70
+
`generateScale(seed, colorScheme)` is the lower-level primitive (12-step OKLCH ramp). Seed input is canonical sRGB hex (`#RGB` / `#RRGGBB`); invalid input throws. Algorithm curves may improve between minors; the hex contract and 12-step shape are stable.
71
+
72
+
See **Theme/TenantGallery** (two tenants × light/dark side by side) and **Theme/ThemePlayground** (live controls + contrast readout).
73
+
43
74
## Typography and fonts
44
75
45
76
Silk exposes three font-family tokens (inspired by Claude Cowork's sans / serif / mono roles) and maps typography roles onto them:
@@ -88,23 +119,66 @@ Defaults are a typed map — not a runtime component registry.
88
119
89
120
## Nesting and portals
90
121
91
-
Nesting works via DOM CSS variable inheritance in normal flow.
92
-
93
-
Portals (for example Dialog) still render under `document.body` by default, but Silk reconstitutes the **nearest** `ThemeProvider` / `SilkProvider` scope on the portaled tree: the same theme class, `data-theme` (when set), and custom `createTheme` CSS variables. Nested providers therefore theme their dialogs correctly without an explicit portal container.
122
+
Nesting works via DOM CSS variable inheritance in normal flow, with two variable **channels**:
94
123
95
-
For cases where you need the portal DOM to live inside a particular subtree (stacking, clipping, or measuring against that subtree), pass Dialog `container`. Nested theming itself does **not** require `container` — see **Components/Interaction/Dialog → NestedThemePortal**.
96
-
97
-
## Component CSS variable hooks
98
-
99
-
Public hooks like `--silk-button-bg` resolve through private vars:
| Semantic | `--silk-color-*`, radii, type, motion, shadows, focus geometry, space source scales | **Replaced** — named children do not carry outer tenant semantics into portals |
127
+
| Custom | Component hooks (`--silk-button-bg`, …) and other `--silk-*` extensions | **Inherited** — portals under an inner named scheme still see outer hooks |
128
+
129
+
Supported patterns:
130
+
131
+
1. **Tenant → named** — outer `theme={tenant}`, inner `colorScheme="dark"`: inner (and its portals) use named dark semantics; outer component hooks still apply.
132
+
2. **Named → tenant** — outer named scheme, inner custom theme: inner semantics win for that subtree and its portals.
Portals (Dialog, Popover, Select, …) reconstitute the nearest scope: theme class, `data-theme`, semantic vars, and custom vars. Nested theming does **not** require Dialog `container` — pass `container` only when the portal DOM must live inside a particular subtree.
136
+
137
+
Constant SSR `<style>` from behavior bindings (ScrollArea) is charter-permitted and is not a theme stylesheet.
138
+
139
+
## Public component CSS variable hooks
140
+
141
+
Component tokens stay sparse — an override surface, not a parallel token system. Every hook is consumed as `var(--silk-…, <semantic fallback>)` and never pre-declared on the component.
Do **not** pre-declare `--silk-button-bg: var(--silk-accent)` on the component — that shadows consumer overrides. See **Components/Visual/Button → StyledOverrides**.
179
+
Do **not** pre-declare `--silk-button-bg: var(--silk-accent)` on the component — that shadows consumer overrides. See **Components/Visual/Button → StyledOverrides**. Removals, renames, and meaning changes are breaking per [API_POLICY](https://github.com/reactive/silk/blob/main/docs/API_POLICY.md).
106
180
107
181
## Further reading
108
182
109
-
- Theme stories under **Theme**
183
+
- Theme stories under **Theme** (TenantGallery, ThemePlayground, TokenAudit)
'Stage 5 exit: two visually distinct tenant themes (Ocean, Ember), each with paired light/dark from `generatePairedPalette`, rendered side by side with inline CSS variables only.',
0 commit comments