Convergence UI 2.0

Headless OKLCH theme tooling for Tailwind v4 and modern React apps

Convergence UI 2.0 pairs a typed theme engine with a floating React editor so teams can ship semantic CSS-variable themes, import existing token sets, validate accessibility, and export clean theme artifacts.

  • Typed ThemeDefinition model for light and dark themes
  • Headless engine for reading, updating, validating, importing, and exporting theme tokens
  • Floating React editor for live token editing, presets, saved workspaces, and accessibility QA
  • CSS import support for :root, .dark, and Tailwind-style token variables
  • Export support for Tailwind v4 and JSON in the editor
  • SSR-friendly <ConvergenceThemeStyle /> helper for Next.js and other React SSR setups
  • Per-component theme overrides through data-convergence-component

Installation

bash
npm install convergence-ui
bash
yarn add convergence-ui
bash
pnpm add convergence-ui

Quick Start

1. Add the editor

Drop the floating editor into your shell to edit semantic theme tokens live inside your app.

tsx
import { Convergence } from "convergence-ui";

export default function AppShell({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <>
      {children}
      <Convergence />
    </>
  );
}

2. Use the engine directly

Use the headless engine in scripts, tooling, tests, or custom app flows when you want to read, update, validate, import, or export themes without mounting the editor.

ts
import {
  ConvergenceEngine,
  DEFAULT_THEME_DEFINITION,
  scoreThemeAccessibility,
} from "convergence-ui";

const engine = new ConvergenceEngine(DEFAULT_THEME_DEFINITION, {
  autoApply: false,
});

engine.setOklch("primary", { l: 0.64, c: 0.18, h: 262 }, { mode: "light" });
engine.setTypography({ fontSans: "Inter, sans-serif" });

const tailwindTheme = engine.export("tailwind-v4");
const jsonTheme = engine.export("json");
const report = scoreThemeAccessibility(engine.getDefinition().themes.light);

3. Render theme CSS during SSR

Use the SSR helper to emit theme CSS from the server for Next.js and other React SSR setups.

tsx
import {
  ConvergenceThemeStyle,
  DEFAULT_THEME_DEFINITION,
} from "convergence-ui";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <head>
        <ConvergenceThemeStyle definition={DEFAULT_THEME_DEFINITION} />
      </head>
      <body>{children}</body>
    </html>
  );
}

Theme Shape

Themes are defined with a typed ThemeDefinition that stores semantic light and dark tokens alongside typography, layout, and shadow settings.

ts
import type { ThemeDefinition } from "convergence-ui";

const theme: ThemeDefinition = {
  themes: {
    light: { /* semantic OKLCH tokens */ },
    dark: { /* semantic OKLCH tokens */ },
  },
  typography: {
    fontSans: "Inter, sans-serif",
    fontSerif: "Georgia, serif",
    fontMono: '"JetBrains Mono", monospace',
    letterSpacing: "0px",
  },
  layout: {
    radius: "0.75rem",
    borderWidth: "1px",
    borderStyle: "solid",
  },
  shadows: {
    "shadow-color": { l: 0, c: 0, h: 0, a: 1 },
    "shadow-2xs": "0 1px 3px 0px oklch(0 0 0 / 0.05)",
    "shadow-xs": "0 1px 3px 0px oklch(0 0 0 / 0.05)",
    "shadow-sm": "0 1px 3px 0px oklch(0 0 0 / 0.10)",
    shadow: "0 1px 3px 0px oklch(0 0 0 / 0.10)",
    "shadow-md": "0 1px 3px 0px oklch(0 0 0 / 0.10)",
    "shadow-lg": "0 1px 3px 0px oklch(0 0 0 / 0.10)",
    "shadow-xl": "0 1px 3px 0px oklch(0 0 0 / 0.10)",
    "shadow-2xl": "0 1px 3px 0px oklch(0 0 0 / 0.25)",
  },
};

Import and Export

The editor exposes two export targets today:

  • tailwind-v4
  • json

The headless engine still supports the full export registry and can import existing CSS variables from :root, .dark, and Tailwind-style token definitions.

ts
import { ConvergenceEngine, DEFAULT_THEME_DEFINITION } from "convergence-ui";

const engine = new ConvergenceEngine(DEFAULT_THEME_DEFINITION, {
  autoApply: false,
});

engine.export("css");
engine.export("tailwind-v4");
engine.export("json");
engine.export("shadcn");

engine.import(`
  :root {
    --background: oklch(0.98 0 0);
    --foreground: oklch(0.14 0.01 260);
  }

  .dark {
    --background: oklch(0.10 0 0);
    --foreground: oklch(0.96 0 0);
  }
`);

Component Overrides

Convergence can scope token overrides to a specific component via data-convergence-component.

html
<button data-convergence-component="button">Save</button>

Use the helper to keep the attribute naming consistent across your app code.

ts
import { createComponentThemeAttributes } from "convergence-ui";

const attrs = createComponentThemeAttributes("button");

Validation and QA

Validation checks theme structure and token shapes. Accessibility scoring reports contrast outcomes for the main semantic foreground/background pairs.

ts
import {
  DEFAULT_THEME_DEFINITION,
  scoreThemeAccessibility,
  validateThemeDefinition,
} from "convergence-ui";

const validation = validateThemeDefinition(DEFAULT_THEME_DEFINITION);
const report = scoreThemeAccessibility(DEFAULT_THEME_DEFINITION.themes.light);

Public API

  • ConvergenceEngine
  • Convergence
  • ConvergenceThemeStyle
  • DEFAULT_THEME_DEFINITION
  • PRESETS
  • validateThemeDefinition
  • scoreThemeAccessibility
  • defaultExportRegistry
  • createThemeCss
  • createComponentThemeAttributes
Convergence

A theming engine for React and Next applications. Built with OKLCH for perceptual uniformity and accessibility.

© 2026 Convergence UI. All rights reserved.

System Operational