Components
MDX element map
Section titled “MDX element map”mdxComponents (from @liebstoeckel/components, wired by the engine’s MDXProvider) maps Markdown to themed elements: h1 (display serif), h2 (text-primary), p (font-body text-muted), ul/li (accent bullets), strong (text-accent), inline code (themed pill), and fenced code (Shiki, brand-bound). Just write Markdown. No imports needed for these.
Slide components
Section titled “Slide components”From @liebstoeckel/engine (see Engine API):
<Step>: a reveal.<CodeMagic steps title? lang?>: animated code.<Magic id className?>: Magic Move, morph different stateless elements (sameid) between slides.<Slot id className?>: place the same stateful element (defined viapersistent) on a slide; it travels/snaps/fades across slides.<Plugin id props? components?>: place a live plugin.
Slide layouts
Section titled “Slide layouts”@liebstoeckel/components ships ready-made layouts for the common slide shapes, so a
deck (or an agent writing one) can compose a full presentation without hand-building
each slide. All of them animate in with the house motion style, scale their type down
as content volume grows, and reflow (e.g. into two columns) before content would
overflow the 1280x720 stage.
| Component | Props | Use |
|---|---|---|
TitleSlide | title, kicker?, subtitle?, byline?, date? | opening slide |
SectionSlide | title, index?, subtitle? | numbered section divider |
BulletsSlide | title, bullets, kicker? | staggered list; bullets are strings or { text, detail? }; heavy lists flow into two columns |
TwoColumnSlide | title, left, right, kicker? | side-by-side Columns (heading?, text?, bullets?, children?) |
QuoteSlide | quote, attribution?, role? | full-stage pull quote |
BigStatSlide | stats, title?, kicker?, aside? | headline numbers; each Stat (value, label, prefix?, suffix?, decimals?, note?) counts up on entry |
ChartSlide | title, children, kicker?, insight?, aside? | frame for a chart (e.g. a registry chart) with an insight line |
ClosingSlide | title, subtitle?, contact?, url? | final slide |
The building blocks are exported too, for custom slides that should match:
Kicker (uppercase eyebrow label), SlideHeading (animated heading; size it with
headingSize(text, "hero" | "large" | "medium"), which steps the type down as the text
gets longer), Caption, AnimatedNumber (value, prefix?, suffix?, decimals?),
and layoutEase (the shared easing curve).
import { BulletsSlide } from "@liebstoeckel/components";
export default function Agenda() { return ( <BulletsSlide kicker="Agenda" title="Where we are going" bullets={[ { text: "The problem", detail: "why decks rot in binary formats" }, "One self-contained .html", "Live sessions and plugins", ]} /> );}Plugin UI primitives
Section titled “Plugin UI primitives”From @liebstoeckel/plugin-ui, used inside plugin client surfaces. They style against var(--brand-*) so they’re automatically on-brand.
| Component | Props | Use |
|---|---|---|
Card | style?, className? | translucent surface container |
Button | onClick?, active?, disabled?, style? | full-width option/action button |
Bar | pct, color?, label, value?, highlight? | animatable result bar (0 to 100) |
Stack | gap?, style? | vertical flex stack |
ScrollArea | maxHeight?, style?, className? | bounded, internally-scrolling region. Cap unbounded plugin content so it doesn’t overflow the fixed slide canvas |
Eyebrow | (none) | uppercase mono label |
Also exported: useTheme() / readTheme() → ThemeTokens (resolved brand colors/fonts/viz for canvas or SVG use).
import { Card, Eyebrow, Bar, Button, Stack } from "@liebstoeckel/plugin-ui";
<Card style={{ width: "100%", maxWidth: 460 }}> <Eyebrow>Live poll · 12 votes</Eyebrow> <Stack> <Bar pct={75} label="Yes" value="9 · 75%" highlight /> <Bar pct={25} label="No" value="3 · 25%" /> </Stack> <Button active>Vote</Button></Card>Code-first presentations your agent can author. One file out, no server.
Comments