Customize
Themes
Install a ready-made look with one command. A theme is one JSON file, so there is nothing else to wire up.
A theme is one JSON file. It carries colors, spacing, the shape of the progress counter, the arrow, the spotlight and the scrim — everything about how a tour looks, and nothing about what it does.
Because it is only data, installing one writes one file into your project. There is no package to add at runtime, no build step, and nothing to keep in sync with your framework.
Install
Section titled “Install”-
Add a theme. Pick one from the gallery below:
Terminal window npx @docentjs/cli theme add ledgerThis writes
docent-theme.json, after checking it. Use--outto put it somewhere else, anddocent theme listto see every theme. -
Hand it to the renderer. One line, wherever you already set up Docent:
import { createTour } from '@docentjs/dom'import theme from './docent-theme.json'createTour(tour, { renderer: { template: theme } })import { DocentProvider } from '@docentjs/react'import theme from './docent-theme.json'<DocentProvider renderer={{ template: theme }}><App /></DocentProvider>import { provideDocentDefaults } from '@docentjs/vue'import theme from './docent-theme.json'provideDocentDefaults({ renderer: { template: theme } })import { useDocent } from '@docentjs/svelte'import theme from './docent-theme.json'const docent = useDocent({ tours, renderer: { template: theme } }) -
That is it. Every tour in the app now uses the theme.
From anywhere
Section titled “From anywhere”A theme is just a URL away, so anyone can publish one. The CLI checks it before writing anything, and refuses a file that is not a valid theme:
npx @docentjs/cli theme add https://example.com/my-theme.jsonThe same check is available in code as validateTheme(theme) from
@docentjs/dom/validate, for themes you load at runtime.
Prefer not to use the CLI? Copy the JSON from any card below into your project instead. It is the same file.
Make it yours
Section titled “Make it yours”Open the file and change it. Every field is documented in theming and arrows and spotlight; the ones a theme uses most:
| Field | What it does |
|---|---|
theme |
colors, radius, width, padding, font, shadow, scrim |
eyebrow |
a small line above every title. {tour} becomes the tour’s name |
progress |
meter, count, ticks, dots or none |
arrow |
caret, none, or one of the nineteen drawn connectors |
spotlight |
padding, radius, shape and ring around the target |
overlay |
dim, blur, vignette or none |
mobile |
on phones: layout (auto, float, dock) and card (stories, compact, classic); a tour’s own mobile wins |
css |
anything the fields above do not cover, scoped to the popover |
A tour can override any of it, so one tour can go its own way without a second theme:
{ "options": { "template": "ledger", "progress": "dots", "eyebrow": "New in 2.4" } }The gallery
Section titled “The gallery”Press Preview to run a real tour with that theme. These are live — the card is the library rendering, not a picture of it.
| Style | Themes |
|---|---|
| Quiet and modern | quiet, slate, ledger |
| Classy | atelier (ivory, Didone serif, a framed card), velvet (plum and gold), broadsheet |
| Glassmorphism | frost (light frosted glass), aurora (dark glass with a violet-to-ice sheen) |
| Neumorphism | pebble (soft light clay), graphite (dark clay with a mint accent) |
| Brutalism | poster (thick ink borders, hard shadows, loud yellow), concrete (raw, monospace, all square) |
| Dark and vivid | nocturne, console, neon, carbon (high contrast) |
| Playful | bloom |
npx @docentjs/cli theme add atelieratelier.json
{
"name": "Atelier",
"theme": {
"background": "oklch(97.6% 0.012 85)",
"foreground": "oklch(22% 0.015 250)",
"muted": "oklch(50% 0.015 250)",
"accent": "oklch(28% 0.05 255)",
"accentForeground": "oklch(97.6% 0.012 85)",
"connector": "oklch(97% 0.012 85)",
"ring": "oklch(97% 0.012 85)",
"radius": 2,
"width": 360,
"padding": "24px 24px 18px",
"shadow": "0 1px 2px oklch(22% 0.02 60 / 0.08), 0 30px 60px -30px oklch(22% 0.03 60 / 0.55)",
"duration": 240
},
"eyebrow": "{tour}",
"progress": "count",
"count": "{current} of {total}",
"arrow": "double",
"spotlight": {
"padding": 10,
"radius": 2,
"animate": true
},
"overlay": {
"color": "oklch(26% 0.02 60)",
"opacity": 0.48
},
"css": ".popover, .popover.sheet { box-shadow: 0 0 0 1px oklch(22% 0.015 250 / 0.12), inset 0 0 0 6px var(--docent-bg), inset 0 0 0 7px oklch(22% 0.015 250 / 0.14), var(--docent-shadow); } .title { font-family: Didot, 'Bodoni 72', 'Iowan Old Style', ui-serif, Georgia, serif; font-size: 22px; font-weight: 400; line-height: 1.2; letter-spacing: -0.01em; } .eyebrow, .count { font-family: 'Iowan Old Style', ui-serif, Georgia, serif; font-style: italic; text-transform: none; letter-spacing: 0.01em; font-size: 13px; } .footer { margin-top: 22px; } .button { border-radius: 0; font-size: 11.5px; letter-spacing: 0.1em; text-transform: uppercase; } .button.primary { padding-inline: 18px; }"
}npx @docentjs/cli theme add auroraaurora.json
{
"name": "Aurora",
"theme": {
"background": "oklch(24% 0.035 285 / 0.58)",
"foreground": "oklch(97% 0.008 285)",
"muted": "oklch(80% 0.03 285)",
"accent": "oklch(80% 0.12 300)",
"accentForeground": "oklch(20% 0.04 285)",
"connector": "oklch(87% 0.09 225)",
"ring": "oklch(87% 0.09 225)",
"radius": 18,
"width": 344,
"padding": "20px 20px 16px",
"shadow": "0 30px 70px -28px oklch(8% 0.05 285 / 0.9)",
"duration": 260
},
"progress": "meter",
"arrow": "s-curve",
"spotlight": {
"padding": 8,
"radius": 12,
"ring": "glow",
"animate": true
},
"overlay": {
"style": "blur",
"blur": 6,
"color": "oklch(16% 0.06 280)",
"opacity": 0.5
},
"css": ".popover { background-image: linear-gradient(140deg, oklch(70% 0.14 300 / 0.18), transparent 45%, oklch(72% 0.12 220 / 0.14)); -webkit-backdrop-filter: blur(26px) saturate(1.7); backdrop-filter: blur(26px) saturate(1.7); } .popover, .popover.sheet { box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.16), 0 0 0 1px oklch(100% 0 0 / 0.12), var(--docent-shadow); } .popover .arrow { border-color: oklch(100% 0 0 / 0.12) !important; -webkit-backdrop-filter: blur(26px); backdrop-filter: blur(26px); } .button { border-radius: 999px; } .button.primary, .button.primary:hover { padding-inline: 16px; background: linear-gradient(120deg, oklch(80% 0.12 300), oklch(85% 0.1 220)); } .button.primary:hover { filter: brightness(1.07); } .meter { width: 40px; background: linear-gradient(90deg, oklch(80% 0.12 300), oklch(85% 0.1 220)) 0 0 / calc(var(--docent-step) / var(--docent-steps) * 100%) 100% no-repeat, oklch(100% 0 0 / 0.14); }"
}npx @docentjs/cli theme add bloombloom.json
{
"name": "Bloom",
"theme": {
"background": "oklch(99% 0.008 330)",
"foreground": "oklch(26% 0.05 330)",
"muted": "oklch(58% 0.04 330)",
"accent": "oklch(58% 0.21 350)",
"accentForeground": "oklch(99% 0.008 350)",
"connector": "oklch(58% 0.21 350)",
"ring": "oklch(78% 0.16 350)",
"radius": 20,
"width": 336,
"padding": "20px 22px 16px",
"shadow": "0 2px 4px oklch(40% 0.12 330 / 0.1), 0 28px 60px -28px oklch(40% 0.14 330 / 0.6)",
"duration": 260
},
"progress": "dots",
"arrow": "squiggle",
"spotlight": {
"padding": 10,
"radius": 16,
"ring": "pulse",
"animate": true
},
"overlay": {
"color": "oklch(30% 0.09 330)",
"opacity": 0.38
},
"css": ".title { font-size: 19px; letter-spacing: -0.015em; } .button { border-radius: 999px; padding-inline: 14px; }"
}npx @docentjs/cli theme add broadsheetbroadsheet.json
{
"name": "Broadsheet",
"theme": {
"background": "oklch(98.6% 0.006 85)",
"foreground": "oklch(21% 0.012 60)",
"muted": "oklch(52% 0.014 60)",
"accent": "oklch(45% 0.14 28)",
"accentForeground": "oklch(98% 0.008 85)",
"connector": "oklch(45% 0.14 28)",
"radius": 3,
"width": 360,
"padding": "18px 20px 16px",
"duration": 190
},
"eyebrow": "{tour}",
"progress": "count",
"spotlight": {
"padding": 8,
"radius": 3,
"ring": "hairline"
},
"overlay": {
"color": "oklch(24% 0.03 60)",
"opacity": 0.46
},
"css": ".title { font-family: ui-serif, Georgia, 'Times New Roman', serif; font-size: 21px; letter-spacing: -0.01em; } .eyebrow { letter-spacing: 0.14em; } .footer { margin-top: 20px; padding-top: 12px; border-top: 1px solid color-mix(in oklch, var(--docent-fg) 14%, transparent); }"
}npx @docentjs/cli theme add carboncarbon.json
{
"name": "Carbon",
"theme": {
"background": "oklch(13% 0.01 285)",
"foreground": "oklch(99% 0.002 285)",
"muted": "oklch(88% 0.008 285)",
"accent": "oklch(90% 0.18 100)",
"accentForeground": "oklch(13% 0.01 285)",
"connector": "oklch(90% 0.18 100)",
"ring": "oklch(90% 0.18 100)",
"radius": 4,
"width": 340,
"padding": "18px",
"shadow": "none"
},
"progress": "ticks",
"spotlight": {
"padding": 6,
"radius": 2,
"ring": "solid"
},
"overlay": {
"opacity": 0.8
},
"css": ".popover { box-shadow: 0 0 0 2px var(--docent-accent); } .marks i { height: 3px; }"
}npx @docentjs/cli theme add concreteconcrete.json
{
"name": "Concrete",
"theme": {
"background": "oklch(90% 0.004 95)",
"foreground": "oklch(14% 0 0)",
"muted": "oklch(38% 0.004 95)",
"accent": "oklch(14% 0 0)",
"accentForeground": "oklch(90% 0.004 95)",
"connector": "oklch(96% 0 0)",
"ring": "oklch(96% 0 0)",
"radius": 0,
"width": 360,
"padding": "16px 18px 14px",
"shadow": "none",
"font": "ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace",
"duration": 120
},
"eyebrow": "// {tour}",
"progress": "count",
"count": "[{current2}/{total2}]",
"arrow": "zigzag",
"spotlight": {
"padding": 6,
"radius": 0,
"shape": "rect",
"ring": "dashed"
},
"overlay": {
"color": "oklch(14% 0 0)",
"opacity": 0.56
},
"css": ".popover, .popover.sheet { box-shadow: 0 0 0 2px var(--docent-fg); } .popover .arrow { border-color: var(--docent-fg) !important; border-width: 2px !important; border-radius: 0 !important; } .title { font-size: 15px; font-weight: 700; line-height: 1.35; text-transform: uppercase; letter-spacing: 0.02em; } .eyebrow { text-transform: none; letter-spacing: 0; font-size: 11px; } .body { font-size: 13px; color: var(--docent-fg); } .footer { margin-top: 16px; padding-top: 12px; border-top: 2px solid var(--docent-fg); } .count { color: var(--docent-fg); letter-spacing: 0; } .button, .popover.stories [part~='button-next'] { border-radius: 0; } .button { box-shadow: inset 0 0 0 2px var(--docent-fg); font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; } .button:hover, [part~='button-skip']:hover { background: var(--docent-fg); color: var(--docent-bg); } [part~='button-skip'] { box-shadow: none; } .button.primary { box-shadow: none; } .button.primary:hover { background: oklch(34% 0 0); } .close { border-radius: 0; color: var(--docent-fg); } .close:hover { background: var(--docent-fg); color: var(--docent-bg); }"
}npx @docentjs/cli theme add consoleconsole.json
{
"name": "Console",
"theme": {
"background": "oklch(24.5% 0.016 60)",
"foreground": "oklch(94% 0.008 60)",
"muted": "oklch(72% 0.012 60)",
"accent": "oklch(74% 0.165 58)",
"accentForeground": "oklch(19% 0.04 60)",
"connector": "oklch(74% 0.165 58)",
"ring": "oklch(74% 0.165 58)",
"radius": 8,
"width": 344,
"padding": "16px 16px 12px",
"shadow": "0 24px 56px -24px oklch(8% 0.02 60 / 0.95)",
"duration": 200
},
"eyebrow": "{tour}",
"progress": "count",
"count": "{current2}/{total2}",
"spotlight": {
"ring": "hairline",
"padding": 8,
"radius": 6,
"animate": true
},
"overlay": {
"color": "oklch(12% 0.014 60)",
"opacity": 0.66
},
"css": ".count { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: 0.02em; } .button { border-radius: 6px; }"
}npx @docentjs/cli theme add frostfrost.json
{
"name": "Frost",
"theme": {
"background": "oklch(99% 0.004 250 / 0.62)",
"foreground": "oklch(22% 0.02 255)",
"muted": "oklch(45% 0.02 255)",
"accent": "oklch(22% 0.02 255)",
"accentForeground": "oklch(99% 0.004 250)",
"connector": "oklch(22% 0.02 255)",
"ring": "oklch(99% 0.004 250)",
"radius": 20,
"width": 340,
"padding": "20px 20px 16px",
"shadow": "0 1px 1px oklch(30% 0.03 255 / 0.06), 0 24px 56px -20px oklch(30% 0.05 255 / 0.42)",
"duration": 240
},
"progress": "dots",
"arrow": "arc",
"spotlight": {
"padding": 8,
"radius": 14,
"ring": "glow",
"animate": true
},
"overlay": {
"style": "blur",
"blur": 3,
"color": "oklch(42% 0.05 255)",
"opacity": 0.3
},
"css": ".popover { -webkit-backdrop-filter: blur(22px) saturate(1.8); backdrop-filter: blur(22px) saturate(1.8); } .popover, .popover.sheet { box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.75), 0 0 0 1px oklch(100% 0 0 / 0.6), var(--docent-shadow); } .popover .arrow { border-color: oklch(100% 0 0 / 0.6) !important; -webkit-backdrop-filter: blur(22px); backdrop-filter: blur(22px); } .button { border-radius: 999px; } .button:hover { background: oklch(100% 0 0 / 0.5); } .button.primary { padding-inline: 16px; } .marks i { background: oklch(22% 0.02 255 / 0.16); }"
}npx @docentjs/cli theme add graphitegraphite.json
{
"name": "Graphite",
"theme": {
"background": "oklch(27% 0.008 260)",
"foreground": "oklch(93% 0.006 260)",
"muted": "oklch(71% 0.01 260)",
"accent": "oklch(82% 0.13 165)",
"accentForeground": "oklch(22% 0.03 165)",
"connector": "oklch(82% 0.13 165)",
"ring": "oklch(82% 0.13 165)",
"radius": 22,
"width": 340,
"padding": "22px 22px 18px",
"shadow": "9px 9px 22px oklch(13% 0.008 260 / 0.85), -9px -9px 22px oklch(39% 0.01 260 / 0.5)",
"duration": 240
},
"eyebrow": "{tour}",
"progress": "ticks",
"arrow": "marker",
"spotlight": {
"padding": 10,
"radius": 14,
"animate": true
},
"overlay": {
"color": "oklch(27% 0.008 260)",
"opacity": 0.84
},
"css": ".popover, .popover.sheet { box-shadow: var(--docent-shadow); } .popover .arrow { border-color: transparent !important; } .ring { box-shadow: 6px 6px 16px oklch(13% 0.008 260 / 0.8), -6px -6px 16px oklch(39% 0.01 260 / 0.5); } .eyebrow { color: var(--docent-accent); } .button { border-radius: 12px; } .button:hover { background: transparent; color: var(--docent-accent); } .button.primary { padding-inline: 16px; box-shadow: 4px 4px 10px oklch(13% 0.008 260 / 0.8), -4px -4px 10px oklch(39% 0.01 260 / 0.45); } .button.primary:hover { background: var(--docent-accent); color: var(--docent-accent-fg); } .button.primary:active { scale: 1; box-shadow: inset 3px 3px 7px oklch(50% 0.1 165 / 0.6), inset -3px -3px 7px oklch(92% 0.1 165 / 0.6); } .close { border-radius: 10px; box-shadow: 3px 3px 7px oklch(13% 0.008 260 / 0.7), -3px -3px 7px oklch(39% 0.01 260 / 0.45); } .close:hover { background: transparent; } .marks i { height: 4px; border-radius: 999px; background: oklch(20% 0.008 260); box-shadow: inset 1px 1px 1px oklch(13% 0.008 260); } .marks i[data-done] { background: var(--docent-accent); box-shadow: none; }"
}npx @docentjs/cli theme add ledgerledger.json
{
"name": "Ledger",
"theme": {
"background": "oklch(99.3% 0.005 95)",
"foreground": "oklch(24% 0.014 95)",
"muted": "oklch(58% 0.011 95)",
"accent": "oklch(42% 0.082 155)",
"accentForeground": "oklch(98% 0.012 155)",
"connector": "oklch(42% 0.082 155)",
"ring": "oklch(98% 0.01 95)",
"radius": 12,
"width": 352,
"padding": "18px 18px 14px",
"shadow": "0 1px 2px oklch(24% 0.014 95 / 0.08), 0 26px 52px -26px oklch(24% 0.014 95 / 0.55)",
"duration": 220
},
"eyebrow": "{tour}",
"progress": "ticks",
"count": "{current2} / {total2}",
"spotlight": {
"padding": 10,
"radius": 10,
"animate": true
},
"overlay": {
"color": "oklch(32% 0.03 95)",
"opacity": 0.44
}
}npx @docentjs/cli theme add neonneon.json
{
"name": "Neon",
"theme": {
"background": "oklch(17% 0.025 285)",
"foreground": "oklch(97% 0.01 285)",
"muted": "oklch(75% 0.03 285)",
"accent": "oklch(87% 0.15 190)",
"accentForeground": "oklch(18% 0.03 220)",
"connector": "oklch(72% 0.25 340)",
"ring": "oklch(87% 0.15 190)",
"radius": 14,
"width": 340,
"padding": "18px 18px 14px",
"shadow": "0 0 0 1px oklch(87% 0.15 190 / 0.35), 0 0 32px -6px oklch(87% 0.15 190 / 0.35), 0 28px 60px -24px oklch(5% 0.02 285 / 0.95)",
"duration": 220
},
"eyebrow": "{tour}",
"progress": "ticks",
"arrow": "glow",
"spotlight": {
"padding": 8,
"radius": 10,
"ring": "pulse",
"animate": true
},
"overlay": {
"color": "oklch(8% 0.03 285)",
"opacity": 0.72
},
"css": ".popover, .popover.sheet { box-shadow: var(--docent-shadow); } .popover .arrow { border-color: oklch(87% 0.15 190 / 0.35) !important; } .eyebrow { color: oklch(76% 0.22 340); letter-spacing: 0.16em; } .title { text-shadow: 0 0 18px oklch(87% 0.15 190 / 0.35); } .button.primary { box-shadow: 0 0 0 1px oklch(87% 0.15 190 / 0.6), 0 0 18px -2px oklch(87% 0.15 190 / 0.7); } .marks i[data-done] { background: var(--docent-accent); box-shadow: 0 0 6px oklch(87% 0.15 190 / 0.8); }"
}npx @docentjs/cli theme add nocturnenocturne.json
{
"name": "Nocturne",
"theme": {
"background": "oklch(23% 0.013 265)",
"foreground": "oklch(95% 0.004 265)",
"muted": "oklch(74% 0.008 265)",
"accent": "oklch(95% 0.004 265)",
"accentForeground": "oklch(14.5% 0.008 265)",
"connector": "oklch(68% 0.13 48)",
"ring": "oklch(68% 0.13 48)",
"radius": 10,
"width": 340,
"padding": "16px 16px 12px",
"shadow": "0 26px 60px -26px oklch(6% 0.01 265 / 0.95)",
"duration": 200
},
"eyebrow": "{tour}",
"progress": "dots",
"arrow": "curve",
"spotlight": {
"padding": 8,
"radius": 9,
"ring": "glow",
"animate": true
},
"overlay": {
"color": "oklch(10% 0.01 265)",
"opacity": 0.68
}
}npx @docentjs/cli theme add pebblepebble.json
{
"name": "Pebble",
"theme": {
"background": "oklch(93.5% 0.008 250)",
"foreground": "oklch(30% 0.02 255)",
"muted": "oklch(50% 0.018 255)",
"accent": "oklch(56% 0.13 255)",
"accentForeground": "oklch(98% 0.005 250)",
"connector": "oklch(56% 0.13 255)",
"ring": "oklch(56% 0.13 255)",
"radius": 24,
"width": 336,
"padding": "22px 22px 18px",
"shadow": "10px 10px 24px oklch(72% 0.02 255 / 0.7), -10px -10px 24px oklch(100% 0 0 / 0.9)",
"duration": 260
},
"progress": "dots",
"arrow": "coil",
"spotlight": {
"padding": 10,
"radius": 16,
"animate": true
},
"overlay": {
"color": "oklch(93.5% 0.008 250)",
"opacity": 0.76
},
"css": ".popover, .popover.sheet { box-shadow: var(--docent-shadow); } .popover .arrow { border-color: transparent !important; } .ring { box-shadow: 7px 7px 16px oklch(72% 0.02 255 / 0.7), -7px -7px 16px oklch(100% 0 0 / 0.95); } .button { border-radius: 999px; } .button:hover { background: transparent; color: var(--docent-accent); } .button.primary { padding-inline: 18px; box-shadow: 5px 5px 12px oklch(72% 0.02 255 / 0.75), -5px -5px 12px oklch(100% 0 0 / 0.9); } .button.primary:hover { background: var(--docent-accent); color: var(--docent-accent-fg); } .button.primary:active { scale: 1; box-shadow: inset 3px 3px 7px oklch(40% 0.12 255 / 0.55), inset -3px -3px 7px oklch(72% 0.12 255 / 0.5); } .close { border-radius: 999px; box-shadow: 3px 3px 7px oklch(72% 0.02 255 / 0.6), -3px -3px 7px oklch(100% 0 0 / 0.9); } .close:hover { background: transparent; } .marks i { background: transparent; box-shadow: inset 1px 1px 2px oklch(68% 0.02 255 / 0.8), inset -1px -1px 2px oklch(100% 0 0 / 0.9); } .marks i[data-done] { background: var(--docent-accent); box-shadow: none; }"
}npx @docentjs/cli theme add posterposter.json
{
"name": "Poster",
"theme": {
"background": "oklch(98.5% 0.012 95)",
"foreground": "oklch(16% 0 0)",
"muted": "oklch(36% 0 0)",
"accent": "oklch(89% 0.18 102)",
"accentForeground": "oklch(16% 0 0)",
"connector": "oklch(89% 0.18 102)",
"ring": "oklch(89% 0.18 102)",
"radius": 2,
"width": 344,
"padding": "20px 20px 18px",
"shadow": "0 0 0 2.5px oklch(16% 0 0), 7px 7px 0 2.5px oklch(16% 0 0)",
"duration": 140
},
"eyebrow": "{tour}",
"progress": "count",
"count": "{current2} / {total2}",
"arrow": "block",
"spotlight": {
"padding": 6,
"radius": 2,
"shape": "rect",
"ring": "solid"
},
"overlay": {
"color": "oklch(16% 0 0)",
"opacity": 0.42
},
"css": ".popover, .popover.sheet { box-shadow: var(--docent-shadow); } .popover .arrow { border-color: var(--docent-fg) !important; border-width: 2.5px !important; border-radius: 0 !important; } :host([data-ring='solid']) .ring { box-shadow: 0 0 0 3px currentColor; } .title { font-size: 20px; font-weight: 800; letter-spacing: -0.02em; } .eyebrow { align-self: flex-start; padding: 3px 6px; background: oklch(72% 0.2 350); color: var(--docent-fg); font-weight: 700; box-shadow: 0 0 0 2px var(--docent-fg); margin-bottom: 4px; } .body { color: var(--docent-fg); } .count { color: var(--docent-fg); font-weight: 700; } .button, .popover.stories [part~='button-next'] { border-radius: 0; font-weight: 700; } .button.primary, .button.primary:hover { background: var(--docent-accent); box-shadow: 0 0 0 2px var(--docent-fg), 3px 3px 0 2px var(--docent-fg); transition: translate 80ms ease-out, box-shadow 80ms ease-out; } .button.primary:hover { translate: -1px -1px; box-shadow: 0 0 0 2px var(--docent-fg), 4px 4px 0 2px var(--docent-fg); } .button.primary:active { scale: 1; translate: 3px 3px; box-shadow: 0 0 0 2px var(--docent-fg); } .close { border-radius: 0; color: var(--docent-fg); } .close:hover { background: var(--docent-accent); }"
}npx @docentjs/cli theme add quietquiet.json
{
"name": "Quiet",
"theme": {
"background": "oklch(99.4% 0.003 285)",
"foreground": "oklch(23% 0.018 285)",
"muted": "oklch(56% 0.014 285)",
"accent": "oklch(26% 0.02 285)",
"radius": 8,
"width": 300,
"padding": "14px 16px 12px",
"shadow": "0 1px 2px oklch(23% 0.02 285 / 0.08), 0 6px 16px -6px oklch(23% 0.02 285 / 0.14)"
},
"progress": "none",
"arrow": "curve",
"spotlight": {
"ring": "glow",
"padding": 6,
"radius": 8
},
"overlay": {
"style": "none"
},
"css": ".title { font-size: 16px; }"
}npx @docentjs/cli theme add slateslate.json
{
"name": "Slate",
"theme": {
"background": "oklch(100% 0 0)",
"foreground": "oklch(21% 0.02 265)",
"muted": "oklch(52% 0.02 265)",
"accent": "oklch(54% 0.22 268)",
"accentForeground": "oklch(99% 0.005 268)",
"connector": "oklch(82% 0.1 268)",
"ring": "oklch(82% 0.1 268)",
"radius": 16,
"width": 344,
"padding": "18px 18px 14px",
"shadow": "0 0 0 1px oklch(21% 0.02 265 / 0.07), 0 2px 4px -1px oklch(21% 0.02 265 / 0.06), 0 12px 24px -6px oklch(21% 0.02 265 / 0.12), 0 40px 80px -24px oklch(30% 0.12 268 / 0.35)",
"duration": 220
},
"progress": "meter",
"arrow": "curve",
"spotlight": {
"padding": 8,
"radius": 12,
"ring": "pulse",
"animate": true
},
"overlay": {
"color": "oklch(21% 0.03 265)",
"opacity": 0.5
},
"css": ".popover, .popover.sheet { box-shadow: var(--docent-shadow); } .title { letter-spacing: -0.02em; } .button { border-radius: 10px; } .button.primary { background: linear-gradient(180deg, oklch(62% 0.2 268), var(--docent-accent)); box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.25), 0 1px 2px oklch(30% 0.15 268 / 0.4), 0 4px 12px -2px oklch(54% 0.22 268 / 0.45); } .button.primary:hover { background: linear-gradient(180deg, oklch(66% 0.2 268), oklch(57% 0.22 268)); } .meter { width: 44px; height: 4px; background: linear-gradient(var(--docent-accent), var(--docent-accent)) 0 0 / calc(var(--docent-step) / var(--docent-steps) * 100%) 100% no-repeat, oklch(21% 0.02 265 / 0.08); }"
}npx @docentjs/cli theme add velvetvelvet.json
{
"name": "Velvet",
"theme": {
"background": "oklch(21% 0.035 345)",
"foreground": "oklch(95% 0.012 80)",
"muted": "oklch(76% 0.03 60)",
"accent": "oklch(83% 0.1 82)",
"accentForeground": "oklch(22% 0.035 345)",
"connector": "oklch(83% 0.1 82)",
"ring": "oklch(83% 0.1 82)",
"radius": 6,
"width": 352,
"padding": "22px 24px 18px",
"shadow": "0 30px 64px -28px oklch(8% 0.04 345 / 0.95)",
"duration": 280
},
"eyebrow": "{tour}",
"progress": "ticks",
"arrow": "swoosh",
"spotlight": {
"padding": 10,
"radius": 8,
"ring": "glow",
"animate": true
},
"overlay": {
"color": "oklch(12% 0.03 345)",
"opacity": 0.66
},
"css": ".popover, .popover.sheet { box-shadow: 0 0 0 1px oklch(83% 0.1 82 / 0.32), inset 0 0 0 5px var(--docent-bg), inset 0 0 0 6px oklch(83% 0.1 82 / 0.2), var(--docent-shadow); } .popover .arrow { border-color: oklch(83% 0.1 82 / 0.32) !important; } .title { font-family: 'Iowan Old Style', 'Palatino Linotype', Palatino, ui-serif, Georgia, serif; font-size: 22px; font-weight: 500; letter-spacing: -0.005em; } .eyebrow { color: var(--docent-accent); font-size: 10px; letter-spacing: 0.24em; } .body { color: oklch(87% 0.016 70); } .button { border-radius: 999px; letter-spacing: 0.02em; } .button.primary { padding-inline: 18px; } .marks i[data-done] { background: var(--docent-accent); }"
}Writing your own
Section titled “Writing your own”Start from the closest theme, change the tokens, and keep going until the fields
run out. If you reach something no field covers, css is the next step, and
slots after that — but a theme that needs
code is no longer something you can publish, share or let a tool edit, so it is
worth staying in JSON as long as you can.