Skip to content

Component reference

Every component here works in any slide without an import. This page is generated from the catalog of @kadal/deck 0.10.0, the same data npx kadal-deck info components <Name>pnpm exec kadal-deck info components <Name>yarn kadal-deck info components <Name>bunx kadal-deck info components <Name>, the VS Code extension’s hovers and the MCP servers read, so it matches the engine you install. Props marked required must be given; the rest have the default shown, or none.

Placing and sizing blocks on the 1920 × 1080 stage.

Absolute · Center · Col · Cols · Drag · DragArrow · FitText · Frame · Grid · Spacer · Stack · Stretch · Transform

Places a block at stage coordinates (pixels on the 1920 × 1080 stage).

<Absolute x={1500} y={80} w={320}><Badge tone="warn">Draft</Badge></Absolute>
Prop Type Default
x number 0 Left, px.
y number 0 Top, px.
w number Width, px.
h number Height, px.
rotate number 0 Degrees.
className string

Centres its children horizontally and vertically in the space it has.

<Center>
# One big idea
</Center>
Prop Type Default
className string

One column inside <Cols> (Markdown inside needs blank lines around it).

<Col span={2}>
Wide column
</Col>
Prop Type Default
className string
span number Grid columns to span.

Columns: each child (or <Col>) is a column. cols takes a CSS grid template.

<Cols cols="2fr 1fr">
<Col>
The main point, in Markdown.
</Col>
<Col>
![](/figure.png)
</Col>
</Cols>
Prop Type Default
cols string CSS grid-template-columns, e.g. “1fr 1fr” or “2fr 1fr”.
n number Number of equal columns (instead of cols).
gap string "2rem" CSS gap.
className string
align string CSS align-items; “start” stops cards in a row from sharing a height.

A block you place by hand. pos is “x,y,w,h[,rotation]” in stage pixels (_ height: automatic) or a name in the slide’s dragPos frontmatter. In kadal-deck dev, double-click it to move, resize, turn and nudge it; the position is saved into deck.mdx. Elsewhere it is simply placed.

<Drag pos="1400,120,380,_">
![](/badge.png)
</Drag>
Prop Type Default
pos string “x,y,w,h[,r]” in stage pixels (_ height: automatic), or a name in the frontmatter’s dragPos.
place string Where it sits while pos says nothing, in the same “x,y,w,h[,r]” form — how <Sticker x y size> places itself. The source still has no position, so the first drag writes pos.
at ClickAt A click step, as <Click at>.
hide boolean Start shown and hide at the step.
effect string "fade-in" The reveal effect with at (see <Click effect>).
as ElementType The element (div).
className string
style CSSProperties

An <Arrow> whose ends are dragged into place in kadal-deck dev. pos is “x,y,dx,dy” (from x,y by dx,dy) or a dragPos name.

<DragArrow pos="300,700,600,-280" color="var(--deck-accent)" width={4} />
Prop Type Default
pos string “x,y,dx,dy”: from (x, y) by (dx, dy), stage pixels — or a frontmatter dragPos name.
width number 2 Line width (px).
color string "currentColor" CSS colour.
twoWay boolean false Heads at both ends.
at ClickAt A click step.
hide boolean
effect string "fade-in"
className string

Text as large as fits its box, between min and max px.

<FitText max={260}>42%</FitText>
Prop Type Default
max number 400
min number 12
className string

A bordered frame around media.

<Frame>![](/screenshot.png)</Frame>
Prop Type Default
className string

A CSS grid of its children.

<Grid cols={3} gap="1rem">
<Glass>One</Glass>
<Glass>Two</Glass>
<Glass>Three</Glass>
</Grid>
Prop Type Default
cols string | number 3 Column count or a template.
rows string | number Row count or a template.
gap string "1.5rem" CSS gap.
className string

Vertical space.

<Spacer size="3rem" />
Prop Type Default
size string "1rem" CSS length.

Children on top of each other in one spot — combine with clicks to swap images in place.

<Stack>
<Click at={[1, 2]}>![](/v1.png)</Click>
<Click at={2}>![](/v2.png)</Click>
</Stack>
Prop Type Default
className string

Grows to fill the slide’s remaining height (an image under a heading).

## The whole map
<Stretch>![](/map.png)</Stretch>
Prop Type Default
className string

Scales a block around an origin.

<Transform scale={0.8}>
A table that is a little too big
</Transform>
Prop Type Default
scale number 1
origin string "top left"
className string

Steps within a slide. See Clicks and animation.

After · Case · Click · ClickCount · Clicks · Fragment · Stepper · Switch

Shows together with the previous click instead of taking a step of its own.

<Click>The claim</Click>
<After>…and its footnote, at the same moment</After>
Prop Type Default
hide boolean Start visible and hide at the step instead.
effect ClickEffect "fade-in" A reveal effect (see clickEffects) or any CSS class the theme defines.
as ElementType The element to render; a span for inline text, div by default.
className string Extra classes.
style CSSProperties Inline style (JSX object).
children ReactNode What is revealed.

