# `SurfaceSkinProvider` _(no submodules)_ ## Purpose `` is the single React boundary that activates a skin for every atomic control inside its subtree. It writes the resolved palette of CSS custom properties (`--cs-*`) onto a wrapping `
`'s inline `style` attribute; every atomic control reads its colours through `var(--cs-…)` declarations, so changing skin is purely a CSS-variable swap with no React-side dispatch. This is the only path through which a skin influences rendering. The schema spec is explicit on this point: there is no JS-level skin registry, no `React.useContext` consumed by controls, and no themed component variants. Keeping skin enforcement on the CSS side enables a single physical surface to host two side-by-side skinned subtrees without forking the React tree. ## Features - Closed `SurfaceSkinVarName` enumeration of canonical variables. - Frozen `DEFAULT_SURFACE_SKIN_VARS` palette. - Pure `buildSkinStyle(vars)` helper for unit testing. - Caller-supplied `className` appended to the default `rcs-skin` class. - `data-skin-id` attribute on the wrapper for integration-test selectors. ## Usage: Basic ```tsx import { SurfaceSkinProvider } from "@suaveplan/react-control-surface/skin"; export function App(): React.ReactNode { return ( ); } ``` ## Usage: Advanced ```tsx import { SurfaceSkinProvider } from "@suaveplan/react-control-surface/skin"; const orangeKnobOverride = { "--cs-knob-track-color": "#ff8800", "--cs-knob-indicator-color": "#ffe0b2", } as const; export function NkiSurface(): React.ReactNode { return ( ); } ``` ## API Reference - `SurfaceSkinProvider(props): React.ReactNode` - `id: string` — written to `data-skin-id` on the wrapper. - `vars?: SurfaceSkinVars` — partial override map merged on top of the defaults; entries whose value is `undefined` keep the default. - `className?: string` — appended to the `"rcs-skin"` base class. - `children?: React.ReactNode` - `buildSkinStyle(vars?: SurfaceSkinVars): CSSProperties` — pure merge helper. - `DEFAULT_SURFACE_SKIN_VARS`, `SURFACE_SKIN_VAR_NAMES` — re-exported defaults and the canonical CSS variable name list. ## Implementation Notes The provider intentionally renders a `
` rather than a fragment because CSS variables only cascade through real DOM ancestors. Inline styles are used (instead of injecting a stylesheet) so server-side rendering remains deterministic and consumers see exactly the colours they configured without load-order pitfalls. Overrides are processed as a string-keyed loop so arbitrary `--cs-foo` properties — useful for one-off device-specific themes — pass straight through to the DOM without requiring an addition to the closed `SurfaceSkinVarName` union.