Diwa Design System

Theme

Diwa ships two themes — Noir (dark, default) and Light. Semantic tokens automatically resolve to the correct value for the active theme. Switching is done by toggling data-theme="light" on any ancestor element.

Example

Theme Noir

Background

primary
bg-base
bg-surface
bg-shading
bg-frosted

Contrast

contrast-low
contrast-med
contrast-high

Notification

success
success-soft
warning
warning-soft
error
error-soft
info
info-soft

State

hover
active
focus
disabled

Theme Light

Background

primary
bg-base
bg-surface
bg-shading
bg-frosted

Contrast

contrast-low
contrast-med
contrast-high

Notification

success
success-soft
warning
warning-soft
error
error-soft
info
info-soft

State

hover
active
focus
disabled

Accent Scale(theme-invariant)

accent-50
accent-100
accent-200
accent-300
accent-400
accent-500
accent-600
accent-700

Usage

Noir is the primary design expression. Use Light only where context demands it — for example, in print-oriented views, high-ambient-light environments, or sub-sections embedded in external light-themed surfaces.

Do

  • Choose Noir as the first choice for Diwa AI interfaces — it reduces visual fatigue in long sessions.
  • Use accessibility-safe semantic tokens: contrast-high for primary text, contrast-medium for secondary, contrast-low only for decorative dividers.
  • Play with bg-base / bg-surface layers to create hierarchy — surface sits one step above base.
  • Scope light theme to a subtree with data-theme="light" on a container element when mixing is intentional.

Don't

  • Don't use contrast-low for text or critical information — it fails WCAG AA contrast.
  • Don't mix tokens from different themes (e.g. using a Noir color value in a Light context).
  • Don't add new raw color values to components. Always reference a semantic token.
  • Don't override semantic tokens with primitives in ad-hoc inline styles.

Theme switching: Toggle by setting data-theme="light" on <html>. Removing the attribute returns to Noir. Themes can be scoped to any subtree.

// Switch to Light
document.documentElement.setAttribute('data-theme', 'light');
// Return to Noir
document.documentElement.removeAttribute('data-theme');
// Scope to a subtree
<section data-theme="light">…</section>

Styles

Import JS tokens for CSS-in-JS frameworks. Hover any tile above to see its full token name. Use CSS custom properties directly in stylesheets — they resolve automatically for the active theme.

import {
  // Theme objects (resolved values for current theme)
  themeNoir,
  themeLight,

  // Noir semantic tokens
  themeNoirPrimary,
  themeNoirBackgroundBase, themeNoirBackgroundSurface,
  themeNoirBackgroundShading, themeNoirBackgroundFrosted,
  themeNoirContrastLow, themeNoirContrastMedium, themeNoirContrastHigh,
  themeNoirNotificationSuccess, themeNoirNotificationSuccessSoft,
  themeNoirNotificationWarning, themeNoirNotificationWarningSoft,
  themeNoirNotificationError, themeNoirNotificationErrorSoft,
  themeNoirNotificationInfo, themeNoirNotificationInfoSoft,
  themeNoirStateHover, themeNoirStateActive,
  themeNoirStateFocus, themeNoirStateDisabled,

  // Light semantic tokens
  themeLightPrimary,
  themeLightBackgroundBase, themeLightBackgroundSurface,
  themeLightBackgroundShading, themeLightBackgroundFrosted,
  themeLightContrastLow, themeLightContrastMedium, themeLightContrastHigh,
  themeLightNotificationSuccess, themeLightNotificationSuccessSoft,
  themeLightNotificationWarning, themeLightNotificationWarningSoft,
  themeLightNotificationError, themeLightNotificationErrorSoft,
  themeLightNotificationInfo, themeLightNotificationInfoSoft,
  themeLightStateHover, themeLightStateActive,
  themeLightStateFocus, themeLightStateDisabled,

  // Accent scale (theme-invariant)
  colorAccent50, colorAccent100, colorAccent200, colorAccent300,
  colorAccent400, colorAccent500, colorAccent600, colorAccent700,
} from '@diwacopilot/components/styles';

/* ─── CSS — always resolve via semantic tokens ────────────────────── */
.card {
  background: var(--diwa-bg-surface);  /* adapts to active theme */
  color:      var(--diwa-primary);
  border:     1px solid var(--diwa-contrast-low);
}

.badge-accent {
  background: var(--diwa-color-accent-100);
  color:      var(--diwa-color-accent-400);
}

/* ─── Scoped light theme region ──────────────────────────────────── */
[data-theme="light"] .card {
  /* tokens above already resolve correctly — no extra overrides needed */
}
@use '@diwacopilot/components/styles' as *;

/* Scoped theme override for a region */
.dark-panel  { @include diwa-theme-noir; }
.light-panel { @include diwa-theme-light; }

/* Use semantic tokens directly in component styles */
.card {
  background: $diwa-bg-surface;
  border: 1px solid $diwa-border;
  color: $diwa-text-primary;
}

.badge-accent {
  background: $diwa-color-accent-100;
  color: $diwa-color-accent-400;
}