Skip to content
THE PIMOLU HANDBOOK
Skip to content

Design system

Themes and presets

Separate color mode, visual character and the identity of your product.

Independent dimensions

theme accepts light, dark or system. stylePreset selects the palette and visual character. radius and density are independent overrides. Undefined radius keeps the preset's radii; undefined density keeps the comfortable default.

The current presets include default, adaptive, cartoon, glass, luxury, monochrome and neo-brutalism. Adaptive remains available. The live examples enumerate the generated export rather than maintaining a second option list.

Choose a starting point

Use defaultTheme/defaultStylePreset for an uncontrolled provider, or theme/stylePreset with their change callbacks when your application owns the state. The brandColor prop accepts a six-digit hex color and derives the primary hover and focus colors.

app/providers.tsxtsx
"use client";

import { Button, PimoluProvider } from "@pimolu/react";

export function BrandedPreview() {
  return (
    <PimoluProvider
      defaultTheme="system"
      defaultStylePreset="default"
      radius="medium"
      density="comfortable"
      brandColor="#4f46e5"
    >
      <Button>Make it yours</Button>
    </PimoluProvider>
  );
}

Read and update preferences

usePimoluTheme exposes theme, resolvedTheme, stylePreset, radius, density and brandColor, plus the corresponding setters. Read resolvedTheme when you need the actual light/dark mode.

PimoluProvider can persist preferences when persist is enabled. This website instead owns validated cookies through controlled callbacks so the server can restore an explicit preference. Choose one persistence strategy for your application.

Keep the source of truth intact

Primitive data lives in packages/design-tokens/src/tokens.json. Semantic aliases live in packages/themes/src/themes.json. Palette files and platform-neutral visual tokens live in packages/themes/src/presets and src/visual.

Default has no presets/default.json: its palette is generated from the semantic themes. Never hand-edit dist. Use build:all after editing the authorized source data and audit:themes to check integration.