Pick and customise a theme
In this guide you choose a look for a deck and make it yours: you try the themes live, install a theme package, set its options, override a colour and a font, give one slide a dark background, and finally copy a theme into the deck to edit it freely. It takes about ten minutes.
You need a deck that runs with npm run devpnpm devyarn devbun run dev. If you don’t have one yet, follow
Your first deck in 5 minutes first.
1. Try the built-in themes on your slides
Section titled “1. Try the built-in themes on your slides”With the deck open in the browser, press T (or the palette button in the bottom-left corner). The theme menu lists the deck’s themes and a light/dark switch; pick one and every slide redraws in it. D flips between light and dark directly.
The menu changes only what this screen shows, and remembers it per deck in this browser. Your
deck.mdx is untouched, and the projector or a viewer’s phone keeps its own choice. A new deck
offers the three themes that ship with the engine:
| Theme | Look |
|---|---|
minimal |
The default: black on white, a wide sans serif, one accent. |
rla |
Zinc-950 with a blue to violet ramp and dot-matrix headings, made for the animated backgrounds. |
stack |
An emerald accent on warm neutrals, Inter, product-like. |
There are 16 themes in all: these three, none (no styles at all, for a deck that brings its own
CSS) and 13 theme packages. The theme gallery shows every one in light and dark.
2. Name the theme
Section titled “2. Name the theme”Every theme in the gallery ships inside @kadal/deck, so there is nothing to install. Pick one and
name it in the headmatter, the YAML block at the top of deck.mdx. This guide uses ocean:
---title: Tide tablestheme: ocean---Save, and the running deck switches to the new theme; there is nothing to import in
src/main.tsx. The theme brings its stylesheet, its fonts, its code colours and its own layouts
(ocean adds waves and depth, and a <Wave /> component). Each theme’s README, linked from
its card in the gallery, lists what it adds.
theme: ocean looks for a built-in theme first, then an installed @kadal/theme-ocean, then
kadal-theme-ocean, then a package called ocean, and finally the copy of ocean inside
@kadal/deck. So installing a theme’s own package is only for pinning it to a version apart from
the engine’s, or for building on it:
npm install @kadal/theme-oceanpnpm add @kadal/theme-oceanyarn add @kadal/theme-oceanbun add @kadal/theme-oceanA theme from someone else (kadal-theme-<name>, or any package) is installed like any other
dependency. When a name matches nothing, kadal-deck dev and kadal-deck build stop with the
names they tried and the command that installs the likeliest one.
3. Choose what the theme menu offers
Section titled “3. Choose what the theme menu offers”themes: puts those first in the menu; the other first-party themes follow them:
---title: Tide tablestheme: oceanthemes: [ocean, minimal, brand]---The deck opens in theme:; viewers can switch to any theme in themes:. Each theme picked from the
menu brings its own layouts, fonts and code colours, and the deck’s own theme’s components stay
available, so no slide breaks. Code blocks recolour too: the build highlights each token once for
every theme in the menu.
4. Set the theme’s options with themeConfig
Section titled “4. Set the theme’s options with themeConfig”Most themes have a few knobs. ocean takes an accent colour for each scheme and can hide the
waves on its cover:
---theme: oceanthemeConfig: accent: "#0b7285" # links, bullets and the progress bar, light scheme accentDark: "#5ff7ff" # the same in the dark scheme waves: true # false hides the swells along the cover---brand is a theme made of options: your colours, logo and footer, with no CSS to write. Put the
logo files in public/:
---theme: brandthemeConfig: primary: "#2453d4" # the cover, links, numbers, the accent secondary: "#0f9d8a" # gradients and shapes on the cover logo: ./logo.svg # from public/; without one the company name is set as a wordmark logoDark: ./logo-dark.svg # the logo on dark slides company: Harbor Labs # the wordmark, the logo's alt text, the footer's default footer: "Harbor Labs · Q3 review · Confidential" # false hides the footer logoPosition: top-right # top-left, bottom-right or none---Each key becomes a CSS custom property on the deck root (accentDark becomes
--theme-accent-dark), so your own CSS can read the same values. A theme’s README lists the keys
it reads; keys it doesn’t read do nothing.
5. Change a colour in your own CSS
Section titled “5. Change a colour in your own CSS”src/styles.css loads after the theme, so a token you set there wins. Every theme is built from
the same custom properties: --deck-bg, --deck-fg, --deck-muted, --deck-accent,
--deck-accent-2, --deck-surface and a few more (the full list is in
Writing a theme). Set the light and the dark value:
.theme-ocean { --deck-accent: #c2410c;}.theme-ocean[data-color-scheme="dark"] { --deck-accent: #fb923c;}Scope the rule to the theme’s class, .theme-<name>, as above. A rule on :root or html is
overridden by the theme, which sets its tokens on the deck’s own element.
6. Change the fonts
Section titled “6. Change the fonts”fonts: in the headmatter loads families from Google Fonts and points the theme’s font tokens at
them. It replaces the theme’s own choice:
---theme: oceanfonts: sans: Inter # body text, and headings unless `heading` is set heading: Fraunces # headings only mono: JetBrains Mono # code---weights (default 300,400,600,700), italic, serif, provider (google, bunny, or none
for fonts already on the machine) and local are covered in
Themes and backgrounds. Exports wait for the fonts before
they take pictures.
7. Give one slide a dark background
Section titled “7. Give one slide a dark background”A slide can force its own colour scheme, so a dark picture or an animated background under a light theme still has readable text. Set it in that slide’s frontmatter:
---colorScheme: darkbackground: { component: topo, color: "rgba(94,234,212,0.5)", fill: "rgba(94,234,212,0.10)" }---
## A dark slide in a light deck
The text, the code and the cards on this slide use the theme's dark tokens.background: takes a colour, a gradient, an image or video from public/, a web page, or one of 36
animated background components such as aurora, topo, globe or starfield. The full list is in
Themes and backgrounds, and defaults: in the
headmatter can give every slide the same one.
8. Rewrite a theme: theme eject
Section titled “8. Rewrite a theme: theme eject”When options and a few variables are not enough, copy the theme into the deck and edit it there:
npx kadal-deck theme ejectpnpm exec kadal-deck theme ejectyarn kadal-deck theme ejectbunx kadal-deck theme ejectTheme "ocean" ejected to /path/to/deck/theme; the headmatter now says theme: ./themeYou get theme/style.css, its layouts in theme/index.tsx, its package.json and README. The
headmatter now says theme: ./theme, nothing else in deck.mdx changes, and the deck looks
exactly as before. Edit theme/style.css and the deck follows. If themes: lists the package
(ocean), list ./theme there instead so the menu offers your copy.
--dir ./my-theme picks another folder, --theme seriph ejects a theme other than the deck’s, and
--force replaces a folder that exists. The built-in themes eject too.
- Themes and backgrounds: every theme, every option, every background.
- Writing a theme: turn your look into a package other decks can install.
- Layers, controls and pages: a footer or a logo on every slide.