Reference

Plugins

Optional add-ons · activated by an attribute on deck-root or an explicit import. None of them are in the core bundle · they fetch on first use only.

The four plugins

Rikiki ships four optional modules. The core (dist/index.js, ~12 KB gzip) doesn't load any of them. Each one fetches separately the first time it's needed, so a deck that doesn't use a plugin pays nothing for it.

PluginSize (gz)Activated byUse-case
deck-transition ~1.7 KB transition="..." attr on deck-root Slide-in / fade / zoom / flip animations between slides
deck-presenter ~2.9 KB Press P Speaker window with notes + next-slide preview + timer
shiki-plugin ~0.6 KB + Shiki from CDN Explicit import + installShiki() Production-grade syntax highlighting for deck-code
deck-notes ~0.4 KB (auto-loaded with core) Use the deck-notes element Speaker notes (read by deck-presenter)

deck-transition · animations between slides

Setting a transition attribute on deck-root triggers a lazy import of the plugin on first navigation. The plugin then cross-fades both the outgoing and incoming slides on every navigation (no background flash regardless of slide colors).

basic usage
<!-- Set on deck-root · the entire deck animates -->
<deck-root transition="slide">
  <deck-cover>...</deck-cover>
  <deck-section>...</deck-section>
  <deck-feature>...</deck-feature>
</deck-root>

Available transitions

ValueEffectDefault duration
slide Auto-directional horizontal. Forward enters from the right, backward from the left.560 ms
slide-right Same as slide but starts in the left-to-right direction (still auto-flips on backward nav).560 ms
slide-up Auto-directional vertical. Forward enters from below, backward from above.520 ms
slide-down Mirror of slide-up.520 ms
fade Soft scale-up · the default if no value matches.480 ms
zoom Aggressive scale-up with spring ease (good for hooks/punchlines).520 ms
flip 3D rotateY · subtle card-flip feel.560 ms

Per-slide override

Set data-transition on any slide host to override the deck-wide default for that slide only.

per-slide
<!-- Per-slide override · data-transition wins over the parent attribute -->
<deck-root transition="fade">
  <deck-cover>...</deck-cover>
  <deck-section data-transition="zoom">...</deck-section>
  <deck-takeaway data-transition="flip">...</deck-takeaway>
</deck-root>

All transitions are transform-only · no opacity, no background animation, no flashing. Honours prefers-reduced-motion: reduce (animations disable cleanly).

deck-presenter · speaker window

Press P during the talk · a popup window opens (you'll need to allow popups for the deck's origin). The window shows:

  • Current slide · live mirror of what the audience sees
  • Next slide · preview of what's coming
  • Speaker notes · the text content of deck-notes inside the current slide
  • Timer · auto-starts, pause / resume / reset buttons
  • Slide counter · current / total

The popup syncs with the main deck via BroadcastChannel · no localStorage races, no postMessage ceremony. Forward keyboard input from the popup also drives the main deck, so you can use one laptop with the second screen mirroring the audience view.

Speaker notes · the deck-notes element

Add deck-notes inside any slide host. The element is hidden in the audience view (:host { display: none }) and read by the presenter window via textContent. Free-form text · use markdown-style bullets if you want, but it's rendered as white-space: pre-wrap.

notes example
<deck-root>
  <deck-cover>
    <h1>Hello</h1>
  </deck-cover>
  <deck-feature>
    <h1 slot="title">My slide</h1>
    <p slot="lead">Audience sees this.</p>

    <deck-notes>
      Speaker-only text. Only visible in the presenter window.
      - Bullet point one
      - Pause for laughter
      - Mention the rollout date
    </deck-notes>
  </deck-feature>
</deck-root>

shiki-plugin · production code highlighting

The default deck-code highlighter is a hand-rolled regex pass (~10 keywords per language, no template literal awareness, no JSX). Good enough for blog snippets, brittle for serious prod code.

Opt in to Shiki when you need real syntax highlighting · TextMate grammars, full theme set, JSX/TSX, template literal interpolation. Shiki itself is ~300 KB · the plugin fetches it from esm.sh on first use, so the cost is paid only if you opt in.

install shiki
<!doctype html>
<html>
<head>
  <link rel="stylesheet" href="rikiki/themes/rikiki.css">
  <script type="module" src="rikiki/dist/index.js"></script>

  <!-- Opt-in Shiki highlighter · pulls Shiki from esm.sh on first highlight -->
  <script type="module">
    import { installShiki } from './rikiki/dist/shiki-plugin.js';
    await installShiki({
      theme: 'one-dark-pro',
      langs: ['ts', 'tsx', 'html', 'css', 'json'],
    });
  </script>
</head>
<body>
  <deck-root>
    <deck-feature>
      <h1 slot="title">Real syntax</h1>
      <deck-code lang="ts" hero>
        const fn = <T,>(x: T): T => x;
      </deck-code>
    </deck-feature>
  </deck-root>
</body>
</html>

After install, every existing and future deck-code instance re-renders through Shiki. Languages that aren't loaded fall back to the regex highlighter so the deck never breaks.

Cost model

Plugin costs are paid only when you opt in:

  • A deck without transition on its root never fetches deck-transition.js.
  • A deck without an installShiki() call never fetches Shiki.
  • Speaker who never presses P never fetches deck-presenter.js.
  • deck-notes ships with the core (0.4 KB) but if you don't use the element, it's just one unused custom-element registration.

Core (dist/index.js) stays at ~12 KB gzip regardless of which plugins your deck eventually uses.