Semantic Derivation
Play+ Semantic Derivation Guideβ
Overviewβ
Semantic tokens are the heart of Play+'s theming model. They allow you to build visually rich and brand-flexible UI experiences by mapping global raw values to meaningful roles. This document explains how semantic tokens are derived, when to use them, when to avoid them, and how the Play+ theming engine operates.
π§± Token Architecture Summaryβ
Tier | Token Type | Ownership | Usage Scope | Overridable? | Example |
---|---|---|---|---|---|
1 | Global Tokens | Play+ Core | Raw values (e.g., colors, spacing) | β (Do not override) | --global-color-pink-500 |
2 | Semantic Tokens | User/Theme | Design roles (e.g., primary text) | β Theme-specific | --color-brand-primary |
3 | Component Tokens | Advanced Usage | Component-specific overrides | β Scoped | --component-button-padding-vertical |
π§ How the Engine Runsβ
The Play+ Theming Engine loads when your application initializes or when a theme is switched at runtime. Here's how it operates:
- Loads the base CSS (
_base.css
) to get the global and default semantic tokens. - Loads
theme.map.json
from the current brand/theme directory. - Applies mappings of semantic tokens β new global tokens.
- Applies derived states (e.g., hover, active, focus, dark variants) based on naming rules.
- Injects final token map into
:root
and watches for hot-swappable updates.
This engine ensures the entire application theme is controlled via one lightweight JSON map, making live previews and runtime updates seamless.
π¨ What Gets a Semantic Token (and What Doesnβt)β
Category | Needs Semantic Token? | Reason |
---|---|---|
Brand Colors | β | Changes between themes; context-aware. |
Text Colors | β | Needs adaptive contrast. |
Backgrounds | β | May shift in dark/light themes. |
Typography (Fonts) | β | Brands may change body/heading fonts. |
Motion Patterns | β | Shared Play+ motion language; not brand-specific. |
Shadow/Elevation | β | Generally consistent across brands. |
Radius | β οΈ (Partial) | Use semantic token if branding requires it. |
Icon Sizes | β | Functional sizes; unlikely to vary. |
Accessibility Tokens | β | Used by accessibility-aware components. |
π Token File Responsibilitiesβ
Path | Purpose |
---|---|
styles/core/_base.css | Contains all global (raw value) tokens and defines the CSS variables for semantic tokens with their base fallback values |
styles/themes/acme/theme.map.json | Maps semantic tokens to new global values for a specific brand. The engine falls back to styles/themes/default/theme.map.json if no theme is loaded. |
β οΈ Never edit
_base.css
directly to theme your app. Instead, override semantic tokens viatheme.map.json
.
β Default Semantic Token Listβ
This list comes from _base.css
and serves as the baseline for all themes:
Colorsβ
--color-brand-primary
--color-brand-secondary
--color-brand-primary-hover
--color-text-primary
--color-text-secondary
--color-text-disabled
--color-text-on-brand
--color-surface-interactive-default
--color-surface-disabled
--color-border-default
--color-border-focus
Typographyβ
--font-family-display
--font-family-heading
--font-body-1
,--font-body-2
--font-heading-h1
,--font-heading-h2
Motionβ
--motion-pattern-fade
--motion-pattern-slide
--motion-pattern-pop
Layout & Spacingβ
--layout-max-width
--layout-gutter-default
Accessibilityβ
--accessibility-focus-ring-color
--accessibility-focus-ring-style
Iconographyβ
--icon-size-md
--icon-color-default
Contentβ
--content-line-measure
Glassmorphismβ
--glass-backdrop-blur
--glass-background-color
π§© Example Derivation Map (Default Theme)β
Semantic Token | Mapped Global Token |
---|---|
--color-brand-primary | --global-color-pink-500 |
--color-brand-primary-hover | --global-color-pink-700 |
--color-brand-secondary | --global-color-purple-500 |
--color-text-primary | --global-color-gray-700 |
--color-text-secondary | --global-color-gray-600 |
--color-text-disabled | --global-color-gray-400 |
--color-text-on-brand | --global-color-white |
--color-surface-interactive-default | --global-color-pink-500 |
--color-surface-disabled | --global-color-gray-200 |
--color-border-default | --global-color-gray-300 |
--color-border-focus | --global-color-pink-500 |
--font-family-display | --global-font-family-display |
--font-family-heading | --global-font-family-heading |
--font-family-body | --global-font-family-body |
--motion-pattern-fade | --global-motion-duration-swift + easing |
--layout-gutter-default | --global-spacing-4 |
--icon-color-default | --color-text-secondary |
--glass-backdrop-blur | --global-glassmorphic-blur |
π Naming Convention Guidelinesβ
Type | Prefix | Example |
---|---|---|
Color | color- | color-surface-disabled |
Typography | font- | font-heading-h1 |
Radius | radius- | radius-md |
Motion | motion-pattern- | motion-pattern-slide |
Layout | layout- | layout-gutter-default |
Icon | icon- | icon-color-on-brand |
Content | content- | content-line-measure |
Accessibility | accessibility- | accessibility-focus-ring-width |
π¦ Best Practicesβ
- Never use global tokens directly in components.
- Derive all design decisions through semantic tokens.
- Only use component-level tokens for scoped overrides or design exceptions.
- Document all brand themes via
theme.map.json
. - Use fallback defaults to ensure graceful degradation.
π Theme Switchingβ
Play+ supports runtime theming:
import { playTheme } from 'playplus-core';
playTheme.load('acme'); // Switch to Acme theme
π§ Final Noteβ
Semantic tokens are what make Play+ adaptable, accessible, and maintainable at scale. They are not an extra layer β they are the design language.
"Let your brand breathe β one token at a time."