One case of a <Switch>. Without at it is one step after the case before; at={0} is what the slide starts with; the last case stays unless it has a range.

<Switch>
<Case at={0}>Before</Case>
<Case>After one click</Case>
</Switch>
Prop Type Default
at string | number | [number, number] When, in the switch’s own steps: n, “a-b”, or [a, b]. Default: one after the case before.
as ElementType This case’s element.
className string Extra classes.

One click step: shows its children from its step on, or hides them with hide.

<Click>Appears on the first click</Click>
<Click at="+2" effect="fade-up">Two clicks later, sliding up</Click>
Prop Type Default
at ClickAt When: omitted = one after the previous step; “+N” relative (“+0” shares the previous step); a number is absolute (0 = always shown); [from, to] shows it from from until to.
hide boolean Start visible and hide at the step instead.
effect ClickEffect "fade-in" A reveal effect (see clickEffects) or any CSS class the theme defines.
as ElementType The element to render; a span for inline text, div by default.
className string Extra classes.
style CSSProperties Inline style (JSX object).
children ReactNode What is revealed.

The click step this slide is at, or with total how many it has; with a function child, anything that depends on the count. Never adds a click step itself. Hook: useClicks().

Step <ClickCount offset={1} /> of <ClickCount total />
<ClickCount when={(c) => c >= 3}>
**Done.**
</ClickCount>
Prop Type Default
total boolean false Show the slide’s number of clicks rather than the current one.
offset number 0 Add this to the number shown: offset={1} counts from 1 (“step 1” before any click).
className string
when ((click: number, total: number) => unknown) Render the children only while this is true of the count: when={(c) => c >= 2}.
children ReactNode | ((click: number, total: number) => ReactNode) With when: what to show. Otherwise a function of the count, for anything that depends on it: {(c, total) => …}. Without either, the number is shown in a <span>.

Wraps a Markdown list (or any children) so each item is its own click step. Leave blank lines around the list inside it.

<Clicks>
- First point
- Second point
- Third point
</Clicks>
Prop Type Default
every number 1 Reveal this many items per click.
depth number 1 How deep nested lists take part; 1 means only the outer list.
effect ClickEffect "fade-in" The reveal effect for every item.
children ReactNode A list, or blocks.

Another name for <Click>; identical.

<Fragment effect="highlight-red">Same as Click</Fragment>
Prop Type Default
at ClickAt
hide boolean
effect ClickEffect
as ElementType The element to render; a span for inline text, div by default.
className string
style CSSProperties

Where the talk (or this slide) is, as fixed furniture: equal cells, so the current step never nudges the others. place="top" or "bottom" puts it on the slide’s rail, outside the layout, so it sits pixel-identical on every slide; follow walks it with this slide’s clicks.

<Stepper steps={["Build", "Rehearse", "Present", "Own the room"]} current={2} place="top" />
<Stepper steps={["Ask", "Measure", "Change"]} follow at={1} />
<Switch at={1}>
<Case at={0}>Ask what the room needs</Case>
<Case>Measure it out loud</Case>
<Case>Change what ran long</Case>
</Switch>
Prop Type Default
steps required ReactNode[] The steps’ labels, in order.
current number The current step, 1-based; 0 for none yet. Ignored with follow.
follow boolean Advance with this slide’s clicks (one step per click) instead of current.
at ClickAt With follow: when the second step arrives, as <Click at>. Default one after the previous click.
place "top" | "bottom" “top” or “bottom”: on the slide’s rail, the same place on every slide. Default: inline.
variant "chips" | "bar" | "dots" chips (default), bar, dots.
numbered boolean Number the steps (chips only). Default true.
className string
label string What a screen reader calls it. Default “Progress”.

One child at a time, switched by clicks: each <Case> takes the next step, or at={n} / at="a-b" in the switch’s own steps; the cases share one spot, so nothing below jumps.

<Switch transition="slide-up">
<Case>First</Case>
<Case>Then</Case>
<Case at="4-6">Steps 4 and 5</Case>
</Switch>
Prop Type Default
at ClickAt When the switch’s first step is: as <Click at>. Default one after the previous click.
transition (string & {}) | "fade" | "slide-up" | "slide-left" | "scale" | "none" "fade" “fade” (default), “slide-up”, “slide-left”, “scale”, or “none”.
unmount boolean false Leave hidden cases out of the page rather than hidden in it.
as ElementType The switch’s element; div by default.
childAs ElementType Each case’s element (childTag); div by default.
className string
children ReactNode <Case>s — or any elements, each one step.

Text, notes, links and small pieces of a slide.

Arrow · Badge · Callout · Confetti · Counter · Encrypted · FlipBoard · Kbd · LightOrDark · Link · Mark · Math · Notes · Qr · RenderWhen · SlideCurrentNo · SlidesTotal · Tex · Timer · TitleRenderer · Toc · Typewriter

