Presets

All 50+ built-in color presets and how to use the preset system.

Each preset defines a complete set of CSS variables for both light and dark mode — covering background, foreground, primary, secondary, muted, accent, destructive, border, input, ring, sidebar colors, chart colors, and optional typography and shadow tokens.

How presets work

When a preset is active, PresetProvider sets data-preset="<id>" on document.documentElement. The library's CSS uses @variant preset-light and @variant preset-dark directives (from custom-variants.css) which expand into the full selector set:

/* Example: how violet-bloom is defined internally */
[data-preset="violet-bloom"] {
  @variant preset-light {
    --primary: #7033ff;
    --background: #fdfdfd;
    /* ... full light mode token set */
  }

  @variant preset-dark {
    --primary: #8c5cff;
    --background: #1a1b1e;
    /* ... full dark mode token set */
  }
}

The preset-light variant applies variables when the element (or its ancestor) is in light mode — and also to any .scheme-light subtree. The preset-dark variant applies when in dark mode — and also to any .scheme-dark subtree. This means presets and dark/light mode are fully independent — every preset works in both modes.

scheme-light / scheme-dark

Scope light or dark mode to a specific subtree regardless of the global theme:

{/* Always renders in light mode, even when the app is dark */}
<div className="scheme-light">
  <MyCard />
</div>

{/* Always renders in dark mode, even when the app is light */}
<div className="scheme-dark">
  <MyCard />
</div>

Using a preset

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

const { setPreset } = usePreset();

setPreset("violet-bloom");

Listing all presets

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

// Array of [id, label] tuples
PRESETS.forEach(([key, label]) => {
  console.log(key, label);
});

Available presets

IDLabel
nuteralNuteral
nuteral-accentNuteral (Accent)
codecanonCodeCanon
anewAnew
redRed
roseRose
orangeOrange
greenGreen
blueBlue
yellowYellow
violetViolet
modern-minimalModern Minimal
violet-bloomViolet Bloom
t3-chatT3 Chat
twitterTwitter
mocha-mousseMocha Mousse
bubblegumBubblegum
amethyst-hazeAmethyst Haze
notebookNotebook
doom-64Doom 64
catppuccinCatppuccin
graphiteGraphite
perpetuityPerpetuity
kodama-groveKodama Grove
cosmic-nightCosmic Night
tangerineTangerine
quantum-roseQuantum Rose
natureNature
bold-techBold Tech
elegant-luxuryElegant Luxury
amber-minimalAmber Minimal
supabaseSupabase
neo-brutalismNeo Brutalism
solar-duskSolar Dusk
claymorphismClaymorphism
cyberpunkCyberpunk
pastel-dreamsPastel Dreams
clean-slateClean Slate
caffeineCaffeine
ocean-breezeOcean Breeze
retro-arcadeRetro Arcade
midnight-bloomMidnight Bloom
candylandCandyland
northern-lightsNorthern Lights
vintage-paperVintage Paper
sunset-horizonSunset Horizon
starry-nightStarry Night
claudeClaude
vercelVercel
darkmatterDarkmatter
monoMono
soft-popSoft Pop
sage-gardenSage Garden

CSS tokens per preset

Each preset can define any of the following tokens. Typography and shadow tokens are optional — presets that omit them fall back to your app's base values.

TokenDescription
--background / --foregroundPage background and text
--card / --card-foregroundCard surface and text
--popover / --popover-foregroundPopover surface and text
--primary / --primary-foregroundPrimary action color
--secondary / --secondary-foregroundSecondary surface
--muted / --muted-foregroundSubtle background and muted text
--accent / --accent-foregroundHighlight / hover surface
--destructive / --destructive-foregroundDestructive / error color
--border / --input / --ringBorders, inputs, focus rings
--sidebar / --sidebar-foreground / …Sidebar-specific tokens
--chart-1--chart-5Data visualization palette
--radiusBase border radius
--font-sans / --font-serif / --font-mono(optional) Preset-specific fonts
--letter-spacing / --spacing(optional) Typographic rhythm
--shadow-color / --shadow-opacity / …(optional) Shadow appearance

Custom presets

Write your own preset CSS using the @variant preset-light and @variant preset-dark directives from custom-variants.css. Import this file in your CSS entry point alongside the library styles:

my-brand-preset.css
@import "@codecanon/next-presets/custom-variants.css";

:root, /* <-- add root if you want the preset to be default, otherwise remove */
[data-preset="my-brand"] {
  @variant preset-light {
    --background: oklch(0.99 0.005 220);
    --foreground: oklch(0.1 0 0);
    --primary: oklch(0.45 0.2 220);
    --primary-foreground: oklch(0.98 0 0);
    --secondary: oklch(0.93 0.02 220);
    --secondary-foreground: oklch(0.2 0 0);
    --muted: oklch(0.95 0.01 220);
    --muted-foreground: oklch(0.5 0 0);
    --accent: oklch(0.9 0.04 220);
    --accent-foreground: oklch(0.15 0 0);
    --destructive: oklch(0.577 0.245 27.325);
    --border: oklch(0.88 0.01 220);
    --input: oklch(0.88 0.01 220);
    --ring: oklch(0.55 0.18 220);
    --radius: 0.5rem;
    /* sidebar, chart, font tokens... */
  }

  @variant preset-dark {
    --background: oklch(0.1 0.005 220);
    --foreground: oklch(0.97 0 0);
    --primary: oklch(0.65 0.18 220);
    /* ... dark mode values */
  }
}
globals.css
@import "./my-brand-preset.css";
@import "@codecanon/next-presets/styles.css";

Then register it in the picker and activate it:

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

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

// In your picker:
<PresetPickerContent presets={MY_PRESETS} />

// Programmatically:
const { setPreset } = usePreset();
setPreset("my-brand");

On this page