Preset picker

PresetPicker, PresetPickerSheet, PresetPickerContent, and related components.

The preset picker is a composable slide-out sheet UI that lets users search, preview, and select from all available presets. It is built from collaborating components that share state through a React context.

PresetPicker

Context provider that wires together the picker components. Wrap all picker sub-components inside it.

import {
  PresetPicker,
  PresetPickerSheet,
  PresetPickerContent,
  PresetPickerToggleButton,
  PresetPickerThemeToggleGroup,
} from "@codecanon/next-presets";

<PresetPicker>
  <PresetPickerToggleButton />
  <PresetPickerSheet>
    <PresetPickerThemeToggleGroup />
    <PresetPickerContent />
  </PresetPickerSheet>
</PresetPicker>

Props

PropTypeDescription
childrenReactNodeRequired. Picker sub-components.

usePresetPicker(caller?)

Hook to access the picker's open/close state from any component inside a <PresetPicker>. Useful for building custom triggers.

import { usePresetPicker } from "@codecanon/next-presets";

const { open, setOpen, toggleOpen } = usePresetPicker();

Return values

PropertyTypeDescription
openbooleanWhether the picker sheet is open.
setOpen(value: boolean) => voidDirectly set open state.
toggleOpen() => voidToggle open/closed.

Throws an error if called outside of a <PresetPicker>.


PresetPickerSheet

Renders the slide-out sheet container. Animates in from the left. Non-modal — the rest of the app stays interactive while open.

<PresetPicker>
  <PresetPickerSheet>
    {/* content here */}
  </PresetPickerSheet>
</PresetPicker>

Extends the Sheet component props. The open and onOpenChange values are wired automatically from PresetPicker context. Pointer events outside the sheet do not close it.


PresetPickerContent

The main body of the picker — renders a search field and the full preset list with live previews.

<PresetPickerContent
  showDock={false}
  card={PresetPreviewCard}
  presets={PRESETS}
/>

Props

PropTypeDefaultDescription
showDockbooleanfalseRender previews in a compact dock style.
cardtypeof PresetPreviewCardPresetPreviewCardCustom preview card component. Must accept the same props.
presetsreadonly PresetTuple[]PRESETSThe list of presets to display. Spread to extend with custom entries.

Extending with custom presets

Pass your own presets alongside the built-ins using the presets prop. Each entry is a [id, label] tuple — the id must match the data-preset value in your CSS:

import { PRESETS, PresetPickerContent } from "@codecanon/next-presets";

const MY_PRESETS = [
  ["my-brand", "My Brand"],
  ...PRESETS,
] as const;

<PresetPickerContent presets={MY_PRESETS} />

Keyboard navigation

KeyAction
/ Move through the preset list
EnterApply the highlighted preset
TypeFilters the preset list by name

PresetPickerThemeToggleGroup

Three-button toggle for switching between light, dark, and system modes. Place it inside <PresetPickerSheet> or anywhere else inside a <PresetPicker>.

import { PresetPickerThemeToggleGroup } from "@codecanon/next-presets";

<PresetPickerThemeToggleGroup />

Accepts all React.ComponentProps<"div"> props. Internally calls useTheme() to read and set the current theme.


PresetPickerToggleButton

A ready-made button that opens and closes the preset picker sheet. Use it as a drop-in trigger without writing a custom usePresetPicker wrapper.

import {
  PresetPicker,
  PresetPickerSheet,
  PresetPickerContent,
  PresetPickerThemeToggleGroup,
  PresetPickerToggleButton,
} from "@codecanon/next-presets";

<PresetPicker>
  <PresetPickerToggleButton>🎨 Themes</PresetPickerToggleButton>
  <PresetPickerSheet>
    <PresetPickerThemeToggleGroup />
    <PresetPickerContent />
  </PresetPickerSheet>
</PresetPicker>

Accepts all Button props including radix-ui asChild. The onClick handler is wired to toggleOpen automatically.


PresetPreviewCard

A mock app UI that renders in the colors of any preset — useful for previewing themes before applying them.

import { PresetPreviewCard } from "@codecanon/next-presets";

<PresetPreviewCard
  preset="violet-bloom"
  label="Violet Bloom"
  active={false}
  highlighted={false}
  variant='default'
/>

Props

PropTypeDefaultDescription
presetstringAny preset ID (built-in or custom) whose colors to render.
labelstringAuto-generated from presetDisplay name shown on the card.
activebooleanfalseHighlights the card with a primary-color ring (currently applied preset).
highlightedbooleanfalseHighlights the card with a secondary ring (keyboard focus).
variant"default" | "dock""default"Sidebar layout or compact dock layout
refReact.Ref<HTMLDivElement>Forwarded to the root element.

The card renders a miniature app chrome — sidebar, header, content cards, and footer — using the preset's CSS variables. This gives an accurate preview of how the preset will look in a real UI.

Custom preview card

Pass a custom component to PresetPickerContent via the card prop. It receives the same props as PresetPreviewCard:

import type { PresetPreviewCard } from "@codecanon/next-presets";

type PreviewCardProps = React.ComponentProps<typeof PresetPreviewCard>;

function MyPreviewCard({ preset, label, active }: PreviewCardProps) {
  return (
    <div data-preset={preset} style={{ border: active ? "2px solid blue" : "none" }}>
      {label}
    </div>
  );
}

<PresetPickerContent card={MyPreviewCard} />

You can also get the data from the usePreset hook.

import { usePreset, PRESET_BY_NAME, type PresetPreviewCard } from "@codecanon/next-presets";

type PreviewCardProps = React.ComponentProps<typeof PresetPreviewCard>;

function MyPreviewCard({ preset }: PreviewCardProps) {
  const { preset: activePreset } = usePreset()

  const active = preset === activePrest
  const label = PRESET_BY_NAME[preset]

  return (
    <div data-preset={preset} style={{ border: active ? "2px solid blue" : "none" }}>
      {label}
    </div>
  );
}

<PresetPickerContent card={MyPreviewCard} />

Full example

import {
  PresetPicker,
  PresetPickerSheet,
  PresetPickerContent,
  PresetPickerThemeToggleGroup,
  usePresetPicker,
} from "@codecanon/next-presets";

function TriggerButton() {
  const { toggleOpen } = usePresetPicker();
  return (
    <button onClick={toggleOpen}>
      🎨 Themes
    </button>
  );
}

export function ThemePicker() {
  return (
    <PresetPicker>
      <TriggerButton />
      <PresetPickerSheet>
        <PresetPickerThemeToggleGroup />
        <PresetPickerContent />
      </PresetPickerSheet>
    </PresetPicker>
  );
}

On this page