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

Wireframe CSS

Overview

The StarSpec wireframe system provides low-fidelity UI sketches that focus on structure and flow rather than high-fidelity design. Styles are implemented in wireframe.css (the Sketch base) and per-theme overrides in wireframe-{id}.css.

Wireframe CSS Conventions

StarSpec uses a low-fidelity, themeable CSS system for UI wireframes. It follows a BEM-lite convention for predictable styling and easy theme overrides.

Naming Convention

  • Block: .wf-{component} (e.g., .wf-tabs)
  • Element: .wf-{component}__{element} (e.g., .wf-tabs__header)
  • Modifier/State: [data-{modifier}] (e.g., .wf-tabs__header[data-active="true"])

Selector Pattern

Core variables are defined in :root and must be overridden in two compound selectors per theme β€” one for light mode and one for dark mode. Both wa-dark/wa-light and data-wf-theme are on the same <html> element, so the compound selectors resolve correctly by specificity alone.

/* Light (default) */
:root[data-wf-theme="ios"],
:root.wa-light[data-wf-theme="ios"] { … }
/* Dark */
:root.wa-dark[data-wf-theme="ios"] { … }

For the full copy-paste template including component override scoping, see get_instructions("starspec/fragments/wireframe/theme-selector-pattern").

Variable Reference

For the full --wf-* variable reference (brand, semantic, geometry, font), see get_instructions("starspec/fragments/wireframe/theme-variables").

Theme Architecture

StarSpec supports multiple themes through a data-wf-theme attribute on the <html> element, set by the wireframe theme picker in the page header.

<html data-wf-theme="ios" class="wa-dark">

Themes override the default CSS variables and provide platform-specific layout adjustments. Every theme must support both light and dark mode. Web Awesome controls light/dark by adding wa-light or wa-dark to <html>, synced from Starlight’s data-theme attribute.

Active Themes

IDLabelCSS fileLightDark
""Sketchwireframe.css (base, always loaded)βœ…βœ…
muiMaterialwireframe-mui.cssβœ…βœ…
iosiOSwireframe-ios.cssβœ…βœ…
tamaguiTamaguiwireframe-tamagui.cssβœ…βœ…

Compound Selector Pattern

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).

Creating a New Wireframe Theme

Step 1 β€” Create the CSS file

Create src/styles/wireframe-{id}.css. Use the compound selector template above. All --wf-color-*, --wf-radius-*, and --wf-spacing-* variables must be defined in both the light and dark blocks.

Optionally, create src/styles/{id}.theme.toml to declare anchor values for StarVision’s visual extraction loop β€” see Theme TOML Specification.

Step 2 β€” Register in themes.json

Add an entry to src/themes.json:

{ "id": "{id}", "label": "{Label}" }

astro.config.ts auto-discovers wireframe-{id}.css via fs.existsSync() β€” no manual config change is needed.

Step 3 β€” Verify

  • Toggle light and dark mode with each theme selected β€” wireframe area must update correctly
  • Confirm the theme appears in the header dropdown
  • Check that no wf-* component renders with hardcoded colors from a previous theme

For the full authoring guide including dark palette guidelines, see Authoring Wireframe Themes.

Layout Structure

Wireframes are composed of high-level blocks that use standard layouts:

  1. Sections (.wf-section): Root container for a wireframe, often with a title
  2. Stacks (.wf-stack): Vertical layout with configurable [data-gap]
  3. Rows (.wf-row): Horizontal layout with [data-gap] and [data-justify]
  4. Cards (.wf-card): Semantic groupings with optional [data-elevated="true"]

Component Modifiers

Modifiers are applied via data-* attributes, keeping the DSL clean while providing flexible styling.

Buttons

  • [data-variant="primary"]: Prominent action
  • [data-variant="secondary"]: Default/Outline
  • [data-variant="ghost"]: Text-only link
  • [data-variant="danger"]: Destructive action

Progress & Sliders

  • [data-variant="success"]: Green fill
  • [data-variant="warning"]: Orange fill
  • [data-variant="danger"]: Red fill

Extending the CSS

To add a new component style:

  1. Define a new block class .wf-{name}
  2. Use existing variables (var(--wf-color-primary)) to ensure theme compatibility
  3. Use data-* attributes for any variants or state
  4. Add element classes with the __ separator for internal parts (e.g., .wf-{name}__indicator)

Never use hardcoded hex values inside component rules. All color values must reference --wf-* variables so they respond to theme and mode changes.