UI Skins
Philosophy: Expose CSS custom properties (design tokens) and theme variants as YAML plugins so site builders can pick brand colors, modes, and theme switches from theme settings — without forking the theme. Skins inject CSS variables and class/data attributes into the page head and root element at render time.
| I need to... | Guide | Summary |
|---|---|---|
| Understand what UI Skins does and when to use it | Overview | Use UI Skins when site builders need to adjust CSS custom property values or toggle named theme variants from theme settings. It is config-time and theme-wide — not per-block and not runtime. |
| Install UI Skins | Installation | Install UI Skins with composer and drush en. Single module only — no submodules. Requires Drupal ^10.3 or ^11 and PHP 8.3+. |
| Declare a CSS variable plugin in YAML | CSS Variable Definition | Declare CSS variable plugins in {theme}.ui_skins.css_variables.yml at the theme root. Each plugin maps a machine name to a CSS variable, a form widget type, and a map of CSS scope → default value. |
| Pick a form widget for a CSS variable | Variable Types & Widgets | Use ui_skins_alpha_color for color tokens (8-char hex), textfield for numeric/unit/arbitrary CSS values, or a custom form element plugin for specialized inputs. |
| Wire variable scopes for nested overrides | Variable Scopes | default_values is a map of CSS selector → value emitting separate CSS rules at render time. Site-builder edits only replace the :root scope value. |
| Declare a theme plugin (light/dark/brand variant) | Theme Definition | Declare theme plugins in {theme}.ui_skins.themes.yml. Each specifies a target element (body/html), injection key (class or data-attribute), value, optional asset library, and optional dependencies. |
| Apply a class vs a data attribute for theme switches | Theme Targets & Keys | Match target and key to the CSS selectors your theme already uses. Bootstrap 5 uses html[data-bs-theme]; Tailwind dark mode uses html.dark. |
| Chain themes via dependencies | Theme Dependencies | Theme dependencies are additive — declaring one theme as a dependency causes both to activate simultaneously. Not a mutual-exclusivity mechanism. |
| Ship a sub-theme with its own variables and themes | Theme Authoring | Author CSS using var(--token), attach via libraries.yml, declare matching plugins at the theme root, clear cache. Sub-themes inherit parent plugin definitions and can override with the same plugin ID. |
| Understand the render-time injection mechanism | Render Pipeline | UI Skins runs via HookHandler\PreprocessHtml. It reads theme settings, resolves transitive dependencies, injects attributes, emits a <style> tag, and attaches optional libraries. |
| Combine UI Skins with UI Styles | UI Skins + UI Styles Together | UI Skins sets CSS variable values theme-wide; UI Styles applies utility classes per-block. Wire them via CSS: color: var(--brand-primary) inside .text-primary. |
| Avoid common mistakes | Anti-Patterns | The most common mistakes are hardcoding hex colors in CSS, expecting runtime switching, and placing YAML files in theme subdirectories instead of the root. |
| Find key classes and services | Code Reference Map | Key classes, services, plugin discovery paths, and theme settings storage schema for the UI Skins module. |