EclipsePalette Explained: Building Accessible Dark Mode Palettes

From Concept to Code: Implementing EclipsePalette in Web Apps

Why a deliberate palette matters

A well-designed color system improves usability, accessibility, branding consistency, and development speed. EclipsePalette is a dark-mode-first color system that balances contrast, tone, and semantic usage so UIs feel cohesive across components and states.

Design goals for EclipsePalette

  • Dark-first: Defaults optimized for low-light backgrounds with careful contrast against near-black surfaces.
  • Semantic tokens: Colors named by purpose (e.g., surface, muted, accent, success, danger) instead of visual descriptions.
  • Accessible contrast: Meet WCAG AA at minimum for normal text and aim for AAA for UI elements where feasible.
  • Scalability: Support multiple elevations and tints for component variants and states.
  • Theming-ready: Easy to expose runtime variables for light/dark switching and branded overrides.

Core tokens and structure

Use a small, consistent set of tokens as the foundation:

  • Background / Surface — base surfaces (surface-100, surface-200, surface-300 for elevated layers)
  • Text — primary, secondary, disabled
  • Accent — primary accent and its hovered/pressed variants
  • Support — success, warning, danger (with subtle and strong variants)
  • Border / Divider — subtle separators and stronger strokes
  • Shadow / Elevation — color/opacity tokens to tint shadows in dark mode

Example token names (CSS custom property style): :root { –eclipse-surface-100: #0b0d10; –eclipse-surface-200: #111219; –eclipse-surface-300: #161820; –eclipse-text-primary: #e6eef8; –eclipse-text-secondary: #b7c4d6; –eclipse-accent-500: #6bb0ff; –eclipse-accent-600: #4b98ff; –eclipse-success-500: #4bd37a; –eclipse-danger-500: #ff6b7a; –eclipse-divider: rgba(255,255,255,0.06); }

Choosing colors and ensuring contrast

  1. Pick base surface and adjust foreground to meet contrast ratios (normal text ≥ 4.5:1).
  2. Use muted variants for secondary text and placeholders (contrast ≥ 3:1 for large text).
  3. Test accent colors on both surface-100 and surface-200; provide stronger accents for emphasis.
  4. Use tools or libraries (contrast checkers, axe-core) during design and CI tests.

Building palettes programmatically

Generate tints/shades from a single accent using HSL or color libraries (e.g., chroma.js) to keep harmonized hues:

JavaScript example (conceptual):

js
import chroma from ‘chroma-js’;const base = chroma(‘#6bb0ff’);const accent = { 300: base.brighten(1).hex(), 500: base.hex(), 700: base.darken(1).hex()};

Implementing in CSS (variables + utility classes)

  • Define variables in a theme root and switch via data-theme or a class on .
  • Create utility classes for semantic roles (.btn-primary, .chip-success) that reference tokens.

CSS snippet:

css
:root[data-theme=“eclipse”]{ –surface: #0b0d10; –text: #e6eef8; –accent: #6bb0ff;}.btn-primary{ background: var(–accent); color: var(–text);}

Component-level guidelines

  • Buttons: provide filled, outline, and ghost variants using surface and accent tokens; ensure focus and active states meet contrast.
  • Cards: use surface-200 for elevated cards, subtle divider and shadow tokens for separation.
  • Inputs: use border/divider tokens and clear disabled/invalid states using support colors.
  • Icons: prefer single-color glyphs with accessible contrast; apply reduced-opacity secondary fills.

Accessibility checklist

  • Text contrast: ≥ 4.5:1 for body, ≥ 3:1 for large text.
  • Focus visible: at least 3:1 contrast between focus outline and adjacent surface.
  • State differences: ensure hover/active/focus states are perceivable without color alone (use underline, icons, or gestures).
  • Test with color blindness simulators and keyboard-only navigation.

Theming and runtime swapping

  • Expose theme via CSS variables and a small JS toggler. Persist preference in localStorage and respect prefers-color-scheme as default.

Minimal toggler:

js
const setTheme = t => document.documentElement.setAttribute(‘data-theme’, t);const prefer = window.matchMedia(‘(prefers-color-scheme: dark)’).matches ? ‘eclipse’ : ‘light’;setTheme(localStorage.getItem

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *