Component reference
ThemeBuilder
An appearance panel whose selection belongs to the application.
Preview
Live previewOptional six-digit hex. Clear to restore the preset. Check contrast with your brand color.
Changes apply to this preview only.
Build your theme
Default · LightA small surface, every token.
Buttons, fields and badges follow the palette, radius and density you pick.
Width adapts to the available space
"use client";
import { useState } from "react";
import { Badge, ThemeBuilder } from "@pimolu/react";
const presets = [
{
id: "default",
label: "Default",
description: "Balanced indigo with soft depth.",
colors: ["#4F46E5", "#818CF8", "#E0E7FF", "#F8FAFC"],
},
{
id: "monochrome",
label: "Monochrome",
description: "Ink, paper and a single accent.",
colors: ["#171717", "#525252", "#D4D4D4", "#FAFAFA"],
},
{
id: "cartoon",
label: "Cartoon",
description: "Playful colour and confident outlines.",
colors: ["#FF5C8A", "#FFD166", "#06D6A0", "#118AB2"],
},
{
id: "glass",
label: "Glass",
description: "Translucent surfaces and cool light.",
colors: ["#38BDF8", "#A5B4FC", "#E0F2FE", "#F8FAFC"],
},
{
id: "luxury",
label: "Luxury",
description: "Warm neutrals, gold and quiet contrast.",
colors: ["#926A35", "#E8CF9B", "#241F1A", "#FAF6EF"],
},
{
id: "neo-brutalism",
label: "Neo-brutalism",
description: "Hard edges, offset shadows, loud accents.",
colors: ["#FFE600", "#FF5C8A", "#171717", "#FFFFFF"],
},
];
function ControlledBuilder() {
const [preset, setPreset] = useState("default");
const [theme, setTheme] = useState<"light" | "dark">("light");
const [brandColor, setBrandColor] = useState("#5B55E7");
const [radius, setRadius] = useState("medium");
const [density, setDensity] = useState("comfortable");
return (
<div className="grid gap-5 min-w-0">
<div className="flex flex-wrap items-center gap-3 min-w-0">
<Badge variant="primary" appearance="soft">
{preset}
</Badge>
<Badge variant="neutral" appearance="soft">
{theme}
</Badge>
<Badge variant="neutral" appearance="soft">
radius: {radius}
</Badge>
<Badge variant="neutral" appearance="soft">
density: {density}
</Badge>
<span className="text-sm text-muted leading-relaxed">{brandColor}</span>
</div>
<ThemeBuilder
title="Build your theme"
presets={presets}
value={preset}
onValueChange={setPreset}
theme={theme}
onThemeChange={setTheme}
brandColor={brandColor}
onBrandColorChange={setBrandColor}
radius={radius}
onRadiusChange={setRadius}
density={density}
onDensityChange={setDensity}
/>
</div>
);
}
export function DemoExample() {
return (<ControlledBuilder />);
}More examples
Different configurations and compositions using the real Pimolu API. Each preview runs independently and follows the site appearance.
Custom preview
Supply any ReactNode as preview. It renders inside the themed preview scope, so Pimolu components pick up the selected preset, colour mode, radius, density and brand colour.
Integration
ThemeBuilder stays a controlled view or owns its fallback state. Wire the same values into PimoluProvider when the choice must reach the rest of the application.
Example: documentation appearance panel
An uncontrolled builder is useful for a quick demo; pass defaultValue to start on a specific preset.
Usage
ThemeBuilder reports a choice; connect it to your application's appearance state deliberately.
API reference
Generated from the public TypeScript declarations. Native HTML attributes are inherited where the component extends them; this reference includes Pimolu props and selected common native attributes.
PimoluThemeBuilderPreset
Type source| Name | Type | Default | Description |
|---|---|---|---|
idRequired | string | — | Stable identifier passed to `onValueChange`. |
labelRequired | string | — | Visible preset name. |
description | string | undefined | — | Optional supporting copy under the name. |
colors | readonly string[] | undefined | — | Swatches shown on the card, for example a palette preview. |
idRequiredstringNo default extracted.
Stable identifier passed to `onValueChange`.
labelRequiredstringNo default extracted.
Visible preset name.
descriptionstring | undefinedNo default extracted.
Optional supporting copy under the name.
colorsreadonly string[] | undefinedNo default extracted.
Swatches shown on the card, for example a palette preview.
PimoluThemeBuilderProps
Type source| Name | Type | Default | Description |
|---|---|---|---|
presetsRequired | readonly PimoluThemeBuilderPreset[] | — | Preset cards, in display order. |
value | string | undefined | — | Controlled preset id. |
defaultValue | string | undefined | the first preset | Initial preset id when uncontrolled. Defaults to the first preset. |
onValueChange | ((presetId: string) => void) | undefined | — | Called with the next preset id. |
theme | PimoluThemeBuilderTheme | undefined | "light" when uncontrolled | Controlled colour mode. Defaults to "light" when uncontrolled. |
onThemeChange | ((theme: PimoluThemeBuilderTheme) => void) | undefined | — | Called with the next colour mode. |
brandColor | string | undefined | #5B55E7 when uncontrolled | Controlled brand colour. Defaults to #5B55E7 when uncontrolled. |
onBrandColorChange | ((color: string) => void) | undefined | — | Called with the colour emitted by the native colour input. |
radius | string | undefined | "medium" | Controlled radius dimension. Defaults to "medium". |
onRadiusChange | ((radius: string) => void) | undefined | — | Called with the next radius dimension. |
density | string | undefined | "comfortable" | Controlled density dimension. Defaults to "comfortable". |
onDensityChange | ((density: string) => void) | undefined | — | Called with the next density dimension. |
preview | ReactNode | — | Custom preview surface. A small component sample is rendered without it. |
title | string | undefined | — | Optional heading for the builder. |
className | string | undefined | — | Standard React/HTML attribute. |
style | CSSProperties | undefined | — | Standard React/HTML attribute. |
aria-label | string | undefined | — | Defines a string value that labels the current element. |
children | ReactNode | — | Standard React/HTML attribute. |
onClick | MouseEventHandler<HTMLDivElement> | undefined | — | Standard React/HTML attribute. |
presetsRequiredreadonly PimoluThemeBuilderPreset[]No default extracted.
Preset cards, in display order.
valuestring | undefinedNo default extracted.
Controlled preset id.
defaultValuestring | undefinedDefault: the first preset
Initial preset id when uncontrolled. Defaults to the first preset.
onValueChange((presetId: string) => void) | undefinedNo default extracted.
Called with the next preset id.
themePimoluThemeBuilderTheme | undefinedDefault: "light" when uncontrolled
Controlled colour mode. Defaults to "light" when uncontrolled.
onThemeChange((theme: PimoluThemeBuilderTheme) => void) | undefinedNo default extracted.
Called with the next colour mode.
brandColorstring | undefinedDefault: #5B55E7 when uncontrolled
Controlled brand colour. Defaults to #5B55E7 when uncontrolled.
onBrandColorChange((color: string) => void) | undefinedNo default extracted.
Called with the colour emitted by the native colour input.
radiusstring | undefinedDefault: "medium"
Controlled radius dimension. Defaults to "medium".
onRadiusChange((radius: string) => void) | undefinedNo default extracted.
Called with the next radius dimension.
densitystring | undefinedDefault: "comfortable"
Controlled density dimension. Defaults to "comfortable".
onDensityChange((density: string) => void) | undefinedNo default extracted.
Called with the next density dimension.
previewReactNodeNo default extracted.
Custom preview surface. A small component sample is rendered without it.
titlestring | undefinedNo default extracted.
Optional heading for the builder.
classNamestring | undefinedNo default extracted.
Standard React/HTML attribute.
styleCSSProperties | undefinedNo default extracted.
Standard React/HTML attribute.
aria-labelstring | undefinedNo default extracted.
Defines a string value that labels the current element.
childrenReactNodeNo default extracted.
Standard React/HTML attribute.
onClickMouseEventHandler<HTMLDivElement> | undefinedNo default extracted.
Standard React/HTML attribute.
Accessibility
- Keep preset names visible, and check the contrast of the resulting theme.