Skip to content

Theme

cfasim-ui uses CSS custom properties for all design tokens.

The simplest way to load all cfasim-ui styles — design tokens, reset, utilities, and the CSS for every @cfasim-ui/components and @cfasim-ui/charts component — is a single import in your app entry:

ts
// src/main.ts
import "@cfasim-ui/theme/all";

This pulls in @cfasim-ui/theme, @cfasim-ui/components/style.css, and @cfasim-ui/charts/style.css together. Use it whenever you're consuming the prebuilt packages from npm — without it, components and charts will render unstyled because their CSS is shipped as a separate file alongside their compiled JS.

Granular imports

If you want only the design tokens and base styles (no component or chart CSS), import the theme entry directly:

ts
import "@cfasim-ui/theme";

Or cherry-pick individual layers:

ts
import "@cfasim-ui/theme/base.css";
import "@cfasim-ui/theme/theme.css";
import "@cfasim-ui/theme/utilities.css";

Variables

css
:root {
  color-scheme: light dark;
}

:root.light {
  color-scheme: light;
}

:root.dark {
  color-scheme: dark;
}

:root {
  /* Primary */
  --color-primary: light-dark(#0066ff, #4d94ff);
  --color-primary-hover: light-dark(#0052cc, #66a3ff);
  --color-primary-active: light-dark(#0047b3, #3385ff);
  --color-text-on-primary: #ffffff;

  /* Backgrounds */
  --color-bg-0: light-dark(#ffffff, #1a1a1a);
  --color-bg-1: light-dark(#f8f9fa, #2d2d2d);
  --color-bg-2: light-dark(#e9ecef, #3d3d3d);
  --color-bg-3: light-dark(#dee2e6, #4d4d4d);

  /* Text */
  --color-text: light-dark(#212529, #f8f9fa);
  --color-text-secondary: light-dark(#495057, #adb5bd);
  --color-text-tertiary: light-dark(#adb5bd, #6c757d);
  --color-text-disabled: light-dark(#ced4da, #495057);

  /* Links */
  --color-link: var(--color-primary);

  /* Borders */
  --color-border: light-dark(#dee2e6, #3a3f44);
  --color-border-header: light-dark(#c4c9ce, #555d64);
  --color-border-hover: light-dark(#adb5bd, #555d64);
  --color-border-focus: var(--color-primary);

  /* Status */
  --color-error: light-dark(#dc3545, #ff6b6b);
  --color-success: light-dark(#28a745, #40c057);
  --color-warning: light-dark(#ffc107, #ffd43b);

  /* Typography */
  --font-family:
    -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial,
    sans-serif;
  --font-family-heading: var(--font-family);
  --font-weight-heading: bold;
  --font-family-mono: "Consolas", "Monaco", "Courier New", monospace;
  --font-size-xs: 0.75rem;
  --font-size-sm: 0.875rem;
  --font-size-md: 1rem;
  --font-size-lg: 1.25rem;
  --font-size-xl: 1.5rem;
  --font-size-2xl: 2rem;
  --line-height-tight: 1.25;
  --line-height-normal: 1.5;

  /* Spacing (rem — consistent regardless of font-size context) */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-12: 3rem;
  --space-20: 5rem;

  /* Radius */
  --radius-sm: 0.25rem;
  --radius-md: 0.375rem;
  --radius-lg: 0.5rem;
  --radius-full: 9999px;

  /* Shadows */
  --shadow-sm: light-dark(
    0 1px 2px 0 rgba(0, 0, 0, 0.05),
    0 1px 2px 0 rgba(0, 0, 0, 0.3)
  );
  --shadow-md: light-dark(
    0 4px 6px -1px rgba(0, 0, 0, 0.1),
    0 4px 6px -1px rgba(0, 0, 0, 0.4)
  );
  --shadow-focus: light-dark(
    0 0 0 3px rgba(0, 102, 255, 0.2),
    0 0 0 3px rgba(77, 148, 255, 0.3)
  );

  /* Transitions */
  --transition-fast: 150ms ease-in-out;
  --transition-normal: 250ms ease-in-out;

  /* Box variants */
  --color-box-info-bg: light-dark(#e6eefa, #1a2a45);
  --color-box-info-text: light-dark(#1a3a6b, #8fb8f0);
  --color-box-success-bg: light-dark(#ecfdf5, #1a3d2a);
  --color-box-success-text: light-dark(#065f46, #a8f0c8);
  --color-box-warning-bg: light-dark(#fef6e7, #3d3210);
  --color-box-warning-text: light-dark(#7a5d0e, #f5d882);
  --color-box-error-bg: light-dark(#fef2f2, #3d1a1a);
  --color-box-error-text: light-dark(#991b1b, #f0a8a8);
  --color-baseline-bg: light-dark(#fef3e6, #3d2a10);
  --color-baseline-text: light-dark(#7a3d00, #f5c882);

  /* Component sizes (em — scales with font-size context) */
  --input-height: 2.5em;
  --button-height: 2.5em;
  --sidebar-width: 400px;
  --toggle-size: 2.5rem;
}

Custom themes

To create a custom theme, add a CSS file that overrides variables under a [data-theme="your-theme"] selector. You only need to include the variables you want to change — everything else falls back to the defaults. Use light-dark() for any values that should differ between light and dark mode.

Here's the built-in cdc theme as an example:

css
[data-theme="cdc"] {
  --font-family:
    "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
    Arial, sans-serif;
  --font-family-heading:
    "Poppins", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
    Arial, sans-serif;
  --font-weight-heading: 200;
  --font-size-md: 1.125rem;
  --font-size-2xl: 2.625rem;
  --color-bg-0: light-dark(#ffffff, #0f1e21);
  --color-bg-1: light-dark(#f4fbfc, #162a2e);
  --color-bg-2: light-dark(#e9f5f8, #1e373c);
  --color-bg-3: light-dark(#dff2f6, #264349);
  --color-primary: light-dark(#007a99, #33b5d6);
  --color-primary-hover: light-dark(#006680, #4dc4e0);
  --color-primary-active: light-dark(#005c73, #1fa8cc);
  --color-link: light-dark(#005ea2, #73b3e7);
  --color-border: light-dark(#c5e4ec, #264349);
  --color-border-hover: light-dark(#a0d4e0, #3a5d64);
  --color-border-focus: var(--color-primary);
}

To activate a theme, set the data-theme attribute on the root element:

html
<html data-theme="your-theme"></html>