@everystate/css 1.0.11

State-driven CSS: reactive styling, design tokens, typed validation, and WCAG contrast enforcement - all via path-based state.

Install

npm install @everystate/css @everystate/core

Overview

@everystate/css has two main APIs:

Both use the same get/set/subscribe pattern as the core store. CSS rules are state. Tokens are state. Themes are state transitions.

Style Engine

createStyleEngine(store) → styleEngine

Creates a style engine that compiles dot-path state to real CSS rules via the CSSOM.

import { createEveryState } from '@everystate/core';
import { createStyleEngine } from '@everystate/css';

const store = createEveryState({});
const engine = createStyleEngine(store);

Dot-Path CSS

Write CSS as dot-path state. The style engine compiles it to real stylesheet rules:

// Set CSS properties via dot paths
store.set('css..button.backgroundColor', '#3b82f6');
store.set('css..button.color', '#ffffff');
store.set('css..button.padding', '0.5rem 1rem');
store.set('css..button.borderRadius', '8px');

// Compiles to:
// .button { background-color: #3b82f6; color: #ffffff; padding: 0.5rem 1rem; border-radius: 8px; }
Path convention CSS paths use css.. prefix. The double-dot indicates a class selector. Tag selectors use css. with a single dot. ID selectors use css.#.

Pseudo-Classes

// :hover
store.set('css..button:hover.backgroundColor', '#2563eb');
store.set('css..button:hover.transform', 'scale(1.02)');

// :focus
store.set('css..input:focus.outline', '2px solid #3b82f6');

// Compiles to:
// .button:hover { background-color: #2563eb; transform: scale(1.02); }
// .input:focus { outline: 2px solid #3b82f6; }

Reactive Updates

Because CSS rules are state, changing a value reactively updates the stylesheet - no class toggling, no inline styles:

// Initial
store.set('css..card.backgroundColor', '#1e293b');

// Later - the stylesheet rule updates in place
store.set('css..card.backgroundColor', '#0f172a');

Design System

createDesignSystem(store) → designSystem

Creates a design system that stores tokens as state and provides reactive bindings to styles.

import { createDesignSystem } from '@everystate/css';

const ds = createDesignSystem(store);

Design Tokens

ds.setTokens({
  'color.primary': '#3b82f6',
  'color.secondary': '#10b981',
  'color.bg': '#0f172a',
  'color.text': '#e2e8f0',
  'spacing.sm': '0.5rem',
  'spacing.md': '1rem',
  'spacing.lg': '2rem',
  'radius.md': '8px',
});

// Read a token
ds.getToken('color.primary'); // '#3b82f6'

// Tokens are reactive - change a token, styles update
store.set('token.color.primary', '#ef4444');

Theme Switching

const themes = {
  light: {
    'color.bg': '#ffffff',
    'color.text': '#1e293b',
    'color.primary': '#3b82f6',
  },
  dark: {
    'color.bg': '#0f172a',
    'color.text': '#e2e8f0',
    'color.primary': '#60a5fa',
  }
};

// Bulk theme swap - all tokens update atomically
ds.applyTheme(themes.dark);

// Toggle
function toggleTheme() {
  const current = store.get('theme.mode') || 'dark';
  const next = current === 'dark' ? 'light' : 'dark';
  ds.applyTheme(themes[next]);
  store.set('theme.mode', next);
}

CSS State (v1 API)

createCssState(initial?: object) → cssStateManager

The original CSS state manager. Stores state directly in CSS custom properties (--key: value) on :root and as data-* attributes on elements.

import { createCssState } from '@everystate/css';

const ui = createCssState({ theme: 'light', count: 0 });
ui.init();

// State is now in CSS:
// :root { --theme: light; --count: 0; }
// <html data-theme="light" data-count="0">

setState / getState

ui.setState(key: string, value: any) → void
ui.getState(key: string) → any
ui.setState('theme', 'dark');
// :root now has --theme: dark
// <html> now has data-theme="dark"

const theme = ui.getState('theme'); // 'dark'

observe(key, callback)

ui.observe(key: string, callback: (value) → void) → unobserve
const unobserve = ui.observe('theme', (value) => {
  console.log('Theme changed to:', value);
});

ui.setState('theme', 'dark'); // logs "Theme changed to: dark"
unobserve();

Declarative Binding

<!-- Auto-updates text content when 'count' changes -->
<span data-observe="count">0</span>

<!-- Sets state on click -->
<button data-state-action="theme" data-state-value="dark">Dark Mode</button>

WordPress / Static Sites

Drop a <script> tag into your theme. No build step, no React, no webpack:

<script type="module">
  import { createCssState } from 'https://esm.sh/@everystate/css';
  const ui = createCssState({ sidebar: 'open', theme: 'light' });
  ui.init();
</script>

<style>
  [data-sidebar="closed"] .sidebar { display: none; }
  [data-theme="dark"] { --bg: #1a1a2e; --text: #eee; }
</style>

Web Components

CSS custom properties defined on :root cascade into Shadow DOM, making @everystate/css a natural theming bridge:

connectedCallback() {
  const theme = getComputedStyle(this).getPropertyValue('--theme').trim();
  this.shadowRoot.innerHTML = `<p>Current theme: ${theme}</p>`;
}