Composables

Colors Design Tokens

Create and manage color design tokens with automatic, easily configurable variants, tints, and shades using the oklch color space.

Overview

The color composables help you create comprehensive color systems with minimal code. They generate color variables with automatic variants using pre-computed, gamut-aware oklch values for perceptually uniform color manipulation.

Why use color composables?

Color composables help you:

  • Create color systems quickly: Define your base colors and automatically generate tints, shades, and levels.
  • Maintain perceptual uniformity: Use oklch color space for consistent, predictable color variations.
  • Enable flexible theming: Use the theme API to re-compute all derived variants for each theme's base colors.
  • Reduce manual work: No need to manually calculate and define every color variant.

useColorDesignTokens

The useColorDesignTokens() function creates a set of color variables from a simple object of color definitions.

styleframe.config.ts
import { styleframe } from "styleframe";
import { useColorDesignTokens } from "@styleframe/theme";

const s = styleframe();

const {
    colorPrimary,
    colorSecondary,
    colorInfo,
    colorSuccess,
    colorWarning,
    colorDanger,
} = useColorDesignTokens(s, {
    primary: "#006cff",
    secondary: "#6c757d",
    info: "#17a2b8",
    success: "#28a745",
    warning: "#ffc107",
    danger: "#dc3545",
} as const);

export default s;

Each key in the object becomes a color variable with the prefix color--, and the export name is automatically converted to camelCase (e.g., primarycolorPrimary).

Pro tip: Use semantic names like primary, secondary, info, success, warning, and danger to create a consistent color system across your application.

useColorLevelDesignTokens

The useColorLevelDesignTokens() function creates a set of color variants at specific OKLCH lightness targets. Each level maps to an absolute lightness value (0–1), and chroma is automatically scaled to stay within the sRGB gamut.

styleframe.config.ts
import { styleframe } from "styleframe";
import {
    useColorDesignTokens,
    useColorLevelDesignTokens,
    colorLevelValues,
} from "@styleframe/theme";

const s = styleframe();

const { colorPrimary } = useColorDesignTokens(s, {
    primary: "#006cff",
} as const);

// Use default level values
// 50: 0.97,  -> near white
// 100: 0.93, -> very light
// 200: 0.85, -> light
// 300: 0.75, -> light-mid
// 400: 0.65, -> mid-light
// 500: 0.55, -> mid-tone
// 600: 0.45, -> mid-dark
// 700: 0.35, -> dark
// 800: 0.25, -> very dark
// 900: 0.17, -> near black
// 950: 0.12, -> darkest
const {
    colorPrimary50,
    colorPrimary100,
    colorPrimary200,
    colorPrimary300,
    colorPrimary400,
    colorPrimary500,
    colorPrimary600,
    colorPrimary700,
    colorPrimary800,
    colorPrimary900,
    colorPrimary950,
} = useColorLevelDesignTokens(s, colorPrimary);

export default s;
Common level scale: Many design systems use levels like 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950 to create a balanced color palette with predictable steps.

Creating Custom Level Variables

You can define your own custom level scale that fits your design needs:

styleframe.config.ts
import { styleframe } from "styleframe";
import { useColorDesignTokens, useColorLevelDesignTokens } from "@styleframe/theme";

const s = styleframe();

const { colorPrimary } = useColorDesignTokens(s, {
    primary: "#006cff",
} as const);

// Custom three-tone system
const { colorPrimaryLight, colorPrimaryBase, colorPrimaryDark } =
    useColorLevelDesignTokens(s, colorPrimary, {
        light: 0.75, // L = 0.75
        base: 0.55,  // L = 0.55
        dark: 0.25,  // L = 0.25
    } as const);

export default s;

Extending the Default Level Values

You can add custom levels to the default scale:

styleframe.config.ts
import { styleframe } from "styleframe";
import { useColorDesignTokens, useColorLevelDesignTokens, colorLevelValues } from "@styleframe/theme";

const s = styleframe();

const { colorPrimary } = useColorDesignTokens(s, {
    primary: "#006cff",
} as const);