A straight arrow between two points in stage coordinates.

<Arrow x1={300} y1={700} x2={900} y2={420} color="var(--deck-accent)" />
Prop Type Default
x1 required number
y1 required number
x2 required number
y2 required number
width number 2 Stroke width.
color string "currentColor" CSS colour.
twoWay boolean false Heads at both ends.
className string

A small inline label.

<Badge tone="good">new</Badge>
Prop Type Default
tone "neutral" | "accent" | "good" | "warn" | "bad" "neutral" neutral · accent · good · warn · bad.
className string

A boxed aside: info, tip, note, warn or danger, with an optional title.

<Callout kind="tip" title="Rule of thumb">
One idea per slide.
</Callout>
Prop Type Default
kind "warn" | "info" | "tip" | "danger" | "note" "info" info · tip · note · warn · danger.
title ReactNode A string, or any content (Comark’s #title slot arrives as content).
className string

A burst of confetti when the slide (or the given click) arrives.

<Confetti at={1} />
Prop Type Default
at string | number Click step.
count number 140 Pieces.
duration number 2200 Milliseconds.

A number that counts up when its slide is shown.

<Counter value={12500} prefix="₹" suffix="/mo" />
Prop Type Default
value required number Target number.
from number 0 Start.
duration number 1500 Milliseconds.
decimals number 0 Decimal places.
prefix string "" Text before.
suffix string "" Text after.
className string

Text that resolves out of random glyphs.

<Encrypted text="Decoded." />
Prop Type Default
text required string The text.
speed number 30 Milliseconds per glyph.
delay number 0 Milliseconds before it starts.
className string

A split-flap board whose cells flip to its text: one cell per character, a row per line.

<FlipBoard text={"HIGH WATER\n06:12"} />
Prop Type Default
text required string The text; \n starts a new row.
rows number Rows (default: the text’s lines).
cols number Columns (default: the longest line).
className string Class on the board.
flipDuration number 35 Milliseconds per flip.
stagger number 15 Milliseconds between neighbouring cells.

A keyboard key.

Press <Kbd>?</Kbd> for help

One thing in the light colour scheme, another in the dark (the slide’s own scheme when its frontmatter forces one): light/dark props, children marked slot="light"/slot="dark", or a function of the scheme.

<LightOrDark>
<div slot="dark">![](/logo-white.svg)</div>
<div slot="light">![](/logo-black.svg)</div>
</LightOrDark>
Prop Type Default
light ReactNode Shown in the light scheme.
dark ReactNode Shown in the dark scheme.
children ReactNode | ((props: { scheme: Scheme; } & Record<string, unknown>) => ReactNode) Either children marked slot="light" / slot="dark" (any element: <div slot="dark">…</div>), or a function of the scheme and the other props: {({ scheme }) => …}.

A link to another slide by 1-based number, h.v, or slide id.

<Link to="results">See the results</Link>
Prop Type Default
to required string | number Slide number (1-based), “h.v”, or a slide id.
title string Tooltip.
className string

A hand-drawn mark: underline, box, circle, highlight, strike-through, crossed-off or bracket, drawn stroke by stroke on its click. The wobble is seeded from the text, so it looks the same on every screen and in the PDF.

The answer is <Mark type="circle">forty-two</Mark>.
<Mark type="bracket" brackets="left right" color="#e11d48" at={2}>Both sides</Mark>
Prop Type Default
type "strike" | MarkType | "line-through" | "linethrough" | "cross" | "crossed" "underline" underline · box · circle · highlight · strike-through · crossed-off · bracket (the aliases strike, line-through, cross, crossed work too).
color string "var(--deck-accent)" Any CSS colour; default the theme’s accent.
at ClickAt When: as <Click at> (default: the next click; 0 = always; [a, b] from a until b).
strokeWidth number Line width in px (default 3; a highlight is as tall as the line).
padding string | number | number[] Space around the text in px: one number, or “top right bottom left” like CSS. Default 5.
iterations number 2 Strokes per line, each a little different (default 2).
multiline boolean One mark per line of wrapped text. Default: on for underline, highlight, strike-through, crossed-off.
brackets string | string[] "right" For a bracket: which sides — “left”, “right”, “top”, “bottom”, or several. Default “right”.
duration number How long the stroke takes to draw, ms (default 800).
animationDuration number Another name for duration.
delay number 0 Wait this long after the click before drawing, ms.
animate boolean true Turn the drawing animation off: the mark appears whole.
opacity number 0–1. Default 1 (a highlight: 0.35, so the text shows through).
className string

Another name for <Tex>.

<Math tex="\int_0^1 x\,dx" block />
Prop Type Default
tex string
block boolean false

Speaker notes. Lifted out at compile time and shown in the presenter view; [click] markers line them up with clicks. HTML comments at the very end of a slide are its notes, and both kinds join.

<Notes>
Open with the question. [click] Then reveal the number.
</Notes>

A QR code for any text or URL, rendered locally.

<Qr value="https://deck.kadal.cc" size={280} />
Prop Type Default
value required string Text or URL to encode.
size number 240 Pixels.
className string

Renders its children only in some places: main (the deck and the presenter’s current slide), slide, presenter, previewNext, overview, print/export, audience, visible; fallback everywhere else.

<RenderWhen context="presenter">Only the speaker sees this.</RenderWhen>
<RenderWhen context={["print", "overview"]} fallback={<Iframe src="https://example.com" />}>![](/still.png)</RenderWhen>
Prop Type Default
context required string | RenderWhenContext[] Where to render: main (the deck and the presenter’s current slide — and the audience’s phone), slide, presenter, previewNext (the presenter’s next box), overview, print (also export), audience, visible (on screen right now). Several — an array or “presenter overview” — render in any of them; visible combined with others must also hold.
fallback ReactNode null Rendered where the context does not match.

This slide’s number (in a global layer: the current slide’s).

Slide <SlideCurrentNo /> of <SlidesTotal />
Prop Type Default
format "c" | "c/t" | "h.v" | "h/v" "c" “c” the flat number (default), “h.v” or “h/v” with vertical slides, “c/t” with the total.
className string

How many slides the deck has (hidden ones left out).

<SlidesTotal /> slides
Prop Type Default
className string

KaTeX maths from JSX. In Markdown prefer $inline$ and $$display$$, which render at build time.

<Tex tex="E = mc^2" block />
Prop Type Default
tex string LaTeX source.
block boolean false Display (centred, own line) instead of inline.

A countdown (with seconds) or a stopwatch that starts when its slide is shown.

<Timer seconds={120} />
Prop Type Default
seconds number Count down from this; omit for a stopwatch.
className string

Another slide’s title, by its number or id (no prop: this slide’s own).

Next up: <TitleRenderer no={3} />
Prop Type Default
no string | number Slide number, 1-based.
id string Or the slide’s id.
fallback ReactNode Shown when that slide has no title (or there is no such slide).
as "div" | "h1" | "h2" | "h3" | "span" | "strong" "span" The element: span (default), h1–h3, strong, div.
className string

A table of contents from every slide’s title and heading level (hideInToc slides skipped).

## Agenda
<Toc maxDepth={1} />
Prop Type Default
columns number 1 Number of columns.
maxDepth number Number.POSITIVE_INFINITY Deepest heading level listed.
minDepth number 1 Shallowest heading level listed.
mode "all" | "onlyCurrentTree" | "onlySiblings" "all" all · onlyCurrentTree · onlySiblings.
listClass string Class on the list.

Text that types itself out when the slide is shown.

<Typewriter text="npm create @kadal/deck@latest" />
Prop Type Default
text required string The text.
speed number 35 Milliseconds per character.
className string
cursor boolean true Show a cursor.

Pictures, sound, video and embedded pages.

Audio · BlueSky · Credits · Emoji · Gif · Iframe · Image · Meme · Sticker · Tweet · Video · Youtube

An audio player.

<Audio src="/clip.mp3" />
Prop Type Default
src required string Audio URL.
autoplay boolean Play on arrival.
loop boolean Loop.
controls boolean true Show controls.
className string

A Bluesky post, through Bluesky’s embed, in the slide’s colour scheme; deck export captures a poster for each scheme.

<BlueSky uri="https://bsky.app/profile/bsky.app/post/3myi2ihquwk26" />
Prop Type Default
uri required string The post: its bsky.app address or its AT-URI.
scale string | number 1 Scale factor.
poster string Stands in for the post in print, the overview and while it loads.
className string

The deck’s media credits: every attributed GIF, sticker, meme template, emoji set, icon set and <Image credit> the slides use, collected when the deck compiles and grouped by source, each with its licence and a link. credits: true in the headmatter adds a slide with it before the last slide and a corner link to it on every other slide, so it is rarely written by hand; a slide that has one is used instead.

---
id: credits
---
<Credits title="Thanks to" />
Prop Type Default
title string | false The heading (default: the headmatter’s credits.title, else “Credits”); false for none.
lede string | false One line under the heading; false for none.
className string Extra classes.

One emoji as an image from an open set (Fluent 3D/Color/Flat, Noto, Noto Animated, Twemoji), served by the host (https://decks.kadal.cc/emoji by default). char is exact; name is looked up in the host’s index. Animated Noto shows a still under reduced motion and in print.

<Emoji name="party-popper" /> <Emoji char="👍🏽" set="twemoji" size={96} />
Prop Type Default
name string Its name in the host’s index (“party-popper”); char wins when both are given.
char string The emoji itself (“🎉”, “👍🏽”): exact, no lookup. Children work too: 🎉.
set "fluent-3d" | "fluent-color" | "fluent-flat" | "noto" | "noto-animated" | "twemoji" fluent-3d (default), fluent-color, fluent-flat, noto, noto-animated, twemoji.
size string | number "1.2em" CSS size (a number is px). Default 1.2em: it sits in a line of text.
alt string Alternative text (default: the name).
className string

A GIF from a provider (KLIPY), hot-linked exactly as the provider returned it, with a small credit on hover. Print and every export (PDF, PNG, PPTX) show a card with its title and a link instead of the media — the providers’ terms don’t allow copying it.

<Gif provider="klipy" slug="hello-hi-662" src="https://static.klipy.com/ii/…/hello.gif" title="Hello" width={498} height={498} />
Prop Type Default
provider string "klipy" Who it came from: “klipy” (default), “kadal” (Kadal’s own library), “giphy”.
id string The provider’s id.
slug string The provider’s slug (builds the link back).
src required string The media URL exactly as the provider returned it (GIF, WebP, or MP4/WebM).
title string Title: the alt text, the credit and the export card.
creator string Who made it, for the credit.
width number Width in px (with height: the aspect ratio).
height number Height in px.
still string A still frame from the provider, shown under reduced motion.
href string The page to link to in the credit and the export card (default: the provider’s page for it).
alt string
className string

An embedded page, loaded only while its slide is near, behind a click-to-interact shield; a poster stands in for print and previews.

<Iframe src="https://example.com" poster="/posters/example.jpg" scale={0.5} />
Prop Type Default
src required string Page URL.
preload boolean Load it before its slide is near.
className string
title string Accessible title.
poster string Stands in for the page in print, the overview and the next-slide box, and while it loads.
posterSize readonly [number, number]
scale number Render the page larger and shrink it: 0.5 gives a small pane the desktop layout.

The img mapping (every ![alt](src)), lazy-loaded; also usable as a tag. preview opens a lightbox on click.

![A map of Chennai](/chennai.png)
<Image src="/chart.png" alt="Revenue by month" preview fit="contain" />
Prop Type Default
src string Image URL; /x.png is served from the deck’s public/ folder.
alt string "" Alternative text (always write one).
preview string | boolean true, or a larger image’s URL, to open a lightbox on click.
fit string CSS object-fit (cover, contain…).
className string
credit string Who to thank (““Harbour at dawn” by Ana Ruiz”): listed by <Credits />, the title on hover.
creditUrl string The work’s page, for the credit’s link.
license string Its licence (“CC BY 2.0”), for the credits.
licenseUrl string The licence’s text.

Image-macro captions over a picture: white Anton with a black outline by default, as real text. template records where the picture came from (Imgflip) and shows the link back on hover and in every export.

<Meme src="https://i.imgflip.com/30b1gx.jpg" template={{ provider: "imgflip", id: "181913649", url: "https://imgflip.com/memetemplate/181913649" }} captions={[{ text: "Writing slides by hand", x: 52, y: 6, width: 45 }, { text: "Kadal Deck", x: 52, y: 56, width: 45 }]} />
Prop Type Default
src required string The image.
provider string “kadal” for a template from Kadal’s own library (the same as template={{ provider: "kadal" }}).
alt string Alternative text (default: the captions).
template MemeTemplate { provider: “imgflip” | “kadal”, id, url, name } — the source, credited with a link.
captions MemeCaption[] [{ text, x, y, width, size, align, color, stroke }]: x/y/width in % of the image (defaults 5, 4, 90), size in % of its width (default 9), align left|center|right, colours CSS (default white on black).
width string | number CSS width (a number is px). Default: as wide as the image, up to its box.
className string

An image placed over the slide in stage pixels — a PNG cut-out, an animated GIF/WebP/APNG. Centred unless x/y say otherwise; in kadal-deck dev double-click it to move, resize or turn it and the position is written back as pos.

<Sticker src="/stickers/rocket.webp" x={1480} y={140} size={260} rotate={-8} shadow />
Prop Type Default
src required string Image URL (public/ path or https).
alt string "" Alternative text (empty: decorative).
size number Width in stage pixels (default 240); the height follows the image.
x number Left edge in stage pixels (default: centred).
y number Top edge in stage pixels (default: centred).
rotate number Degrees, clockwise.
flip boolean | "x" | "y" Mirror it: true or “x” left↔right, “y” upside down.
shadow boolean A soft drop shadow that follows the image’s outline.
pos string “x,y,w,h[,r]” — what dragging it in kadal-deck dev writes; wins over x/y/size/rotate.
provider string Where it came from: “kadal” for Kadal’s own library (credited “Kadal”).
id string The provider’s id for it (“kadal/ship-it”). Without a provider, id is the element’s id.
still string A still frame of an animated sticker: shown under reduced motion and in print.
credit string A credit of its own (“Photo by Ana Ruiz”), on hover and in the deck’s credits.
creditUrl string The credit’s link (the work’s page).
license string Its licence (“CC BY 4.0”), for the credits.
licenseUrl string The licence’s text.
className string
style CSSProperties

An embedded post from X/Twitter.

<Tweet id="20" />
Prop Type Default
id string | number Post id.
url string Or the post URL.
scale number 1 Scale factor.
poster string Stands in for the post in print, the overview and while it loads.

A video that knows the slide’s clicks: plays on arrival, at a click (at), pauses at one (pauseAt), jumps or rewinds at others (steps), or when the enclosing reveals it; still at its print frame in print and thumbnails.

<Video src="/demo.mp4" at={1} pauseAt={3} steps={{ 2: 42 }} timestamp={5} autoreset="slide" />
Prop Type Default
src string Video URL (public/ path or https), or <source> children.
autoplay boolean | "once" Play when the slide (or at, or the enclosing <Click>) arrives; “once”: only the first time.
at ClickAt The click at which it starts playing (as <Click at>); implies autoplay.
pauseAt ClickAt The click at which it pauses.
steps Record<string | number, VideoStep> What happens at further clicks: { 3: "pause", 4: "play", 6: 12.5, 8: "rewind" } (absolute clicks).
autoreset "slide" | "click" “slide”: back to timestamp whenever the slide is left; “click”: whenever the deck steps back before at.
timestamp string | number Start here, in seconds.
loop boolean Loop.
muted boolean true Muted (default true).
controls boolean false Show controls.
poster string Poster image.
printPoster string The poster in print, the overview and the next-slide box (default poster).
printTimestamp string | number The frame shown in print and previews: seconds, or “last”. Default timestamp.
className string
children ReactNode <source> elements, captions (<track>), fallback text.

A YouTube embed by id or URL.

<Youtube id="dQw4w9WgXcQ" start={42} />
Prop Type Default
id string Video id.
url string Or the full URL.
autoplay boolean Play on arrival.
start number Start at second.
className string
poster string Stands in for the player in print, the overview and while it loads.

Highlighted code. You write fences; these are what they compile to. See Code.

Code · CodeGroup · MagicMove

The pre mapping behind fenced code blocks: Shiki highlighting, line-highlight steps, titles. Write a fence, not this tag.

```ts {1|2-3|all} [app.ts]
const a = 1;
const b = 2;
export { a, b };
```
Prop Type Default
className string
data-steps string
data-lines string
data-start string
data-title string
data-max-height string
data-hide-until-step string
data-lang string
data-total string
data-monaco string editor, diff, run or write: the block is a Monaco editor (see MonacoCode).
data-code string The block’s source for the editor (the modified side of a diff).
data-original string The original side of a {monaco-diff}.
data-monaco-options string The editor’s and runner’s options, as JSON.
data-snippet string Where a <<< import read the code from: path#region.
data-twoslash string

Code blocks as tabs, each named by its fence’s [title] with a file-type badge. Usually written as ::code-group … :: around the fences (::: works too); ←/→ move between tabs. clicks turns tabs on each click; print="all" prints every tab.

::code-group
```sh [npm]
npm i @kadal/deck
```
```sh [bun]
bun add @kadal/deck
```
::
Prop Type Default
children ReactNode The fenced code blocks, one per tab (blank lines around them inside the tag).
clicks boolean Open the next tab on each click of the slide, from the group’s own step on.
at string | number With clicks: when the first turn happens, like <Click at> ("+1", an absolute step).
active number 0 The tab open at first (0-based). Default 0.
print "active" | "all" What print and export show: the open tab (default) or every tab.
className string Extra classes.

Shiki Magic Move: code that morphs between versions, one per click. Written as a ````md magic-move fence holding one code fence per step; an inner fence’s highlight steps ({*|2|4-5}) are clicks too, in order with the morphs. Outer options: at, lines, duration; [file.ts] adds a title bar. Follows the colour scheme and the theme menu.

````md magic-move
```ts
let n = 1
```
```ts
const n = 1
```
````
Prop Type Default
block required number

See Maths, diagrams and sketches.

KatexLines · Mermaid · Sketch

Display maths whose lines light up one step per click: what $$ {1|3|all} compiles to. Write the $$ block, not this tag.

$$ {1|2|all}
\begin{aligned}
a &= b + c \\
d &= e
\end{aligned}
$$
Prop Type Default
steps string "" 1|3|all: one set of lines per step.
at string | number The click the steps start at (a number, or +n).
finally string Lines shown once the slide’s clicks pass the last step (default: the last step).
startLine number 1 The number of the first line (default 1).
children ReactNode The rendered formula.

A Mermaid diagram rendered in the browser in the deck’s colours. Pass the source as a template string.

<Mermaid>{`flowchart LR
A[Write] --> B[Check] --> C[Present]`}</Mermaid>
Prop Type Default
children ReactNode Mermaid source as a JSX template string.
code string The diagram’s source, when it is not the children.
scale number 1 Scale factor.
theme string A Mermaid theme for this diagram: default, neutral, dark, forest, base.
config Record<string, unknown> Mermaid configuration for this diagram (themeVariables, look, flowchart…).
className string
alt string What the diagram shows, for screen readers (a fence’s alt); default its first line.

An Excalidraw drawing in the deck’s colours: from the sketch DSL (scene), an .excalidraw file (src), or Mermaid (children); steps tours its regions one click at a time.

<Sketch>{`flowchart LR; idea --> slide --> talk`}</Sketch>
<Sketch src="/diagrams/flow.excalidraw" height="600px" />
Prop Type Default
scene SketchScene A scene built with sketch() from @kadal/deck/sketch (import it in src/components.tsx or the slide).
src string | ExcalidrawFile Path to an .excalidraw file in public/.
mermaid string Mermaid source to convert.
steps SketchStep[] [] Regions to light up, one per click, after the whole diagram has shown.
caption ReactNode Shown under the diagram when no step’s caption is.
width string CSS size limits for the drawing.
height string CSS max height.
fontSize number Font size for Mermaid conversions.
zoomable boolean true Show the button that opens it in Excalidraw’s viewer.
className string

Animation keyed to a slide’s clicks.

Motion

Animates a block with motion (framer-motion): initial → enter on arrival, leave on exit, and per-click targets.

<Motion initial={{ opacity: 0, x: -80 }} enter={{ opacity: 1, x: 0 }} clicks={{ "click-1": { scale: 1.2 } }}>
Slides in from the left
</Motion>
Prop Type Default
initial TargetAndTransition { opacity: 0, y: 24 } Motion target before arrival.
enter TargetAndTransition { opacity: 1, y: 0 } Motion target on arrival.
leave TargetAndTransition Motion target on exit.
clicks Record<string, TargetAndTransition> {} Apply from a click on: { "click-1": { x: 40 }, "click-2": { y: 60 } }.
at string | number Tie the whole thing to a click step (like v-click + v-motion).
transition Transition<any> motion transition options.
className string
style CSSProperties
as "div" | "h1" | "h2" | "h3" | "img" | "li" | "p" | "span" "div" Element to render.

Cards, glows and text effects. They read the theme’s tokens and take a tone.

Blob · Chip · Divider · Glass · Glow · GradientText · Halo · Icon · Ribbon · Shimmer · Tilt

A soft organic colour blob for decoration.

<Blob color="var(--deck-accent-2)" x="80%" y="20%" />
Prop Type Default
color string CSS colour.
x string "50%" CSS left.
y string "50%" CSS top.
size string "40%" CSS size.
rotate number 0 Degrees.
opacity number 0.5 0–1.
className string

A pill with an optional lucide icon.

<Chip tone="good" icon="check">Shipped</Chip>
Prop Type Default
tone Tone "neutral" One of: accent, accent-2, good, warn, bad, info, neutral, purple, pink, amber, teal.
icon string A lucide icon name (kebab-case).
className string

A horizontal rule with an optional centred label.

<Divider label="Part two" />
Prop Type Default
label ReactNode
className string

A frosted card. Cards that share a row share a height.

<Glass tone="accent" glow>
**42 ms** p95
</Glass>
Prop Type Default
className string
tone Tone "neutral" One of: accent, accent-2, good, warn, bad, info, neutral, purple, pink, amber, teal.
pad string "1em" CSS padding.
glow boolean false Coloured glow.
style CSSProperties

A soft blurred light behind the content.

<Glow color="var(--deck-accent)" x="70%" y="30%" />
Prop Type Default
color string CSS colour.
size string "60%" CSS size.
x string "50%" CSS left.
y string "50%" CSS top.
opacity number 0.35 0–1.
className string

Text filled with a gradient (theme accents by default).

# <GradientText>Ship it.</GradientText>
Prop Type Default
from string Start colour.
to string End colour.
angle number 90 Degrees.
className string
as "h1" | "h2" | "h3" | "span" | "strong" "span" Element.

A ring of light around an icon or emoji.

<Halo tone="accent"><Icon name="sparkles" /></Halo>
Prop Type Default
tone Tone "accent" One of: accent, accent-2, good, warn, bad, info, neutral, purple, pink, amber, teal.
size string "3.2em" CSS size.
className string

A Lucide icon by name, or any Iconify icon as set:name (mdi:account, logos:vue). The tag form <mdi-account /> compiles to this. Built decks bundle the drawings from the deck’s installed @iconify-json/<set> (or @iconify/json); the hosted shell, or a set not installed, fetches them from the Iconify API once and keeps them.

<Icon name="rocket" size="2em" /> <Icon name="mdi:account-circle" color="tomato" /> <logos-react class="text-3xl" />
Prop Type Default
name required string A Lucide name (rocket), or any Iconify icon as set:name (mdi:account, logos:vue).
size string | number "1em" Height: CSS size or px (the width follows the icon’s proportions). Tag form: 1.2em.
color string CSS colour (monochrome icons).
strokeWidth number 1.75 Lucide icons only.
className string
class string Another spelling of className.
style string | CSSProperties An object, or a CSS string (style="color: tomato").
title string An accessible name; without one the icon is decorative.

A corner ribbon on the slide.

<Ribbon tone="warn">Beta</Ribbon>
Prop Type Default
tone Tone "accent" One of: accent, accent-2, good, warn, bad, info, neutral, purple, pink, amber, teal.
corner "left" | "right" "right" left · right.

Text with a light sweeping across it.

## <Shimmer>Now live</Shimmer>
Prop Type Default
className string
as "h1" | "h2" | "span" | "strong" "span"

A card that tilts toward the pointer.

<Tilt><Glass>Hover me</Glass></Tilt>
Prop Type Default
className string
max number 8 Maximum tilt in degrees.

See Themes and backgrounds.

Background

A registered component background (by name) or custom children as an animated layer behind this slide’s content. Usually you set background: in frontmatter instead.

<Background name="aurora" opacity={0.6} />
Prop Type Default
name string A registered background name (see backgrounds).
opacity number 1 0–1.
className string

Components that talk to the deck’s room. See The live room.

Leaderboard · Pace · Poll · Presence · QrJoin · Questions · Quiz · Reactions · WordCloud

The quiz leaderboard.

<Leaderboard top={5} />
Prop Type Default
top number 8 How many places.
className string

A gauge of the audience’s slower/faster feedback.

<Pace />
Prop Type Default
className string

A poll the presenter opens; the audience answers from their phones. Kinds: choice, multi, rating, words.

<Poll id="lunch" question="Lunch?" options={["Dosa", "Biryani", "Both"]} />
Prop Type Default
id required string Stable id, unique in the deck (results are keyed by it).
question required string The question.
options string[] [] Answers (choice and multi).
kind PollKind "choice" choice · multi · rating · words.
scale number 5 Points on a rating scale.
liveResults boolean true Show results as they come, or only once closed.
className string

How many people are following.

<Presence />
Prop Type Default
className string

The QR code and short link for the audience page — put it on the title or first slide.

<QrJoin size={300} />
Prop Type Default
size number 260 Pixels.
caption string "Scan to follow along, react and ask" Text under the code.
className string

The audience’s questions, most upvoted first.

## Questions?
<Questions limit={5} />
Prop Type Default
limit number 6 How many to show.
className string

A timed quiz question with points for speed; feeds the leaderboard.

<Quiz id="q1" question="2 + 2?" options={["3", "4", "5"]} correct={1} seconds={15} />
Prop Type Default
id required string Stable id, unique in the deck.
question required string The question.
options required string[] Answers.
correct required number 0-based index of the right answer.
seconds number 20 Time limit.
className string

A reaction bar on the slide (the audience page always has one).

<Reactions />
Prop Type Default
className string

The audience answers in a word or two; the words grow as they repeat.

<WordCloud id="one-word" question="One word for this talk?" />
Prop Type Default
id required string Stable id, unique in the deck.
question required string The prompt.
className string

See Glossary term cards.

Term · TermReadout · Terms

A glossary term card by hand: the entry named by its text or id, or a one-off with def. The compiler links first mentions from glossary.yaml automatically.

<Term>UTM</Term> · <Term id="utm">projected metres</Term> · <Term def="Root-mean-square error." tag="Statistics">RMSE</Term>
Prop Type Default
id string The glossary entry (its id, name or alias). Without it the children’s text is looked up.
def string A one-off definition (inline Markdown). With it, the glossary is not consulted.
more string
title string The card’s title for a one-off; defaults to the children’s text.
full string An abbreviation’s expansion.
tag string Category chip.
link string Source URL.
html string Set by the compiler: def/more already rendered (with KaTeX), and an automatic link.
moreHtml string
auto boolean Internal (set by the compiler).

The open term’s definition as page content, for a page whose slide is too small for a card (custom audience pages).

<TermReadout />
Prop Type Default
className string

Links glossary mentions inside a plain string at render time — for words that arrive as a prop, which the compiler cannot see.

<small><Terms>{"GNSS accuracy in UTM metres"}</Terms></small>

What plain Markdown renders through. You rarely write these tags yourself.

Anchor · Li · Ol · Ul

The a mapping: [text](#/3) and other in-deck hash links navigate; external links open in a new tab.

[the results slide](#/results) · [docs](https://deck.kadal.cc/docs/)
Prop Type Default
href string

The li mapping: a plain item, or a click step inside <Clicks>.

- each item renders through this

The ol mapping behind numbered Markdown lists.

1. a numbered list renders through this
Prop Type Default
className string

The ul mapping behind Markdown bullet lists; <Clicks> steps its items.

- a Markdown list renders through this
Prop Type Default
className string

Send feedback