Skip to content
Wireframe Theme Selector Pattern
AutoXXS (320px)XS (375px)SM (640px)MD (768px)LG (1024px)XL (1280px)XXL (1536px)
SketchMaterialiOSTamagui
DataInjectionKeyPatternsServiceTransactionProcessResearchProductQualityPerformanceSpecDomainFunctionTechnologyArchitectureConfigMiddlewareDataDatabaseDrizzleMigrationModelop-sqliteSchemaSQLState ManagementDraftKeystoneMergePatchPatchesPersistenceReactiveRedoStoreUndoTestingDeviceFactoryIsolationTypeScriptZodTopicsCommunicationBidsNVCDesignDesign ImplicationsEducationPedagogyFoundationsPsychologyAttachmentFloodingRelatingAuthentic RelatingUIEditorReact Native

Wireframe Theme Selector Pattern

Fragment convention Wireframe Theme Selector Pattern
tags
uiconventiontheming

Both wa-dark/wa-light and data-wf-theme are set on the same <html> element. Themes must define variables in two compound selector blocks so they cooperate with Web Awesome’s dark/light class mechanism:

/* ── Light (default) ──────────────────────────────────────── */
/* Applies when wa-light is present, and also before any WA */
/* class is set (prevents flash of unstyled content at paint). */
:root[data-wf-theme="{id}"],
:root.wa-light[data-wf-theme="{id}"] {
--wf-color-primary: #…;
--wf-color-primary-text: #…;
--wf-color-bg: #…;
--wf-color-bg-light: #…;
--wf-color-bg-elevated: #…;
--wf-color-text: #…;
--wf-color-text-muted: #…;
--wf-color-border: #…;
--wf-color-border-dark: #…;
--wf-color-success: #…;
--wf-color-warning: #…;
--wf-color-danger: #…;
--wf-radius-card: …px;
--wf-radius-button: …px;
--wf-border-width: 1px;
--wf-spacing-gap: 1rem;
/* Optional: --wf-font-body, --wf-font-heading, --wf-font-mono */
}
/* ── Dark ─────────────────────────────────────────────────── */
/* Overrides when wa-dark is present on <html>. */
:root.wa-dark[data-wf-theme="{id}"] {
--wf-color-primary: #…; /* often a lighter tint than light mode */
--wf-color-bg: #…;
--wf-color-bg-light: #…;
--wf-color-bg-elevated: #…;
--wf-color-text: #…;
--wf-color-text-muted: #…;
--wf-color-border: #…;
--wf-color-border-dark: #…;
}
/* ── Component overrides ─────────────────────────────────── */
/* Scope to the theme to avoid polluting other themes. */
/* Use :root[data-wf-theme="{id}"] .wf-{component} for */
/* overrides that apply in both modes; narrow further with */
/* .wa-light / .wa-dark when mode-specific shapes are needed. */
:root[data-wf-theme="{id}"] .wf-card { … }
:root.wa-dark[data-wf-theme="{id}"] .wf-card { … }

Specificity notes

SelectorSpecificityWhen it wins
:root[data-wf-theme="{id}"](0,1,1)Default / light mode
:root.wa-light[data-wf-theme="{id}"](0,2,1)Explicit light mode (same result)
:root.wa-dark[data-wf-theme="{id}"](0,2,1)Dark mode — beats the single-selector default

The dark block wins by specificity alone — no !important or load-order tricks required. The plain :root[data-wf-theme] block handles the moment before any WA class is applied (pre-paint flash prevention).