// Extend with additional fine-grained levels
const colorPrimaryLevels = useColorLevelDesignTokens(s, colorPrimary, {
    ...colorLevelValues,
    150: 0.80, // Add 150 level
    250: 0.70, // Add 250 level
    350: 0.60, // Add 350 level
    450: 0.50, // Add 450 level
} as const);

export default s;

useColorShadeDesignTokens

The useColorShadeDesignTokens() function creates darker variants of a color by subtracting from the base color's lightness, with gamut-aware chroma scaling.

styleframe.config.ts
import { styleframe } from "styleframe";
import {
    useColorDesignTokens,
    useColorShadeDesignTokens,
} from "@styleframe/theme";

const s = styleframe();

const { colorPrimary } = useColorDesignTokens(s, {
    primary: "#006cff",
} as const);

// Use default shade values
// 50: 5,   -> 5% darker
// 100: 10, -> 10% darker
// 150: 15, -> 15% darker
// 200: 20, -> 20% darker
const {
    colorPrimaryShade50,
    colorPrimaryShade100,
    colorPrimaryShade150,
    colorPrimaryShade200,
} = useColorShadeDesignTokens(s, colorPrimary);

export default s;

Creating Custom Shade Variables

Define your own shade scale for precise control over darker variants:

styleframe.config.ts
import { styleframe } from "styleframe";
import { useColorDesignTokens, useColorShadeDesignTokens } from "@styleframe/theme";

const s = styleframe();

const { colorPrimary } = useColorDesignTokens(s, {
    primary: "#006cff",
} as const);

// Custom shade system for hover and active states
const { colorPrimaryHover, colorPrimaryActive, colorPrimaryPressed } =
    useColorShadeDesignTokens(s, colorPrimary, {
        hover: 8, // 8% darker for hover
        active: 12, // 12% darker for active
        pressed: 18, // 18% darker for pressed
    } as const);

export default s;

Extending the Default Shade Values

Add more shade levels to the default set:

styleframe.config.ts
import { styleframe } from "styleframe";
import {
    useColorDesignTokens,
    useColorShadeDesignTokens,
    defaultColorShadeValues,
} from "@styleframe/theme";

const s = styleframe();

const { colorPrimary } = useColorDesignTokens(s, {
    primary: "#006cff",
} as const);

// Extend with additional shade levels
const colorPrimaryShades = useColorShadeDesignTokens(s, colorPrimary, {
    ...defaultColorShadeValues,
    250: 25, // Add 250 level (25% darker)
    300: 30, // Add 300 level (30% darker)
    400: 40, // Add 400 level (40% darker)
} as const);

export default s;
Naming convention: The level names don't have to follow any specific pattern. Use whatever scale makes sense for your design system.

useColorTintDesignTokens

The useColorTintDesignTokens() function creates lighter variants of a color by adding to the base color's lightness, with gamut-aware chroma scaling.

styleframe.config.ts
import { styleframe } from "styleframe";
import {
    useColorDesignTokens,
    useColorTintDesignTokens,
    defaultColorTintValues,
} from "@styleframe/theme";

const s = styleframe();

const { colorPrimary } = useColorDesignTokens(s, {
    primary: "#006cff",
} as const);

// Use default tint values
// 50: 5,   -> 5% lighter
// 100: 10, -> 10% lighter
// 150: 15, -> 15% lighter
// 200: 20, -> 20% lighter
const {
    colorPrimaryTint50,
    colorPrimaryTint100,
    colorPrimaryTint150,
    colorPrimaryTint200,
} = useColorTintDesignTokens(s, colorPrimary, defaultColorTintValues);

export default s;

Creating Custom Tint Variables

Create your own tint scale for specific design needs:

styleframe.config.ts
import { styleframe } from "styleframe";
import { useColorDesignTokens, useColorTintDesignTokens } from "@styleframe/theme";

const s = styleframe();

const { colorPrimary } = useColorDesignTokens(s, {
    primary: "#006cff",
} as const);

