Theming
Global reskinning uses CSS custom properties. Import the base stylesheet once, override variables on :root or a scoped wrapper, and optionally use DoodleUIProvider for React-level defaults.
Quick start
import "doodleui-react/styles.css";
The library does not load Google Fonts for you. Set --doodle-ui-font-family (or --doodle-ui-font via SketchSeedProvider) after you add a font yourself.
Precedence
For sketch parameters (roughness, strokeWidth, bowing, sketchColor, fillStyle):
- Per-component prop
DoodleUIProviderprop (also sets scoped CSS vars)- CSS custom property on an ancestor
- Built-in constant in the package
CSS variable reference
| Variable | Light default | Dark default | Purpose |
| --- | --- | --- | --- |
| --doodle-ui-roughness | 1.5 | 1.5 | rough.js sketchiness |
| --doodle-ui-bowing | 1 | 1 | Line bowing |
| --doodle-ui-stroke-width | 1.75 | 1.75 | Stroke width (px) |
| --doodle-ui-stroke-color | #1f1d1a | #f3f4f6 | Default ink / strokes |
| --doodle-ui-fill-style | hachure | hachure | Fill pattern when shapes have fill |
| --doodle-ui-font-family | "Patrick Hand", cursive | same | Handwriting stack (no font loaded automatically) |
| --doodle-ui-bg-color | #f7f6f2 | #131923 | Paper / surfaces |
| --doodle-ui-text-color | #1f1d1a | #f3f4f6 | Body text |
| --doodle-ui-color-info | #1d4e89 | #60a5fa | Alert / status info |
| --doodle-ui-color-warning | #c47b17 | #fbbf24 | Warning |
| --doodle-ui-color-error | #c0392b | #f87171 | Error |
| --doodle-ui-color-success | #2d6a4f | #34d399 | Success |
Contrast (default palettes)
Measured contrast ratios for shipped defaults (WCAG AA requires ≥ 4.5:1 for normal text and ≥ 3:1 for non-text strokes):
- Light: stroke/text
#1f1d1aon#f7f6f2— ~15.6:1 - Dark: stroke/text
#f3f4f6on#131923— ~16.0:1
Thin hand-drawn strokes can look lighter than solid borders; test your own --doodle-ui-stroke-width and colors if you push toward pastel inks.
Dark mode
With styles.css imported:
- Automatic:
@media (prefers-color-scheme: dark)updates tokens when you do not force light. - Explicit:
data-theme="dark"or classdarkonhtmlor any ancestor. - Force light on a dark OS:
data-theme="light"or classlight(wins over the media query). - React subtree:
<DoodleUIProvider theme="dark">setsdata-themeand palette resolution for descendants.
<html data-theme="dark">
<!-- or -->
<html class="dark">
<DoodleUIProvider theme="system">
{/* follows OS + html attributes */}
</DoodleUIProvider>
Font pairings
Load fonts yourself, then point --doodle-ui-font-family (or --doodle-ui-font for shuffle palettes) at the family.
Patrick Hand (default body)
<link
href="https://fonts.googleapis.com/css2?family=Patrick+Hand&display=swap"
rel="stylesheet"
/>
// app/layout.tsx (Next.js)
import { Patrick_Hand } from "next/font/google";
const patrick = Patrick_Hand({ subsets: ["latin"], weight: "400", variable: "--font-patrick" });
// CSS: --doodle-ui-font-family: var(--font-patrick), cursive;
Kalam (single-font stack)
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@400;700&display=swap"
rel="stylesheet"
/>
:root {
--doodle-ui-font-family: "Kalam", cursive;
}
Architects Daughter + Patrick Hand (headings + body)
<link
href="https://fonts.googleapis.com/css2?family=Architects+Daughter&family=Patrick+Hand&display=swap"
rel="stylesheet"
/>
:root {
--doodle-ui-font-family: "Patrick Hand", cursive;
}
h1, h2, h3 {
font-family: "Architects Daughter", cursive;
}
Caveat (accents / headings only)
Caveat is expressive but less readable at small body sizes — use for titles or badges.
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400;600&display=swap"
rel="stylesheet"
/>
Provider + CSS together
Provider sketch props mirror onto scoped --doodle-ui-* variables. Use CSS for site-wide tokens and the provider when you need a subtree override:
import "doodleui-react/styles.css";
import { DoodleUIProvider, Button } from "doodleui-react";
export function App() {
return (
<DoodleUIProvider roughness={2.2} theme="light">
<Button>Heavier global sketch</Button>
</DoodleUIProvider>
);
}
Try the theme generator for copy-paste :root blocks that match these names.