// Custom tint system for background variations
const { colorPrimarySubtle, colorPrimaryLight, colorPrimaryPale } =
    useColorTintDesignTokens(s, colorPrimary, {
        subtle: 25, // 25% lighter
        light: 35, // 35% lighter
        pale: 45, // 45% lighter
    } as const);

export default s;

Extending the Default Tint Values

Add more tint levels to the default set:

styleframe.config.ts
import { styleframe } from "styleframe";
import {
    useColorDesignTokens,
    useColorTintDesignTokens,
    defaultColorTintValues,
} from "@styleframe/theme";

const s = styleframe();

const { colorPrimary } = useColorDesignTokens(s, {
    primary: "#006cff",
} as const);

// Extend with additional tint levels
const colorPrimaryTints = useColorTintDesignTokens(s, colorPrimary, {
    ...defaultColorTintValues,
    250: 25, // Add 250 level (25% lighter)
    300: 30, // Add 300 level (30% lighter)
    400: 40, // Add 400 level (40% lighter)
} as const);

export default s;

Examples

Complete Color System

Here's a complete example showing how to build a comprehensive color system:

styleframe.config.ts
import { styleframe } from "styleframe";
import type { Styleframe } from "styleframe";
import {
    useColorDesignTokens,
    useColorLevelDesignTokens,
    useColorShadeDesignTokens,
    useColorTintDesignTokens,
    colorLevelValues,
    defaultColorShadeValues,
    defaultColorTintValues,
} from "@styleframe/theme";

const s = styleframe();

// Base colors
const { colorPrimary, colorSecondary, colorSuccess, colorDanger } = useColorDesignTokens(
    s,
    {
        primary: "#006cff",
        secondary: "#6c757d",
        success: "#28a745",
        danger: "#dc3545",
    } as const,
);

// Create full scales for primary color
const colorPrimaryLevels = useColorLevelDesignTokens(
    s,
    colorPrimary,
    colorLevelValues,
);
const colorPrimaryShades = useColorShadeDesignTokens(
    s,
    colorPrimary,
    defaultColorShadeValues,
);
const colorPrimaryTints = useColorTintDesignTokens(s, colorPrimary, defaultColorTintValues);

// Create limited variants for secondary colors
const { colorSecondaryShade100 } = useColorShadeDesignTokens(s, colorSecondary, {
    100: 10,
} as const);

const { colorSuccessTint100 } = useColorTintDesignTokens(s, colorSuccess, {
    100: 10,
} as const);

const { colorDangerShade100 } = useColorShadeDesignTokens(s, colorDanger, {
    100: 10,
} as const);

export default s;

Theme-Aware Color System

Create color variables that adapt to different themes. Since variants are pre-computed at build time, the theme API re-computes all derived variants for each theme's base colors:

styleframe.config.ts
import { styleframe } from "styleframe";
import { useColorDesignTokens, useColorLevelDesignTokens } from "@styleframe/theme";

const s = styleframe();
const { theme } = s;

// Light theme colors
const { colorPrimary } = useColorDesignTokens(s, {
    primary: "#006cff",
} as const);

// Dark theme colors
theme('dark', ({ variable }) => {
    variable(colorPrimary, "#4da3ff");
})

// Create level variants that work with both themes
const colorPrimaryLevels = useColorLevelDesignTokens(s, colorPrimary, {
    100: 0.93,
    500: 0.55,
    900: 0.17,
} as const);

export default s;

Best Practices

  • Start with base colors using useColorDesignTokens() before creating variants.
  • Choose the right approach for variants: Use levels for absolute control, and shades/tints for relative adjustments.
  • Be consistent with naming: If you use 50, 100, 200 for shades, use the same scale for tints.
  • Test color contrast: Ensure your color variants meet WCAG accessibility guidelines for text and UI elements.
  • Document your color system: Explain when to use each variant and what they represent in your design language.
  • Use semantic color names: Names like primary, success, warning are more meaningful than blue, green, yellow.
  • Leverage OKLCH benefits: Take advantage of the perceptually uniform color space for consistent color variations.
Good to know: We must use as const to ensure the object is treated as a constant type. This helps TypeScript infer the return type of the composables and provides better type safety.

FAQ