rikiki-deck 0.6.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/rikiki-debug/SKILL.md +17 -7
- package/.claude/skills/rikiki-deck/SKILL.md +362 -77
- package/.claude/skills/rikiki-theme/SKILL.md +1 -1
- package/README.md +69 -50
- package/bin/lib/assemble.mjs +154 -0
- package/bin/lib/box-geometry.mjs +66 -0
- package/bin/lib/browser.mjs +302 -0
- package/bin/lib/check-api.d.ts +28 -0
- package/bin/lib/check-api.mjs +6 -0
- package/bin/lib/check-plugins.mjs +228 -0
- package/bin/lib/check.mjs +1347 -0
- package/bin/lib/cli-error.mjs +26 -0
- package/bin/lib/component-deps.mjs +69 -0
- package/bin/lib/diff.mjs +275 -0
- package/bin/lib/export-pdf.mjs +65 -0
- package/bin/lib/graph-hit.mjs +86 -0
- package/bin/lib/inline.mjs +137 -39
- package/bin/lib/narrative.mjs +77 -0
- package/bin/lib/prune-icons.mjs +104 -0
- package/bin/lib/render.mjs +195 -0
- package/bin/lib/scan-external.mjs +126 -0
- package/bin/lib/starter.mjs +27 -14
- package/bin/lib/visual.mjs +120 -0
- package/bin/rikiki.mjs +420 -35
- package/dist/annotation-marks.d.ts +60 -0
- package/dist/annotation-marks.js +1 -0
- package/dist/bar-segments.d.ts +28 -0
- package/dist/bar-segments.js +1 -0
- package/dist/browser-location.d.ts +3 -0
- package/dist/browser-location.js +1 -0
- package/dist/cards-syntax.d.ts +31 -0
- package/dist/cards-syntax.js +6 -0
- package/dist/{plugins/click-stages.d.ts → click-stages.d.ts} +1 -1
- package/dist/deck-agenda.d.ts +25 -0
- package/dist/deck-agenda.js +6 -0
- package/dist/deck-annotate.d.ts +108 -0
- package/dist/deck-annotate.js +18 -0
- package/dist/deck-bar.d.ts +32 -0
- package/dist/deck-bar.js +19 -0
- package/dist/deck-bento.d.ts +38 -0
- package/dist/deck-bento.js +4 -0
- package/dist/{molecules/deck-callout.d.ts → deck-callout.d.ts} +2 -0
- package/dist/deck-callout.js +1 -1
- package/dist/deck-cell.d.ts +19 -0
- package/dist/deck-cell.js +1 -0
- package/dist/deck-checklist.d.ts +20 -0
- package/dist/deck-checklist.js +1 -0
- package/dist/{layouts/deck-cover.d.ts → deck-cover.d.ts} +8 -0
- package/dist/deck-cover.js +9 -6
- package/dist/deck-csv.d.ts +38 -0
- package/dist/deck-csv.js +15 -0
- package/dist/deck-feature-cards.js +2 -2
- package/dist/deck-feature.d.ts +18 -0
- package/dist/deck-feature.js +2 -2
- package/dist/deck-figure.d.ts +26 -0
- package/dist/deck-figure.js +8 -0
- package/dist/deck-fit.d.ts +14 -0
- package/dist/deck-fit.js +1 -0
- package/dist/deck-flow.d.ts +41 -0
- package/dist/deck-flow.js +7 -0
- package/dist/deck-graph.d.ts +92 -0
- package/dist/deck-graph.js +25 -0
- package/dist/deck-grid.js +1 -1
- package/dist/deck-icon.d.ts +20 -0
- package/dist/deck-icon.js +1 -0
- package/dist/{atoms/deck-kicker.d.ts → deck-kicker.d.ts} +5 -0
- package/dist/deck-kicker.js +1 -1
- package/dist/deck-kpi-grid.d.ts +26 -0
- package/dist/deck-kpi-grid.js +4 -0
- package/dist/deck-link.d.ts +21 -0
- package/dist/deck-link.js +1 -0
- package/dist/{molecules/deck-md.d.ts → deck-md.d.ts} +3 -0
- package/dist/deck-md.js +8 -3
- package/dist/deck-mermaid.js +15 -3
- package/dist/deck-outline.d.ts +50 -0
- package/dist/deck-outline.js +1 -0
- package/dist/deck-overview.js +53 -39
- package/dist/deck-persona.d.ts +31 -0
- package/dist/deck-persona.js +6 -0
- package/dist/deck-photo.js +1 -1
- package/dist/deck-point.d.ts +22 -0
- package/dist/deck-point.js +1 -0
- package/dist/deck-presenter.js +120 -48
- package/dist/deck-pull.d.ts +13 -0
- package/dist/deck-pull.js +1 -0
- package/dist/{atoms/deck-punch.d.ts → deck-punch.d.ts} +6 -0
- package/dist/deck-punch.js +1 -1
- package/dist/deck-quote.d.ts +28 -0
- package/dist/deck-quote.js +6 -0
- package/dist/{runtime/deck-root.d.ts → deck-root.d.ts} +88 -8
- package/dist/deck-root.js +17 -13
- package/dist/deck-section.js +2 -2
- package/dist/deck-source.d.ts +12 -0
- package/dist/deck-source.js +2 -0
- package/dist/deck-split.d.ts +30 -0
- package/dist/deck-split.js +5 -3
- package/dist/{molecules/deck-stat.d.ts → deck-stat.d.ts} +2 -0
- package/dist/deck-stat.js +2 -2
- package/dist/{molecules/deck-step-list.d.ts → deck-step-list.d.ts} +8 -0
- package/dist/deck-step-list.js +4 -2
- package/dist/deck-table.d.ts +26 -0
- package/dist/deck-table.js +1 -0
- package/dist/deck-takeaway.d.ts +18 -0
- package/dist/deck-takeaway.js +2 -2
- package/dist/deck-timeline.d.ts +37 -0
- package/dist/deck-timeline.js +5 -0
- package/dist/deck-transition.js +3 -3
- package/dist/deck-versus.d.ts +18 -0
- package/dist/deck-versus.js +9 -0
- package/dist/deep-link.d.ts +29 -0
- package/dist/deep-link.js +1 -0
- package/dist/escape-html.d.ts +3 -0
- package/dist/escape-html.js +1 -0
- package/dist/fit-controller.d.ts +27 -0
- package/dist/fit-controller.js +1 -0
- package/dist/graph-layout.d.ts +35 -0
- package/dist/graph-layout.js +1 -0
- package/dist/grid-tracks.d.ts +17 -0
- package/dist/grid-tracks.js +1 -0
- package/dist/icon-set.d.ts +6 -0
- package/dist/icon-set.js +1 -0
- package/dist/index.d.ts +37 -31
- package/dist/index.js +95 -49
- package/dist/keymap.d.ts +40 -0
- package/dist/keymap.js +1 -0
- package/dist/mouse-nav.d.ts +12 -0
- package/dist/mouse-nav.js +1 -0
- package/dist/navigation.d.ts +25 -0
- package/dist/navigation.js +1 -0
- package/dist/parse-csv.d.ts +9 -0
- package/dist/parse-csv.js +3 -0
- package/dist/shared-styles.js +1 -1
- package/dist/shiki.d.ts +8 -0
- package/dist/signature.d.ts +2 -0
- package/dist/signature.js +1 -0
- package/dist/slide-fill.d.ts +8 -0
- package/dist/slide-fill.js +1 -0
- package/dist/standalone.js +301 -169
- package/dist/vendor/THIRD-PARTY-NOTICES.txt +4347 -0
- package/dist/vendor/inventory.json +3029 -0
- package/dist/vendor/lit.js +62 -2
- package/dist/vendor/mermaid.min.js +95 -95
- package/dist/vendor/shiki.js +1 -57
- package/dist/viewport.d.ts +42 -0
- package/dist/viewport.js +1 -0
- package/docs/llms/rikiki-reference.md +955 -64
- package/docs/llms/rikiki-workflow.md +536 -0
- package/llms.txt +39 -12
- package/package.json +33 -12
- package/themes/rikiki.css +173 -47
- package/themes/siliceum.css +171 -51
- package/dist/layouts/deck-feature.d.ts +0 -11
- package/dist/layouts/deck-split.d.ts +0 -18
- package/dist/layouts/deck-takeaway.d.ts +0 -11
- package/dist/plugins/shiki.d.ts +0 -8
- /package/dist/{runtime/color.d.ts → color.d.ts} +0 -0
- /package/dist/{atoms/deck-badge.d.ts → deck-badge.d.ts} +0 -0
- /package/dist/{molecules/deck-card.d.ts → deck-card.d.ts} +0 -0
- /package/dist/{atoms/deck-code-highlighter.d.ts → deck-code-highlighter.d.ts} +0 -0
- /package/dist/{atoms/deck-code.d.ts → deck-code.d.ts} +0 -0
- /package/dist/{layouts/deck-feature-cards.d.ts → deck-feature-cards.d.ts} +0 -0
- /package/dist/{molecules/deck-grid.d.ts → deck-grid.d.ts} +0 -0
- /package/dist/{runtime/deck-help.d.ts → deck-help.d.ts} +0 -0
- /package/dist/{molecules/deck-mermaid.d.ts → deck-mermaid.d.ts} +0 -0
- /package/dist/{molecules/deck-metric.d.ts → deck-metric.d.ts} +0 -0
- /package/dist/{runtime/deck-notes.d.ts → deck-notes.d.ts} +0 -0
- /package/dist/{runtime/deck-overview.d.ts → deck-overview.d.ts} +0 -0
- /package/dist/{layouts/deck-photo.d.ts → deck-photo.d.ts} +0 -0
- /package/dist/{runtime/deck-presenter.d.ts → deck-presenter.d.ts} +0 -0
- /package/dist/{layouts/deck-section.d.ts → deck-section.d.ts} +0 -0
- /package/dist/{molecules/deck-shortcut.d.ts → deck-shortcut.d.ts} +0 -0
- /package/dist/{molecules/deck-stack.d.ts → deck-stack.d.ts} +0 -0
- /package/dist/{molecules/deck-tier-list.d.ts → deck-tier-list.d.ts} +0 -0
- /package/dist/{runtime/deck-transition.d.ts → deck-transition.d.ts} +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Rikiki · LLM reference
|
|
2
2
|
|
|
3
|
-
This reference documents rikiki v0.
|
|
3
|
+
This reference documents rikiki v0.7.2.
|
|
4
4
|
|
|
5
5
|
Exhaustive, self-consistent reference for authoring valid **rikiki** decks. Every
|
|
6
6
|
tag, attribute, slot, and token below was derived from the source in this repo
|
|
7
|
-
(`
|
|
7
|
+
(`dist/index.js` registers every component; `themes/rikiki.css` is the
|
|
8
8
|
canonical token list). Do not invent tags, attributes, or tokens · use only what
|
|
9
9
|
is listed here.
|
|
10
10
|
|
|
@@ -34,7 +34,8 @@ navigation, hash routing, the progress bar, step dots, and the keyboard hint.
|
|
|
34
34
|
|
|
35
35
|
## 2 · Minimal deck
|
|
36
36
|
|
|
37
|
-
The canonical skeleton
|
|
37
|
+
The canonical skeleton · `rikiki init <name>.html` writes exactly this, with the
|
|
38
|
+
runtime copied into `./rikiki/` beside it:
|
|
38
39
|
|
|
39
40
|
```html
|
|
40
41
|
<!doctype html>
|
|
@@ -226,13 +227,22 @@ Direct children of `<deck-root>`. Each is one slide.
|
|
|
226
227
|
|
|
227
228
|
| Tag | Purpose | Key attributes | Slots |
|
|
228
229
|
|-----|---------|----------------|-------|
|
|
229
|
-
| `deck-cover` | Opening slide, dark, with brand + meta | `brand` (split on " · "), `brand-src` (logo URL), `speaker`, `company`, `duration`, `audience`, `runtime`; per-row label overrides `speaker-label`, `company-label`, `duration-label`, `audience-label`, `runtime-label` | default `<h1>`, `.sub`/`p[slot=sub]` |
|
|
230
|
+
| `deck-cover` | Opening slide, dark, with brand + meta | `brand` (split on " · "), `brand-src` (logo URL), `speaker`, `company`, `company-src` (client logo URL, shown before the company name), `duration`, `audience`, `runtime`; per-row label overrides `speaker-label`, `company-label`, `duration-label`, `audience-label`, `runtime-label` | default `<h1>`, `.sub`/`p[slot=sub]` |
|
|
230
231
|
| `deck-section` | Chapter divider (also a chapter boundary for 2D nav) | `num` | default `<h1>` (may use `<em>`) |
|
|
231
232
|
| `deck-feature` | Headline + lead + one focal block | `eyebrow` | `title` (`<h1>`), `lead`, default (focal block, e.g. `deck-code`) |
|
|
232
233
|
| `deck-split` | Two or three columns side by side | `eyebrow`, `cols` (`1-1`/`1-2`/`2-1`/`3`), `gap` (1..6 or raw CSS length), `col-gap` (1..6 or raw CSS length) | `title`, `lead`; `left`/`right` (2-col) or `a`/`b`/`c` (3-col) |
|
|
233
234
|
| `deck-feature-cards` | Hero focal block + two detail cards under it | `eyebrow` | `title`, `lead`, default (hero block), `left`, `right` |
|
|
234
235
|
| `deck-photo` | Full-bleed image slide, content on overlay | `src` (required), `position` (CSS `object-position`, default `center`), `darken` (0..1 overlay alpha, default `0.35`), `align` (top/center/bottom, default center), `text-align` (left/center/right, default left) | default slot: any content; style slotted children with `.sub`/`.kicker` classes (these are **CSS classes**, not named slots) |
|
|
235
236
|
| `deck-takeaway` | Centered punchline, dark | `kicker` | default (e.g. `p.display`, `p.caption`, a `deck-callout`) |
|
|
237
|
+
| `deck-bento` | Bento grid slide · multi-row/column cells share the space | `eyebrow`, `cols` (1..12 or template, default 2), `rows` (1..12 or template, default 1 full-height row), `gap` (1..6 or CSS, default 3), `align`, `justify` | `title` (`<h1>`), default (`deck-point` / `deck-cell` children) |
|
|
238
|
+
|
|
239
|
+
`eyebrow` renders as a short accent-coloured line above the title, in sentence
|
|
240
|
+
case. Write it as a word or two, the way you would say it · "numbers", not
|
|
241
|
+
"NUMBERS". It used to render as a filled pill holding tracked-out small caps,
|
|
242
|
+
which is unreadable at projection distance and is one of the plainest marks of a
|
|
243
|
+
generated page (ADR-002). The tokens are unchanged, so a deck that wants the
|
|
244
|
+
badge back sets `--deck-eyebrow-bg`, `--deck-eyebrow-color`,
|
|
245
|
+
`--deck-eyebrow-radius` and `--deck-eyebrow-padding-x` / `-y`.
|
|
236
246
|
|
|
237
247
|
---
|
|
238
248
|
|
|
@@ -240,23 +250,27 @@ Direct children of `<deck-root>`. Each is one slide.
|
|
|
240
250
|
|
|
241
251
|
| Tag | Purpose | Key attributes | Slots / children |
|
|
242
252
|
|-----|---------|----------------|------------------|
|
|
243
|
-
| `deck-callout` | Highlighted note box | `type` (`info`/`warn`/`danger`/`ok`) | default (text / `deck-md`) |
|
|
253
|
+
| `deck-callout` | Highlighted note box | `type` (`info`/`warn`/`danger`/`ok`), `on-dark` (inverse text on a dark raised surface, for a dark slide) | default (text / `deck-md`) |
|
|
244
254
|
| `deck-card` | Tinted card | `color` (`yellow`/`orange`/`green`/`red`), `center`, `compact` | default (`<h3>` + body) |
|
|
245
|
-
| `deck-md` | Render Markdown (GFM) | · | default = raw Markdown text |
|
|
246
|
-
| `deck-mermaid` | Render a Mermaid diagram (
|
|
255
|
+
| `deck-md` | Render Markdown (GFM) · also expands `::: cards` blocks into a tinted card grid | · | default = raw Markdown text |
|
|
256
|
+
| `deck-mermaid` | Render a Mermaid diagram (uses the optional vendored Mermaid runtime) | `compact` | default = Mermaid source |
|
|
247
257
|
| `deck-stat` | Big-number visual | `num`, `tone` (`yellow`/`orange`/`green`/`red`/`purple`/`lime`/`cyan`) | `claim` (`<h3>`), default = body line |
|
|
248
258
|
| `deck-metric-list` | Wraps `deck-metric` rows | · | `deck-metric` children |
|
|
249
259
|
| `deck-metric` | One metric row | `severity` (`bad`/`warn`/`ok`/`info`), `value`, `mono` (render the value in the mono font) | default = label |
|
|
250
260
|
| `deck-tier-list` | Tier ladder | · | `deck-tier`, `deck-tier-arrow` children |
|
|
251
261
|
| `deck-tier` | One tier row | `name`, `speed`, `severity` (`muted`/`warn`/`ok`/`hot`), `hot` | default = description text |
|
|
252
262
|
| `deck-tier-arrow` | Separator note between tiers | · | default = text |
|
|
253
|
-
| `deck-step-list` | Numbered step ladder |
|
|
254
|
-
| `deck-step` | One step row | `n`, `note` | default = label |
|
|
263
|
+
| `deck-step-list` | Numbered step ladder | `direction` (`column` default, `row` for a chain across the width), `no-connectors` | `deck-step` children (each one carries its own `note-position`) |
|
|
264
|
+
| `deck-step` | One step row | `n`, `note`, `note-position` (`inline` default / `below`, the note under the label rather than beside it) | default = label |
|
|
255
265
|
| `deck-shortcut-list` | Shortcut grid | `cols` (column count, e.g. `1`), `col-gap` (1..6) | `deck-shortcut` children |
|
|
256
266
|
| `deck-shortcut` | One keyboard-shortcut row | `keys` (space-separated), `label`, `note`, `tone` (`accent`/`ok`) | default = note |
|
|
257
267
|
| `deck-kbd` | Inline key chip | `tone` (`accent`/`ok`) | default = key text |
|
|
258
268
|
| `deck-stack` | Flex stack helper | `gap` (1..6), `direction` (`row`/`column`), `align` (`start`/`center`/`end`/`stretch`), `justify` (`start`/`center`/`end`/`between`/`around`), `fill` (grow to fill the cross axis) | children |
|
|
259
269
|
| `deck-grid` | CSS grid helper | `cols` (1..12 or template), `rows`, `gap` (1..6 or CSS), `align`, `justify`, `fill` | children |
|
|
270
|
+
| `deck-cell` | Bento grid item, sized BY THE GRID · a `container-type: size` box so child `cqw`/`cqh` type scales against the cell, not the slide. A slotted `img`/`svg`/`video` auto-fits the cell (object-fit contain); a slotted `table` fills the width | `span` (`"CxR"`, e.g. `2x1`, or a bare column count), `col`/`row` (per-axis override · integer → `span N`, else raw line syntax), `tone` (`info`/`warn`/`ok`/`danger`), `plain` (drop the card chrome), `flat` (keep the surface but drop the border), `align` (**horizontal**: `start`/`center`/`end`/`stretch`), `justify` (**vertical**: `start`/`center`/`end`/`between`) | default (`<h3>` + body, or any block) |
|
|
271
|
+
| `deck-point` | Bento grid item, sized BY ITS CONTENT · one point of a bento, for words. Not a size container, so a row of points is as tall as the tallest one and a painted point shows no hole under its text; a row made only of points, all with the same number of children and none claiming a span, shares the grid's rows, so a title that wraps to a second line no longer drags its own body text below its neighbours'. Reach for `deck-point` for words and `deck-cell` for anything measured (fit-to-cell text, a diagram, an image) | `span`, `col`/`row`, `tone` (`info`/`warn`/`ok`/`danger`), `plain` (stop painting the chrome · the gutter stays, so the reading edge survives), `flat`, `align` (**horizontal**) · no `justify`, a point has no leftover height to distribute | default (`<h3>` + body) |
|
|
272
|
+
| `deck-fit` | Shrink slotted content to fit its box by font-size (for non-`deck-punch` text content · not for images, which scale geometrically) | `min` (rem, default 1), `max` (rem, default 12) | default = any content |
|
|
273
|
+
| `deck-csv` | Render inline CSV as a styled table (cells are trimmed) | `delimiter` (default `,`), `no-header` (first row is data), `fit` (shrink the table to fit the cell), `fit-min`/`fit-max` (rem bounds, default 0.6/2), `highlight-rows` / `highlight-cols` (1-based, space-separated), `reveal` (one body row per step) | default = raw CSV text |
|
|
260
274
|
|
|
261
275
|
---
|
|
262
276
|
|
|
@@ -266,8 +280,9 @@ Direct children of `<deck-root>`. Each is one slide.
|
|
|
266
280
|
|-----|---------|----------------|-------|
|
|
267
281
|
| `deck-badge` | Small status badge | `type` (`bad`/`ok`/`info`/`warn`/`neutral`) | default = text |
|
|
268
282
|
| `deck-kicker` | Uppercase eyebrow label | `on-dark` | default = text |
|
|
269
|
-
| `deck-punch` | Short punchy line | `tone` (`warn`/`danger`/`ok`/`info`/`muted`/`accent`; inherits text color if absent), `size` (`lead`/`big`/`mega`/`stat`/`display`), `weight` (`700`/`800`/`900`), `align` (`left`/`center`/`right`) | default = text |
|
|
283
|
+
| `deck-punch` | Short punchy line | `tone` (`warn`/`danger`/`ok`/`info`/`muted`/`accent`; inherits text color if absent), `size` (`lead`/`big`/`mega`/`stat`/`display`), `weight` (`700`/`800`/`900`), `align` (`left`/`center`/`right`), `fit` (shrink to fit the box · overrides `size`/cqw fluid scaling), `fit-min`/`fit-max` (rem bounds, default 1/12) | default = text |
|
|
270
284
|
| `deck-code` | Syntax-highlighted code | `lang`, `hero`, `nested`, `step-groups` | default = code text |
|
|
285
|
+
| `deck-source` | A source or credit line, placed under any evidence block (`deck-csv`, `deck-table`, `deck-bar`, `deck-kpi-grid`, `deck-annotate`, or plain prose) | `href` (turns the credit into a link) | default = the credit text |
|
|
271
286
|
|
|
272
287
|
### deck-code details
|
|
273
288
|
|
|
@@ -276,8 +291,8 @@ Direct children of `<deck-root>`. Each is one slide.
|
|
|
276
291
|
`less`. **Any other value** (`python`, `rust`, `bash`, `go`, `sql`, …) is **not
|
|
277
292
|
an error and produces no warning** — the block is silently colored with the JS
|
|
278
293
|
rules, so the result looks plausible but is wrong. For any language outside the
|
|
279
|
-
list above,
|
|
280
|
-
|
|
294
|
+
list above, add or rebuild a compatible highlighter. Rikiki's optional Shiki
|
|
295
|
+
plugin covers a curated subset described below.
|
|
281
296
|
- `hero` · centers the block vertically as the slide's focal element.
|
|
282
297
|
- `nested` · lighter border, no shadow (for use inside a `deck-card`).
|
|
283
298
|
- `step-groups` · a JSON array attribute that turns the snippet into a stepped
|
|
@@ -285,13 +300,12 @@ Direct children of `<deck-root>`. Each is one slide.
|
|
|
285
300
|
|
|
286
301
|
Highlighting is done client-side with a built-in regex highlighter (no build
|
|
287
302
|
step), limited to the languages listed under `lang` above. An opt-in **Shiki
|
|
288
|
-
plugin
|
|
289
|
-
|
|
290
|
-
understand.
|
|
303
|
+
plugin upgrades every `deck-code` block to TextMate highlighting for a curated
|
|
304
|
+
set of common web languages.
|
|
291
305
|
|
|
292
306
|
### Shiki plugin (optional, opt-in)
|
|
293
307
|
|
|
294
|
-
|
|
308
|
+
The Shiki plugin (`dist/shiki.js`) re-renders all `<deck-code>` blocks
|
|
295
309
|
through [Shiki](https://shiki.style), loaded from the vendored
|
|
296
310
|
`dist/vendor/shiki.js` bundle on first use (offline · no CDN). Install it after
|
|
297
311
|
the rikiki bundle:
|
|
@@ -300,7 +314,7 @@ the rikiki bundle:
|
|
|
300
314
|
<script type="module" src="./dist/index.js"></script>
|
|
301
315
|
<script type="module">
|
|
302
316
|
import { installShiki } from './dist/shiki.js';
|
|
303
|
-
await installShiki({ theme: 'one-dark-pro', langs: ['ts', '
|
|
317
|
+
await installShiki({ theme: 'one-dark-pro', langs: ['ts', 'js', 'html', 'css'] });
|
|
304
318
|
</script>
|
|
305
319
|
```
|
|
306
320
|
|
|
@@ -308,13 +322,15 @@ API:
|
|
|
308
322
|
|
|
309
323
|
```ts
|
|
310
324
|
async function installShiki(opts?: {
|
|
311
|
-
theme?:
|
|
312
|
-
langs?:
|
|
325
|
+
theme?: 'one-dark-pro';
|
|
326
|
+
langs?: Array<'ts' | 'typescript' | 'js' | 'javascript' | 'html' | 'css' | 'json'>;
|
|
313
327
|
}): Promise<void>
|
|
314
328
|
```
|
|
315
329
|
|
|
316
|
-
-
|
|
317
|
-
`langs` to
|
|
330
|
+
- The offline artifact contains only `one-dark-pro` and the TypeScript,
|
|
331
|
+
JavaScript, HTML, CSS and JSON grammars. Set `langs` to the subset your deck
|
|
332
|
+
uses. Supporting another grammar or theme requires rebuilding the vendor
|
|
333
|
+
entry with an explicit import.
|
|
318
334
|
- Shiki owns the palette under this plugin: it colors each token with an inline
|
|
319
335
|
style from the chosen `theme`, so pick a `theme` that suits your code
|
|
320
336
|
background (e.g. `one-dark-pro` on a dark deck). The `--deck-code-syntax-*`
|
|
@@ -324,9 +340,8 @@ async function installShiki(opts?: {
|
|
|
324
340
|
- **How it hooks in:** it registers a highlighter on the shared `<deck-code>`
|
|
325
341
|
class via `setDeckCodeHighlighter` (resolved through `customElements.get`), so
|
|
326
342
|
it never patches the component's internals · see *Writing a plugin* below.
|
|
327
|
-
- **Trade-off:** the
|
|
328
|
-
|
|
329
|
-
~14 KB gzip.
|
|
343
|
+
- **Trade-off:** the curated runtime is about 113 KB when gzip-compressed. It remains opt-in and
|
|
344
|
+
lazy, so the core bundle stays ~43 KB gzip.
|
|
330
345
|
|
|
331
346
|
---
|
|
332
347
|
|
|
@@ -348,7 +363,7 @@ The step dots at the bottom of the deck reflect the active slide's step count.
|
|
|
348
363
|
|
|
349
364
|
### Click-stages plugin (per-element reveals)
|
|
350
365
|
|
|
351
|
-
`
|
|
366
|
+
The click-stages plugin (`dist/click-stages.js`) adds Slidev-style `v-click` reveals. rikiki drives
|
|
352
367
|
them with **attributes** (`data-click` on any element) · it does **not** support
|
|
353
368
|
Slidev's `<v-click>` / `<v-clicks>` wrapper elements. It is **opt-in** · not part
|
|
354
369
|
of the core bundle. Install it after rikiki loads:
|
|
@@ -488,20 +503,20 @@ It is hidden in the deck itself; only the presenter window reads its text.
|
|
|
488
503
|
|
|
489
504
|
---
|
|
490
505
|
|
|
491
|
-
## 9 · Multi-
|
|
506
|
+
## 9 · Multi-file decks
|
|
492
507
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
weight added).
|
|
508
|
+
A long talk is easier to write, review and diff in pieces. `rikiki assemble`
|
|
509
|
+
joins ordered partials into the single HTML file everything else expects.
|
|
496
510
|
|
|
497
511
|
A `deck.config.js` (or `.json`) describes the deck:
|
|
498
512
|
|
|
499
513
|
```js
|
|
500
514
|
export default {
|
|
501
515
|
title: 'My talk',
|
|
502
|
-
theme: '
|
|
503
|
-
bundle: '
|
|
504
|
-
transition: 'slide',
|
|
516
|
+
theme: 'rikiki/tokens.css', // href, relative to the OUTPUT file
|
|
517
|
+
bundle: 'rikiki/dist/index.js', // runtime href, relative to OUTPUT
|
|
518
|
+
transition: 'slide', // optional <deck-root transition="…">
|
|
519
|
+
lang: 'fr', // optional <html lang="…">
|
|
505
520
|
slides: [
|
|
506
521
|
'parts/cover.html',
|
|
507
522
|
'parts/intro.md',
|
|
@@ -514,38 +529,27 @@ export default {
|
|
|
514
529
|
- **`.md` partials** can hold one or many slides. A line that is exactly `---`
|
|
515
530
|
splits the file into separate slides (reveal.js convention); each chunk is
|
|
516
531
|
wrapped into its own `<deck-feature><deck-md>…</deck-md></deck-feature>`. Use
|
|
517
|
-
`***` for a horizontal rule inside a slide
|
|
532
|
+
`***` for a horizontal rule inside a slide, since `---` is the slide break.
|
|
518
533
|
|
|
519
534
|
Run it:
|
|
520
535
|
|
|
521
536
|
```bash
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
537
|
+
npx rikiki assemble deck.config.js # → <title>.html next to the config
|
|
538
|
+
npx rikiki assemble deck.config.js out/talk.html # explicit output
|
|
539
|
+
npx rikiki assemble deck.config.js - # to stdout
|
|
525
540
|
```
|
|
526
541
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
> The single-file export step (`bundle.mjs`, §12) only rewrites paths that use
|
|
533
|
-
> the `rikiki/…` convention · specifically references matching
|
|
534
|
-
> `rikiki/(dist|themes|tokens.css)` (as the decks under `examples/` do). It does
|
|
535
|
-
> **not** resolve plain relative paths like `../../dist/index.js`.
|
|
536
|
-
>
|
|
537
|
-
> The in-repo `decks/example` deliberately uses `../../dist/index.js` /
|
|
538
|
-
> `../../tokens.css` relative paths so it can be **served directly** for dev. As
|
|
539
|
-
> a result, `decks/example`'s assembled output is meant for direct serving and
|
|
540
|
-
> does **not** bundle via `bundle.mjs` as-is. To produce a bundleable assembled
|
|
541
|
-
> deck, point its `deck.config.js` `theme`/`bundle` at the `rikiki/…`-style paths
|
|
542
|
-
> that `bundle.mjs` rewrites.
|
|
542
|
+
`theme` and `bundle` default to the `rikiki/…` paths `rikiki init` writes, which
|
|
543
|
+
are the ones `rikiki bundle` inlines. Point them elsewhere and the deck still
|
|
544
|
+
serves, but the command says on stderr that the single-file export will leave
|
|
545
|
+
those references external.
|
|
543
546
|
|
|
544
|
-
|
|
547
|
+
Assembly is a one-way step: edit the partials, re-run, and keep the assembled
|
|
548
|
+
file as an artefact rather than a source.
|
|
545
549
|
|
|
546
550
|
## 10 · Livereload (authoring only)
|
|
547
551
|
|
|
548
|
-
`
|
|
552
|
+
The livereload module (`dist/livereload.js`) polls the `Last-Modified`/etag of the deck's files and
|
|
549
553
|
auto-reloads the page when any change (showing a brief toast and keeping the
|
|
550
554
|
current slide via the hash). It watches: the deck's `<link rel="stylesheet">`
|
|
551
555
|
hrefs, the rikiki component files in `dist/`, and the deck HTML itself.
|
|
@@ -553,7 +557,7 @@ hrefs, the rikiki component files in `dist/`, and the deck HTML itself.
|
|
|
553
557
|
Enable it two ways:
|
|
554
558
|
|
|
555
559
|
- **`?live`** on the deck URL · `dist/index.js` lazy-imports the poller only when
|
|
556
|
-
this query param is present, e.g. `…/
|
|
560
|
+
this query param is present, e.g. `…/my-deck.html?live`.
|
|
557
561
|
- **Load the module directly** · `<script type="module" src="./dist/livereload.js">`
|
|
558
562
|
(it auto-starts on import).
|
|
559
563
|
|
|
@@ -613,27 +617,264 @@ Light-DOM helper classes the theme ships (use on slotted children):
|
|
|
613
617
|
|
|
614
618
|
## 12 · Bundling (single-file export)
|
|
615
619
|
|
|
616
|
-
`bundle
|
|
617
|
-
|
|
618
|
-
|
|
620
|
+
`rikiki bundle` crawls a deck's `<link>` and `<script type="module">`
|
|
621
|
+
references and inlines everything, lit included, into one self-contained HTML
|
|
622
|
+
file. It curates the runtime down to the components the deck actually uses.
|
|
619
623
|
|
|
620
624
|
```bash
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
+
npx rikiki bundle my-talk/index.html # → my-talk/index.bundle.html
|
|
626
|
+
npx rikiki bundle my-talk/index.html out.html # explicit output
|
|
627
|
+
npx rikiki bundle my-talk/index.html - # to stdout
|
|
628
|
+
npx rikiki bundle my-talk/index.html --no-fonts # drop the web fonts, use system ones
|
|
629
|
+
npx rikiki bundle my-talk/index.html --with-mermaid # inline the mermaid runtime
|
|
630
|
+
npx rikiki bundle my-talk/index.html --with-shiki # inline the Shiki highlighter
|
|
625
631
|
```
|
|
626
632
|
|
|
627
|
-
The
|
|
628
|
-
|
|
633
|
+
The command needs the optional peer `rolldown` (`npm i -D rolldown`); without
|
|
634
|
+
it, it says so and does nothing. It exits non-zero if the result would still
|
|
635
|
+
fetch something at runtime, so a file it accepts really opens offline.
|
|
636
|
+
|
|
637
|
+
It resolves rikiki references written in the `rikiki/(dist|themes|tokens.css)`
|
|
638
|
+
spelling · the one `rikiki init` writes.
|
|
629
639
|
|
|
630
640
|
---
|
|
631
641
|
|
|
642
|
+
## 12b · Looking at a deck, and measuring it
|
|
643
|
+
|
|
644
|
+
You cannot see a deck you wrote. These two commands are the eyes and the ruler.
|
|
645
|
+
Both need the optional peer `playwright`.
|
|
646
|
+
|
|
647
|
+
### `rikiki render` · pictures
|
|
648
|
+
|
|
649
|
+
```bash
|
|
650
|
+
npx rikiki render talk.html # → talk.shots/, one PNG per slide
|
|
651
|
+
npx rikiki render talk.html --out previews/ # somewhere else
|
|
652
|
+
npx rikiki render talk.html --slides intro,4 # by id or by 1-based number
|
|
653
|
+
npx rikiki render talk.html --steps # every revealed state, not just the first
|
|
654
|
+
npx rikiki render talk.html --width 1280 --height 720
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
It writes, beside the pictures:
|
|
658
|
+
|
|
659
|
+
- `index.html` · a plain gallery, no runtime, opens offline;
|
|
660
|
+
- `manifest.json` · the contract between a picture and the slide it came from.
|
|
661
|
+
|
|
662
|
+
```json
|
|
663
|
+
{
|
|
664
|
+
"schema": 1,
|
|
665
|
+
"deck": "talk.html",
|
|
666
|
+
"canvas": { "width": 1920, "height": 1080 },
|
|
667
|
+
"slideCount": 12,
|
|
668
|
+
"captured": 12,
|
|
669
|
+
"stepsCaptured": false,
|
|
670
|
+
"shots": [
|
|
671
|
+
{ "index": 1, "id": "intro", "tag": "deck-cover", "title": "…", "step": 0, "file": "01-intro.png" }
|
|
672
|
+
]
|
|
673
|
+
}
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
Read `stepsCaptured`. Without `--steps`, a stepped slide is photographed in its
|
|
677
|
+
opening state, which is usually the emptiest one it has: judging it then is
|
|
678
|
+
judging a slide nobody will see. File names are derived from the slide id and
|
|
679
|
+
are always safe, whatever the id contains; the manifest keeps the id verbatim,
|
|
680
|
+
which is what you edit against.
|
|
681
|
+
|
|
682
|
+
The command waits for the elements to upgrade, the fonts to load, the diagrams
|
|
683
|
+
to draw and every animation to finish before each shot. It does not sleep.
|
|
684
|
+
|
|
685
|
+
#### `--baseline <dir>` · what moved since last time
|
|
686
|
+
|
|
687
|
+
```bash
|
|
688
|
+
npx rikiki render talk.html --out after/ --baseline before/
|
|
689
|
+
npx rikiki render talk.html --out after/ --baseline before/ --json > diff.json
|
|
690
|
+
npx rikiki render talk.html --out after/ --baseline before/ --threshold 0
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
The deck is rendered as usual, then every PNG that has a same-named file in
|
|
694
|
+
`<dir>` is compared to it, in the browser that just took the pictures: both
|
|
695
|
+
images go on a canvas and `getImageData` counts the pixels whose worst channel
|
|
696
|
+
moved by more than 32 of 255. A file only one side has is reported as `added`
|
|
697
|
+
or `missing`, never as a diff; two captures of different sizes are `resized`,
|
|
698
|
+
with both sizes and no pixel count, because a ratio across a resize means
|
|
699
|
+
nothing.
|
|
700
|
+
|
|
701
|
+
Human output goes to stderr, one line per changed slide, most changed first:
|
|
702
|
+
|
|
703
|
+
```
|
|
704
|
+
rikiki · diff · 1 slide(s) changed · most changed first
|
|
705
|
+
· 9.21% 01-intro.png · Le titre de la slide · box 101,383 1204×323
|
|
706
|
+
rikiki · diff · 1 changed · 11 stable · 0 added · 0 missing · 0 resized · baseline before/
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
`--json` writes the whole report to stdout and nothing else; the same report is
|
|
710
|
+
always written to `diff.json`, beside `manifest.json`:
|
|
711
|
+
|
|
712
|
+
```json
|
|
713
|
+
{
|
|
714
|
+
"schema": "rikiki.render-diff/1",
|
|
715
|
+
"baseline": "/abs/path/to/before",
|
|
716
|
+
"threshold": 0.5,
|
|
717
|
+
"slides": [
|
|
718
|
+
{
|
|
719
|
+
"file": "01-intro.png",
|
|
720
|
+
"slide": 1, "id": "intro", "title": "…", "step": 0,
|
|
721
|
+
"status": "changed",
|
|
722
|
+
"changedRatio": 0.0921, "changedPixels": 190941, "totalPixels": 2073600,
|
|
723
|
+
"box": { "left": 101, "top": 383, "width": 1204, "height": 323 }
|
|
724
|
+
},
|
|
725
|
+
{ "file": "04-wide.png", "status": "resized",
|
|
726
|
+
"baselineSize": { "width": 1920, "height": 1080 }, "size": { "width": 1280, "height": 720 } },
|
|
727
|
+
{ "file": "09-gone.png", "status": "missing" }
|
|
728
|
+
],
|
|
729
|
+
"summary": { "changed": 1, "stable": 11, "added": 0, "missing": 1, "resized": 1 }
|
|
730
|
+
}
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
`slides` is ranked by `changedRatio` descending, so the loudest slide is the
|
|
734
|
+
first thing read; the entries nobody could measure (`added`, `missing`,
|
|
735
|
+
`resized`) keep to the end, where the report names them one by one. `box` is
|
|
736
|
+
the smallest rect containing every changed pixel · it is where to look.
|
|
737
|
+
|
|
738
|
+
`--threshold` is a percentage of a slide's pixels: at or above it a slide is
|
|
739
|
+
`changed`, below it `stable`. The default `0.5` is there because re-rendering
|
|
740
|
+
an unchanged deck still repaints its anti-aliasing, and a report where 57 of 64
|
|
741
|
+
slides are "changed" hides the seven that really moved. `--threshold 0` lists
|
|
742
|
+
every slide where a single pixel moved; a slide where nothing moved stays
|
|
743
|
+
`stable` even then.
|
|
744
|
+
|
|
745
|
+
Exit code is 1 when at least one slide is `changed`, `missing` or `resized`, 0
|
|
746
|
+
otherwise · a slide the baseline never had is news, not a regression. A
|
|
747
|
+
`--baseline` pointing at a directory that is not there stops before the render,
|
|
748
|
+
with exit 2.
|
|
749
|
+
|
|
750
|
+
### `rikiki check` · measurements
|
|
751
|
+
|
|
752
|
+
```bash
|
|
753
|
+
npx rikiki check talk.html # a readable report on stderr
|
|
754
|
+
npx rikiki check talk.html --json # the report on stdout, nothing else
|
|
755
|
+
npx rikiki check talk.html --no-visual # skip the pixel pass (one shot per slide)
|
|
756
|
+
npx rikiki check talk.html --steps # measure every revealed state, not just the first
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
Every slide is measured, in its opening state, whatever the mode: `check`
|
|
760
|
+
walks the deck one slide at a time, because `deck-root` lays out the slide on
|
|
761
|
+
screen and hides the rest · measuring the document in one shot would read empty
|
|
762
|
+
boxes for every slide but the first, and report a clean deck. The walk drives
|
|
763
|
+
the deck by its location hash; a deck it cannot navigate stops the walk at that
|
|
764
|
+
slide with `NAVIGATION_STALLED`, and the report still carries every slide
|
|
765
|
+
measured before it.
|
|
766
|
+
|
|
767
|
+
Without `--steps`, a stepped slide is only ever measured in its opening state
|
|
768
|
+
· `advanceStep`'s own geometry rarely changes with it (rikiki reveals dim and
|
|
769
|
+
highlight, it does not hide), but content wired to a step through other means
|
|
770
|
+
can still defect only once revealed. With `--steps`, each slide is walked from
|
|
771
|
+
its opening state through every state `advanceStep` reaches (`ArrowRight`),
|
|
772
|
+
running the same diagnostics on each. Every diagnostic then carries a `state`
|
|
773
|
+
(`0` for the opening state) both in the JSON and appended to the human line
|
|
774
|
+
(`· state 2`). A diagnostic identical on code, slide and path/message across
|
|
775
|
+
several states of one slide is reported once, at the lowest state it held.
|
|
776
|
+
`statesInspected` counts every state actually measured · without `--steps`
|
|
777
|
+
that is one per slide, so it reads the slide count.
|
|
778
|
+
The pixel pass still measures only the opening state of each slide either way
|
|
779
|
+
· `notChecked` says so.
|
|
780
|
+
|
|
781
|
+
The pixel pass photographs each slide with the engine's own chrome hidden, and
|
|
782
|
+
measures where the ink sits. It reports imbalance only · a slide whose content
|
|
783
|
+
fills the canvas is left alone whatever empty space remains. `visualMeasured`
|
|
784
|
+
in the report says whether it ran.
|
|
785
|
+
|
|
786
|
+
Exit codes: `0` nothing blocking, `1` defects found, `2` the deck could not be
|
|
787
|
+
looked at (bad invocation, unreadable file). An agent branches on those: `1`
|
|
788
|
+
means fix the deck, `2` means fix the call.
|
|
789
|
+
|
|
790
|
+
Each diagnostic carries a stable `code`, a `severity`, the slide it belongs to,
|
|
791
|
+
an `element` path that reaches into the Shadow DOM (`deck-feature#detail
|
|
792
|
+
::shadow div`), the `measurement` that justifies it, and a `suggestion`.
|
|
793
|
+
|
|
794
|
+
| Code | Severity | What it means |
|
|
795
|
+
|---|---|---|
|
|
796
|
+
| `RUNTIME_NOT_LOADED` | error | the elements never registered · every slide is raw HTML |
|
|
797
|
+
| `NO_DECK_ROOT` / `NO_SLIDES` | error | nothing to show |
|
|
798
|
+
| `RESOURCE_MISSING` | error | a file the deck asked for did not arrive |
|
|
799
|
+
| `PAGE_ERROR` | error | the page threw during setup |
|
|
800
|
+
| `NAVIGATION_STALLED` | error | the deck never arrived at that slide · the walk stopped there and the report holds only what came before |
|
|
801
|
+
| `UNKNOWN_ELEMENT` | error | a misspelled `deck-*` tag · it renders as nothing at all |
|
|
802
|
+
| `STRAY_MARKUP` | warning | prose about markup that the parser turned into an element · escape the angle brackets |
|
|
803
|
+
| `CONTENT_CLIPPED` | error | the slide clips rather than scrolls · that content is lost |
|
|
804
|
+
| `CONTENT_ESCAPES_BOX` | error | a painted box runs past its nearest painted ancestor by more than 4px, and nothing clips · the box is too small for what is inside it |
|
|
805
|
+
| `CONTENT_OVERLAPS_SIBLING` | error | two unrelated painted boxes intersect by more than 8px on both axes · one paints over the other |
|
|
806
|
+
| `SLIDE_DENSE` | warning | nothing is cut yet, but there is no room left |
|
|
807
|
+
| `SLIDE_TOP_HEAVY` | warning | measured on the pixels · the ink sits in the top with a dead band under it |
|
|
808
|
+
| `TALK_SHORTER_THAN_ANNOUNCED` | warning | the notes carry far less speech than the cover announces |
|
|
809
|
+
| `TEXT_TOO_SMALL` | warning | below the readable floor once the canvas is scaled |
|
|
810
|
+
| `TEXT_LAST_LINE_ORPHAN` | warning | a block of prose ends on a stub under a quarter of the width above it · measured on the painted lines, headings and short blocks excepted · worst one per slide |
|
|
811
|
+
| `UNKNOWN_ATTRIBUTE` | warning | an attribute the element neither reads nor styles on · the value is dropped |
|
|
812
|
+
| `DUPLICATE_SLIDE_ID` | warning | two slides answer to the same name |
|
|
813
|
+
| `EXTERNAL_DEPENDENCY` | warning | the deck fetches from the network at runtime |
|
|
814
|
+
| `GRAPH_NODE_OUT_OF_BOUNDS` | error | a `deck-node` is painted outside its `deck-graph` canvas · move it inward with `at`, shorten its note, or constrain it with `width` |
|
|
815
|
+
| `GRAPH_EDGE_CROSSES_NODE` | warning | the line a `deck-edge` actually paints, bends and stroke width included, runs over a node it does not connect · move the obstructing node, or route the edge around it |
|
|
816
|
+
| `GRAPH_NODE_OVERLAPS_NODE` | error | two `deck-node` of the same `deck-graph` are painted on top of each other · one of them is unreadable |
|
|
817
|
+
| `GRAPH_NODE_COVERS_LABEL` | error | a `deck-node` is painted over a `deck-group` / `deck-lane` / edge caption · move the node with `at`, or the region with its own `at` |
|
|
818
|
+
| `GRAPH_EDGE_SKEWED` | warning | an edge misses horizontal or vertical by a few pixels · a frank diagonal is left alone, a three-degree slope is a slip · align the two `at` coordinates, or set `route="ortho"` |
|
|
819
|
+
| `GRAPH_NODES_OFF_AXIS` | warning | two nodes sit within the alignment slack of the same row or column without sharing it · worst offender per graph |
|
|
820
|
+
| `GRAPH_NODE_SIZES_MIXED` | warning | two nodes of one row (or column) differ by a few pixels in height (or width) · near-equal boxes read as a failed attempt at the same size, plainly different ones are left alone |
|
|
821
|
+
| `GRAPH_LAYOUT_NOT_SEMANTIC` | warning | every node of a graph of three or more sits on one axis, with no `layout` · the `at` coordinates re-do what `layout="row"` / `layout="column"` says |
|
|
822
|
+
|
|
823
|
+
The report also carries `notChecked`, which names what was **not** looked at:
|
|
824
|
+
revealed steps, accessibility, wording and facts, other viewports, text inside
|
|
825
|
+
a diagram, and the size of a component's own chrome. Silence about a check that
|
|
826
|
+
never ran would read as a clean bill.
|
|
827
|
+
|
|
828
|
+
Two things it will not do: call a slide bad for having empty space, and claim a
|
|
829
|
+
deck is accessible. Space is a choice, and a handful of measurements is not an
|
|
830
|
+
accessibility audit.
|
|
831
|
+
|
|
632
832
|
## 13 · Recipes / cookbook
|
|
633
833
|
|
|
834
|
+
For choosing a composition from what a slide has to say, see
|
|
835
|
+
[`rikiki-workflow.md`](./rikiki-workflow.md). This section is the wiring: what
|
|
836
|
+
to type once the composition is chosen.
|
|
837
|
+
|
|
634
838
|
Copy-paste patterns. Every tag/attribute used here is defined above · combine
|
|
635
839
|
them freely. Assume the deck head loads the theme then `dist/index.js` (§2).
|
|
636
840
|
|
|
841
|
+
### An opt-in component slide (§20)
|
|
842
|
+
|
|
843
|
+
The opt-in components are not in `dist/index.js` · load the ones you use, one
|
|
844
|
+
script tag each, after the core bundle. They follow the direction in §20: one
|
|
845
|
+
filled area at most, two type sizes, no label above content.
|
|
846
|
+
|
|
847
|
+
```html
|
|
848
|
+
<script type="module" src="dist/index.js"></script>
|
|
849
|
+
<script type="module" src="dist/deck-kpi-grid.js"></script>
|
|
850
|
+
<script type="module" src="dist/deck-flow.js"></script>
|
|
851
|
+
```
|
|
852
|
+
|
|
853
|
+
```html
|
|
854
|
+
<deck-feature eyebrow="Numbers" spread="center">
|
|
855
|
+
<h1 slot="title">Where the time went</h1>
|
|
856
|
+
<deck-kpi-grid cols="3">
|
|
857
|
+
<deck-kpi value="34" label="components in the default bundle"></deck-kpi>
|
|
858
|
+
<deck-kpi value="14" label="more, one script tag each" tone="accent"></deck-kpi>
|
|
859
|
+
<deck-kpi value="0" label="network calls at runtime" note="a bundled deck runs offline"></deck-kpi>
|
|
860
|
+
</deck-kpi-grid>
|
|
861
|
+
</deck-feature>
|
|
862
|
+
|
|
863
|
+
<deck-feature eyebrow="Chain" spread="center" data-steps="4">
|
|
864
|
+
<h1 slot="title">One stage at a time</h1>
|
|
865
|
+
<deck-flow cols="4" reveal>
|
|
866
|
+
<deck-flow-step label="Write" note="one HTML file"></deck-flow-step>
|
|
867
|
+
<deck-flow-step label="Preview" note="open it"></deck-flow-step>
|
|
868
|
+
<deck-flow-step label="Bundle" note="one command"></deck-flow-step>
|
|
869
|
+
<deck-flow-step label="Present" note="offline"></deck-flow-step>
|
|
870
|
+
</deck-flow>
|
|
871
|
+
</deck-feature>
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
At step 0 the whole chain is visible and neutral · its shape is half the
|
|
875
|
+
message. Each step then moves the block to the stage being discussed. A running
|
|
876
|
+
version of both slides is in `examples/rikiki-tour/index.html`.
|
|
877
|
+
|
|
637
878
|
### Markdown + code feature slide
|
|
638
879
|
|
|
639
880
|
```html
|
|
@@ -684,6 +925,62 @@ them freely. Assume the deck head loads the theme then `dist/index.js` (§2).
|
|
|
684
925
|
</deck-feature-cards>
|
|
685
926
|
```
|
|
686
927
|
|
|
928
|
+
### Bento layout (adaptive cells + fit-to-box text)
|
|
929
|
+
|
|
930
|
+
A `deck-cell` stacks its children in a column, so its two alignment knobs run
|
|
931
|
+
on the axes their names do not suggest: **`align` moves content left/right**,
|
|
932
|
+
**`justify` moves it up/down**. To push a cell's content to the bottom, write
|
|
933
|
+
`justify="end"`, not `align="end"`.
|
|
934
|
+
|
|
935
|
+
Cells share a multi-row/column grid via `span`. Each `deck-cell` is a size
|
|
936
|
+
container, so `cqw`/`cqh` type (and `<deck-punch fit>`) adapts to the cell it
|
|
937
|
+
lands in, not the whole slide. Use `fit` when the text length is unknown and
|
|
938
|
+
must never overflow; use `size="display"` (or any `cqw`-based size) for plain
|
|
939
|
+
fluid scaling without the JS measure.
|
|
940
|
+
|
|
941
|
+
```html
|
|
942
|
+
<deck-bento eyebrow="Overview" cols="3" rows="2" gap="3">
|
|
943
|
+
<h1 slot="title">Sharing the space</h1>
|
|
944
|
+
<deck-cell span="2x1" align="center" justify="center">
|
|
945
|
+
<deck-punch fit>Headline that shrinks to fit its cell</deck-punch>
|
|
946
|
+
</deck-cell>
|
|
947
|
+
<deck-cell span="1x2" tone="info"><h3>Side</h3><deck-md>Tall cell.</deck-md></deck-cell>
|
|
948
|
+
<deck-cell tone="ok"><h3>A</h3></deck-cell>
|
|
949
|
+
<deck-cell tone="warn"><h3>B</h3></deck-cell>
|
|
950
|
+
</deck-bento>
|
|
951
|
+
```
|
|
952
|
+
|
|
953
|
+
### Cards from markdown (`::: cards`)
|
|
954
|
+
|
|
955
|
+
Author a whole slide in markdown and let `deck-md` expand a `::: cards` fenced
|
|
956
|
+
block into a tinted card grid · the fast way to write a bento without HTML.
|
|
957
|
+
Inside the fence, `:: <tone> <span> | <title>` opens a card (both `tone` —
|
|
958
|
+
`info`/`warn`/`ok`/`danger` — and `span` like `2x1` are optional, any order);
|
|
959
|
+
the lines until the next `::` are its markdown body. The fence takes `cols=N`
|
|
960
|
+
and `gap=N` (default `cols` = number of cards).
|
|
961
|
+
|
|
962
|
+
```html
|
|
963
|
+
<deck-feature>
|
|
964
|
+
<deck-md>
|
|
965
|
+
# You won't write it all yourself
|
|
966
|
+
|
|
967
|
+
Every dependency is a trade-off:
|
|
968
|
+
|
|
969
|
+
::: cards cols=3
|
|
970
|
+
:: warn | Reproducibility
|
|
971
|
+
same versions on every machine, every CI run
|
|
972
|
+
:: warn | Build cost
|
|
973
|
+
source you compile vs prebuilt you link
|
|
974
|
+
:: ok 2x1 | Control
|
|
975
|
+
who owns the version, the flags, the patches
|
|
976
|
+
:::
|
|
977
|
+
</deck-md>
|
|
978
|
+
</deck-feature>
|
|
979
|
+
```
|
|
980
|
+
|
|
981
|
+
For pixel control (true cell spans, `fit` text, images, `deck-csv`), author the
|
|
982
|
+
grid explicitly with `deck-bento` + `deck-cell` instead.
|
|
983
|
+
|
|
687
984
|
### Big-number stat
|
|
688
985
|
|
|
689
986
|
```html
|
|
@@ -826,6 +1123,95 @@ slide to the second.
|
|
|
826
1123
|
|
|
827
1124
|
## 14 · Authoring rules for LLMs
|
|
828
1125
|
|
|
1126
|
+
Everything above this section says what you MAY write. This one says what makes
|
|
1127
|
+
the result worth projecting, because the two are not the same question and
|
|
1128
|
+
decks assembled correctly from the tables above have been rejected in a room.
|
|
1129
|
+
|
|
1130
|
+
### 14.1 · What the slide is
|
|
1131
|
+
|
|
1132
|
+
A slide is read from three to ten metres, for about forty seconds, while
|
|
1133
|
+
someone talks over it, and then again as a thumbnail in the overview grid and
|
|
1134
|
+
as a page in a PDF. What survives that trip is **area, size, position, one
|
|
1135
|
+
saturated colour and empty space**. What does not survive is a hairline, type
|
|
1136
|
+
under about twenty pixels on the wall, letter spacing, small caps, a
|
|
1137
|
+
low-contrast tint, and anything that has to be compared against something else
|
|
1138
|
+
to be understood. Compose from the first list. See
|
|
1139
|
+
`docs/design/adr-002-extras-visual-direction.md`.
|
|
1140
|
+
|
|
1141
|
+
### 14.2 · The title is the message, the body is the proof
|
|
1142
|
+
|
|
1143
|
+
A content slide's title is a **full sentence stating what the slide argues**,
|
|
1144
|
+
about eight to fourteen words, and the body is its **evidence** · a figure, a
|
|
1145
|
+
diagram, a table, a number. Not a bullet list restating the title.
|
|
1146
|
+
|
|
1147
|
+
This is the assertion-evidence structure (Michael Alley, Penn State), and it is
|
|
1148
|
+
here because the comprehension gain over the usual topic-and-subtopic slide is
|
|
1149
|
+
measured and statistically significant, not because it reads better.
|
|
1150
|
+
|
|
1151
|
+
A topic title carries no message, so the body has to carry all of it, and the
|
|
1152
|
+
slide ends up with nothing to look at. "Graph" names a subject; "An architecture
|
|
1153
|
+
reads as boxes and arrows, never as paragraphs" says something the evidence can
|
|
1154
|
+
then support.
|
|
1155
|
+
|
|
1156
|
+
It costs nothing in type size: at the shipped title size the usable width holds
|
|
1157
|
+
about forty-four characters a line, so fourteen words fit on two lines. It does
|
|
1158
|
+
cost height · a two-line title takes a line back from the body, and
|
|
1159
|
+
the repository's slide-budget suite will say so.
|
|
1160
|
+
|
|
1161
|
+
`deck-cover` and `deck-section` are exempt. A chapter title is a boundary, not
|
|
1162
|
+
an assertion, and three words are right there.
|
|
1163
|
+
a test in the repository holds the band on every shipped deck.
|
|
1164
|
+
|
|
1165
|
+
### 14.3 · The five rules
|
|
1166
|
+
|
|
1167
|
+
1. **One loud thing.** A slide has one statement. Everything else on it is
|
|
1168
|
+
quiet. Two loud things means the eye picks the wrong one.
|
|
1169
|
+
2. **Two sizes, and the gap between them is the design.** A statement and a
|
|
1170
|
+
reading size, nothing in between. The theme sets the statement at more than
|
|
1171
|
+
twice the reading size on purpose · a title at 1.5x reads as body text in
|
|
1172
|
+
bold, which is the single most common reason a deck looks flat.
|
|
1173
|
+
3. **One mass at most.** One filled area per slide, carrying whatever the
|
|
1174
|
+
content actually marks. Nothing marked means nothing filled. On these themes
|
|
1175
|
+
a pale tint is invisible in a room; real emphasis is the inverse surface.
|
|
1176
|
+
4. **A line only where two things would otherwise touch.** A table header, a
|
|
1177
|
+
timeline axis, an edge in a diagram. Never as decoration or as a signature.
|
|
1178
|
+
5. **Left, ragged right.** The vertical edge down the left is what makes a
|
|
1179
|
+
glance cheap. Centre a whole slide if you mean to; never centre a column
|
|
1180
|
+
inside a row of columns, because it breaks that edge.
|
|
1181
|
+
|
|
1182
|
+
### 14.4 · Filling the canvas
|
|
1183
|
+
|
|
1184
|
+
Most rejected slides put their content in the top fifth and leave the rest
|
|
1185
|
+
white. That is almost never a component problem · it is a deck that never asked
|
|
1186
|
+
for a distribution. `spread` and `fill` (§19) are the answer, and the choice
|
|
1187
|
+
between them is: `spread` when the type size is right and only the rhythm is
|
|
1188
|
+
wrong, `fill` when the slide is genuinely under-filled and the text should grow
|
|
1189
|
+
into it (pair it with `<deck-fit>`).
|
|
1190
|
+
|
|
1191
|
+
Prefer cutting to shrinking. If a slide needs a third type size or a smaller
|
|
1192
|
+
body to fit, it is two slides. `<deck-notes>` takes what does not fit, and a
|
|
1193
|
+
stepped reveal (§7) is the medium's own way of showing a lot without crowding.
|
|
1194
|
+
|
|
1195
|
+
### 14.5 · Rows of items
|
|
1196
|
+
|
|
1197
|
+
Reach for **`<deck-point>`** when a bento item holds words, and **`<deck-cell>`**
|
|
1198
|
+
when it holds something that must be measured to its box · fit-to-cell text, a
|
|
1199
|
+
diagram, an image.
|
|
1200
|
+
|
|
1201
|
+
The difference is not cosmetic. A row of `deck-point` is as tall as its tallest
|
|
1202
|
+
point, and a row made only of points (same number of children each, no spans,
|
|
1203
|
+
no declared `rows`) shares the grid's bands, so a title that wraps to a second
|
|
1204
|
+
line does not drag its own body text below its neighbours'. A row of
|
|
1205
|
+
`deck-cell` takes a share of the slide instead, so a cell that carries a surface
|
|
1206
|
+
will show a box taller than its text. Mixing them in one row is allowed and
|
|
1207
|
+
costs the shared bands.
|
|
1208
|
+
|
|
1209
|
+
Whichever you use, do not reach for `plain` to remove the gutter · it keeps the
|
|
1210
|
+
gutter on purpose, so a painted item and a plain one start their text on the
|
|
1211
|
+
same edge.
|
|
1212
|
+
|
|
1213
|
+
### 14.6 · Mechanics
|
|
1214
|
+
|
|
829
1215
|
- **Never nest `<deck-root>`.** One per document.
|
|
830
1216
|
- **Load theme CSS before `dist/index.js`.**
|
|
831
1217
|
- Every direct child of `<deck-root>` is one slide; keep **one focal idea per
|
|
@@ -838,3 +1224,508 @@ slide to the second.
|
|
|
838
1224
|
(or component `--deck-*-…` tokens on one host). Do not hardcode colors.
|
|
839
1225
|
- Move detail into **`<deck-notes>`** rather than crowding the slide.
|
|
840
1226
|
- Only use tags, attributes, and tokens listed in this document.
|
|
1227
|
+
|
|
1228
|
+
---
|
|
1229
|
+
|
|
1230
|
+
## 15 · Trust model
|
|
1231
|
+
|
|
1232
|
+
- **Deck content is trusted.** `deck-md` renders raw HTML from the markdown you
|
|
1233
|
+
write, on purpose. That is the contract: a deck is a page its author
|
|
1234
|
+
publishes. There is no `sanitize` attribute and none is planned.
|
|
1235
|
+
- **Derived text is not.** A renderer error message quotes the source that broke
|
|
1236
|
+
it, so it is escaped before display. Never assume an error string is inert.
|
|
1237
|
+
- **mermaid runs at `strict`.** HTML in diagram labels is encoded and
|
|
1238
|
+
click-bound scripts are refused. There is no permissive opt-in.
|
|
1239
|
+
- **Never render untrusted markdown or diagram source.** If the content comes
|
|
1240
|
+
from a form, an API or a CMS field a stranger can edit, sanitise it before it
|
|
1241
|
+
reaches `<deck-md>`. rikiki is a presentation engine, not a sandbox.
|
|
1242
|
+
|
|
1243
|
+
---
|
|
1244
|
+
|
|
1245
|
+
## 16 · The three ways a deck runs
|
|
1246
|
+
|
|
1247
|
+
Pick one deliberately · they make different promises.
|
|
1248
|
+
|
|
1249
|
+
**Served** · the folder as you wrote it. HTML, CSS and JS stay separate files,
|
|
1250
|
+
so editing a slide needs no build. ES modules mean it needs a **static HTTP
|
|
1251
|
+
server**, not a double-click: `npx serve .`, or anything that speaks HTTP.
|
|
1252
|
+
Offline once every asset is local.
|
|
1253
|
+
|
|
1254
|
+
**Standalone** · one HTML file, produced by `rikiki bundle deck.html out.html`.
|
|
1255
|
+
Opens straight from `file://`, so it survives a USB stick, an email attachment
|
|
1256
|
+
and an archive. Nothing is fetched at runtime: scripts, styles, fonts and images
|
|
1257
|
+
are all inside. The presenter works from it too.
|
|
1258
|
+
|
|
1259
|
+
- A deck using `<deck-mermaid>` needs `--with-mermaid` (+~3 MB).
|
|
1260
|
+
- A deck using Shiki needs `--with-shiki` (about +0.7 MB raw, 113 KB compressed).
|
|
1261
|
+
- Without the flag the command **fails** and names the missing runtime · it will
|
|
1262
|
+
not hand you a file that renders an empty diagram offline.
|
|
1263
|
+
- `rikiki init --standalone` produces a starter with the same guarantees.
|
|
1264
|
+
|
|
1265
|
+
**CDN** · two `<script>`/`<link>` tags from jsdelivr. Zero install, but the deck
|
|
1266
|
+
fetches the framework every time it runs, so it needs the network and is **not**
|
|
1267
|
+
an archival format. Always pin a version.
|
|
1268
|
+
|
|
1269
|
+
The self-containment of a standalone file is enforced, not assumed:
|
|
1270
|
+
the bundle suite writes each bundle outside the repository, opens it over
|
|
1271
|
+
`file://`, and fails if the page issues a single request beyond itself.
|
|
1272
|
+
|
|
1273
|
+
---
|
|
1274
|
+
|
|
1275
|
+
## 17 · Printing and PDF export
|
|
1276
|
+
|
|
1277
|
+
A deck carries its own print stylesheet · no mode to switch on, no separate
|
|
1278
|
+
build.
|
|
1279
|
+
|
|
1280
|
+
- **One slide, one page.** Every slide prints, in order, at the deck's canvas
|
|
1281
|
+
size. The `@page` box is written from `--deck-canvas-w/h`, so a 16:9 deck
|
|
1282
|
+
prints 16:9 · forcing A4 crops it.
|
|
1283
|
+
- **Backgrounds are kept** (`print-color-adjust: exact`) · a tinted layout means
|
|
1284
|
+
nothing in black and white.
|
|
1285
|
+
- **Chrome is dropped** · counter, progress bar, nav arrows, key hints, step dots.
|
|
1286
|
+
- **Steps do not multiply pages.** A slide with click-stages prints once, fully
|
|
1287
|
+
revealed. Speaker notes stay out.
|
|
1288
|
+
|
|
1289
|
+
From the browser: print, backgrounds on. From the command line:
|
|
1290
|
+
|
|
1291
|
+
```sh
|
|
1292
|
+
rikiki export deck.html --output deck.pdf
|
|
1293
|
+
```
|
|
1294
|
+
|
|
1295
|
+
The command serves the deck over HTTP (ES modules need it), waits for
|
|
1296
|
+
`document.fonts.ready` and for every `<deck-mermaid>` to settle, then prints. It
|
|
1297
|
+
reports any asset it could not load rather than handing back a silently
|
|
1298
|
+
incomplete PDF. It needs **Playwright**, an optional peer dependency:
|
|
1299
|
+
`npm i -D playwright && npx playwright install chromium`.
|
|
1300
|
+
|
|
1301
|
+
The whole contract is verified by a print suite that reads the produced
|
|
1302
|
+
PDF back with poppler.
|
|
1303
|
+
|
|
1304
|
+
---
|
|
1305
|
+
|
|
1306
|
+
## 18 · Embedding a deck in a page
|
|
1307
|
+
|
|
1308
|
+
A `<deck-root>` that is a direct child of `<body>` **is** the page: it owns the
|
|
1309
|
+
scroll, the rem baseline, the URL hash, the keyboard and the wheel. Anywhere
|
|
1310
|
+
else it is a widget, and owns none of that.
|
|
1311
|
+
|
|
1312
|
+
An embedded deck:
|
|
1313
|
+
|
|
1314
|
+
- **leaves the host's styling alone.** The theme's reset, page background and
|
|
1315
|
+
helper classes (`.accent`, `.lead`, `.display`, `table.dense` …) are scoped to
|
|
1316
|
+
the deck subtree. Importing a theme does not restyle the page around it.
|
|
1317
|
+
- **does not touch the URL.** `#section-3` stays the host's anchor. Deep links
|
|
1318
|
+
work on a full-page deck only.
|
|
1319
|
+
- **takes the keyboard only while focused.** It gets `tabindex="0"`, so a reader
|
|
1320
|
+
tabs to it and then navigates with the arrow keys. Until then the arrows
|
|
1321
|
+
belong to the host page.
|
|
1322
|
+
- **lets the wheel scroll the host.** Ctrl/⌘ + wheel still zooms, and panning
|
|
1323
|
+
still works once a slide is magnified.
|
|
1324
|
+
|
|
1325
|
+
**Several decks per document are supported.** Each keeps its own canvas, its own
|
|
1326
|
+
slide index and its own navigation; focus decides which one the keyboard drives.
|
|
1327
|
+
Only one of them can be the page. Pinned by the multi-deck suite.
|
|
1328
|
+
|
|
1329
|
+
Recommended for a thumbnail or an inline demo:
|
|
1330
|
+
|
|
1331
|
+
```html
|
|
1332
|
+
<div style="width: 640px; height: 360px">
|
|
1333
|
+
<deck-root no-hint no-arrows>…</deck-root>
|
|
1334
|
+
</div>
|
|
1335
|
+
```
|
|
1336
|
+
|
|
1337
|
+
---
|
|
1338
|
+
|
|
1339
|
+
## 19 · Filling the slide vertically
|
|
1340
|
+
|
|
1341
|
+
A slide body takes the height left under the title, but its blocks stack at the
|
|
1342
|
+
top. A short slide therefore leaves most of the canvas empty · measured at 62%
|
|
1343
|
+
on a three-line `deck-feature`. Two opt-in attributes on `deck-feature`,
|
|
1344
|
+
`deck-split` and `deck-takeaway` share that space. Both are no-ops when absent,
|
|
1345
|
+
so existing decks are untouched.
|
|
1346
|
+
|
|
1347
|
+
| Attribute | Effect |
|
|
1348
|
+
|---|---|
|
|
1349
|
+
| `spread="between"` | push the blocks apart over the full height |
|
|
1350
|
+
| `spread="around"` / `"evenly"` | distribute the space around / between evenly |
|
|
1351
|
+
| `spread="center"` / `"end"` / `"start"` | group the blocks, centred / bottom / top (default) |
|
|
1352
|
+
| `fill` | give the height to the blocks themselves rather than to the gaps |
|
|
1353
|
+
|
|
1354
|
+
An unknown `spread` value falls back to `start` rather than dropping the
|
|
1355
|
+
layout.
|
|
1356
|
+
|
|
1357
|
+
`fill` on its own makes the blocks taller, not the text. Pair it with
|
|
1358
|
+
`<deck-fit>` to grow the text into the box it now has:
|
|
1359
|
+
|
|
1360
|
+
```html
|
|
1361
|
+
<deck-feature fill>
|
|
1362
|
+
<h1 slot="title">Filled</h1>
|
|
1363
|
+
<deck-fit max="5">One line that grows to fill its share of the slide.</deck-fit>
|
|
1364
|
+
<deck-fit max="5">And a second one.</deck-fit>
|
|
1365
|
+
</deck-feature>
|
|
1366
|
+
```
|
|
1367
|
+
|
|
1368
|
+
Which to reach for: `spread` when the type size is right and only the rhythm is
|
|
1369
|
+
wrong; `fill` when the slide is genuinely under-filled and the text should be
|
|
1370
|
+
bigger. `deck-bento` remains the answer when the content wants a grid rather
|
|
1371
|
+
than a stack.
|
|
1372
|
+
|
|
1373
|
+
---
|
|
1374
|
+
|
|
1375
|
+
## 20 · Opt-in components
|
|
1376
|
+
|
|
1377
|
+
Some components are **not** in `dist/index.js`. A deck that does not use them
|
|
1378
|
+
pays nothing for them · manifesto principle 3, light by default. Each is its own
|
|
1379
|
+
module, loaded next to the bundle:
|
|
1380
|
+
|
|
1381
|
+
```html
|
|
1382
|
+
<script type="module" src="dist/index.js"></script>
|
|
1383
|
+
<script type="module" src="dist/deck-bar.js"></script>
|
|
1384
|
+
<script type="module" src="dist/deck-quote.js"></script>
|
|
1385
|
+
```
|
|
1386
|
+
|
|
1387
|
+
`rikiki bundle` folds a loaded module into the single file like any other
|
|
1388
|
+
script, so a standalone deck keeps them and stays offline. Forget the `<script>`
|
|
1389
|
+
and the tag stays an unknown element: it renders its text content, logs nothing,
|
|
1390
|
+
and the rest of the deck is unaffected.
|
|
1391
|
+
|
|
1392
|
+
**Past about four added modules, stop adding script tags and bundle.** Each
|
|
1393
|
+
module is compiled on its own and carries its own copy of the shared code, and
|
|
1394
|
+
gzip compresses one large repetitive file far better than several small ones,
|
|
1395
|
+
so script tags stop paying off quickly. Measured on this release, gzipped:
|
|
1396
|
+
|
|
1397
|
+
| what the deck loads | gzip |
|
|
1398
|
+
|---|---|
|
|
1399
|
+
| `dist/index.js` alone | 26 KB |
|
|
1400
|
+
| `dist/index.js` + 3 modules | 30 KB |
|
|
1401
|
+
| `dist/index.js` + 5 modules | 33 KB |
|
|
1402
|
+
|
|
1403
|
+
`rikiki bundle` carries only the components the deck actually writes, in one
|
|
1404
|
+
file, so it is smaller than the plain bundle for any deck that does not use
|
|
1405
|
+
every component · and it is the only option that gets *smaller* as the deck
|
|
1406
|
+
gets simpler, rather than larger. Script tags are the convenient path for one
|
|
1407
|
+
or two extras, not the cheap one.
|
|
1408
|
+
|
|
1409
|
+
Every evidence block below (`deck-csv`, `deck-table`, `deck-bar`,
|
|
1410
|
+
`deck-kpi-grid`, `deck-annotate`, and plain prose) takes a `deck-source`
|
|
1411
|
+
underneath it for the credit line · `deck-source` is a core atom (§6), not an
|
|
1412
|
+
opt-in module, because so many of these need it. `deck-figure` renders one
|
|
1413
|
+
internally for its own `source` / `source-href` attributes, so the two
|
|
1414
|
+
authoring paths render identically and cannot drift.
|
|
1415
|
+
|
|
1416
|
+
| Tag | Purpose | Key attributes | Slots |
|
|
1417
|
+
|-----|---------|----------------|-------|
|
|
1418
|
+
| `deck-bar` | A proportion, drawn · one value against a total, or a stack of categories on one track | `value`, `total`, `label`, `tone` (`accent`/`ok`/`warn`/`danger`/`info`/`muted`), `segments` (`label:value:tone` triples separated by `\|`), `no-value`, `no-legend` | · |
|
|
1419
|
+
| `deck-icon` | A symbol · one of 24 drawn glyphs by `name`, or any `<svg>` you slot in. Nothing is vendored; `rikiki bundle` keeps only the glyphs the deck writes | `name`, `size` (`sm`/`md`/`lg`/`xl`), `tone`, `label` (absent means decorative, and it is hidden from assistive technology) | default = a fallback `<svg>` |
|
|
1420
|
+
| `deck-checklist` / `deck-check` | What works and what does not, told apart by shape as well as colour | list: `cols` · item: `no` | item default = the text |
|
|
1421
|
+
| `deck-kpi-grid` / `deck-kpi` | Several figures that read as one family · the grid owns the value / label / note rows and every figure adopts them, so all the values share one baseline and all the labels sit on one line | grid: `cols`, `ruled` (a visible divider between figures) · figure: `value` (statement size · `--deck-kpi-value-size` for a fluid one), `label`, `note`, `tone` (`accent`/`ok`/`warn`/`danger` put the figure on the inverse surface and colour its label with the tone; `default` and `muted` paint nothing) | · |
|
|
1422
|
+
| `deck-pull` | An excerpt lifted out of a dense slide · text wraps around it when floated | `side` (`full`/`left`/`right`) | default = the excerpt |
|
|
1423
|
+
| `deck-persona` | Who is speaking, or who the case study is about · the portrait block is the inverse surface, so the person has a place on the slide | `name`, `person-role` (**not** `role`), `org`, `context` (the quiet line, gapped away from the identity), `src` (a portrait; initials in inverse ink stand in without one), `on-dark` (the block flips to paper with ink initials), `compact` (shrinks the block and the name together, for a supporting persona), `inline` (name, role and context on one wrapping row) | · |
|
|
1424
|
+
| `deck-versus` | A directed comparison as a BLOCK inside a slide (`deck-split` covers the case where the comparison is the whole slide) | `pivot`, `winner` (`left`/`right`), `slide` (make the comparison a deck-root slide of its own, with `title` and `lead` slots), `eyebrow` (context label above the title, slide mode only) | `title`, `lead`, `left`, `right`, `footer` (full width, under both sides, slide mode only; a slotted `deck-callout` keeps its own size) |
|
|
1425
|
+
| `deck-flow` / `deck-flow-step` | A chain across the width · numbered stages, and only the active one takes the block | flow: `cols`, `reveal` · stage: `label`, `note` | stage default = extra content |
|
|
1426
|
+
| `deck-timeline` / `deck-milestone` | A trajectory in time, on an axis | timeline: `direction` (`row`/`column`), `alternate` (row only · milestones alternate above and below the axis, each twice as wide), `reveal` · milestone: `date`, `label`, `note`, `tone` | · |
|
|
1427
|
+
| `deck-graph` / `deck-node` / `deck-edge` / `deck-group` / `deck-lane` | Nodes, edges, regions and bands · the primitive behind every boxes-and-arrows slide | graph: `layout` (`free`/`row`/`column`), `reveal` · node: `at` (`x,y` in percent), `label`, `note`, `boxed`, `tone`, `icon`, `width` (an explicit CSS width such as `18ch` or `240px`, so a long label wraps instead of colliding) · edge: `from`, `to`, `label`, `dashed`, `arrow` (`end` default / `start` / `both` / `none`), `route` (`straight` default / `ortho` for right-angle segments), `label-offset` (`x,y` in pixels, moves the label off the line) · each edge publishes the polyline it paints back onto itself as `data-path` (`x1,y1 x2,y2[ ...]`, graph-relative CSS pixels), which is what `rikiki check` reads · group: `at` (`x,y,w,h`), `label`, `solid` · lane: `at` (`top,height`), `label` | node default = extra content |
|
|
1428
|
+
| `deck-table` | A hand-authored table with the hierarchy `deck-csv` has · the table stays in your light DOM, so its cells may carry markup | `highlight-rows`, `highlight-cols`, `reveal` | default = your `<table>` |
|
|
1429
|
+
| `deck-annotate` | A screenshot the speaker can point at · numbered markers positioned in percent, revealed one per step through the engine's own step mechanism · a real `<figure>`/`<figcaption>`, so it can carry its own caption and source like `deck-figure` | `src`, `alt`, `marks` (`x,y,label` triples separated by `\|`, coordinates in percent), `all-at-once`, `no-legend`, `leader` (draw a line from the target point to a displaced badge), `offset` (`x,y` in pixels, or a named side `above` / `below` / `left` / `right` : the badge is displaced by its own rendered diameter plus `--deck-annotate-anchor-gap` in that direction, and its leader turns on regardless of `leader`), `offsets` (per-mark displacements separated by `\|`, mixing pixel and keyword forms, e.g. `above\|0,-40\|right`; a missing entry falls back to `offset`), `caption`, `source`, `source-href` (turns the credit into a link) | `caption`, `source` |
|
|
1430
|
+
| `deck-agenda` | The running order and where the talk is · reads the deck's own chapter structure, so adding a `deck-section` grows a line | `no-numbers`, `no-jump` | · |
|
|
1431
|
+
| `deck-quote` | Someone else's words, attributed · distinct from `deck-punch`, which is the speaker's own line | `author`, `author-role` (**not** `role`, which belongs to ARIA), `size` (`lead`/`big`/`mega`), `plain` (drop the rule beside the quote), `on-dark`, `no-mark` | default = the quoted text |
|
|
1432
|
+
| `deck-figure` | A screenshot, a diagram or a chart as content · the image keeps its ratio, and its caption and credit stay attached to it semantically | `src`, `alt` (required unless `decorative`), `caption`, `source`, `source-href` (turns the credit into a link), `decorative` (the image carries no information · produces `alt=""`) | `image`, `caption`, `source` |
|
|
1433
|
+
|
|
1434
|
+
Tokens follow the usual per-component convention and every default routes to a
|
|
1435
|
+
semantic `--rik-*` token, so both shipped themes are covered:
|
|
1436
|
+
`--deck-bar-track`, `--deck-bar-height`, `--deck-bar-radius`, `--deck-bar-fill`,
|
|
1437
|
+
`--deck-bar-divider`, `--deck-bar-legend-color`, `--deck-bar-label-color`,
|
|
1438
|
+
`--deck-bar-value-color`; `--deck-quote-color`, `--deck-quote-size`,
|
|
1439
|
+
`--deck-quote-rule`, `--deck-quote-mark-color`, `--deck-quote-author-color`,
|
|
1440
|
+
`--deck-quote-role-color`, `--deck-quote-max-width`;
|
|
1441
|
+
`--deck-annotate-mark-bg`, `--deck-annotate-mark-color`, `--deck-annotate-mark-size`,
|
|
1442
|
+
`--deck-annotate-mark-ring`, `--deck-annotate-radius`, `--deck-annotate-legend-color`,
|
|
1443
|
+
`--deck-annotate-leader`, `--deck-annotate-leader-width`, `--deck-annotate-anchor-gap`
|
|
1444
|
+
(defaults to `--rik-space-2`, the gap a keyword offset leaves between the
|
|
1445
|
+
target point and the badge), `--deck-annotate-gap`
|
|
1446
|
+
(defaults to `--deck-figure-gap`), `--deck-annotate-caption-color` (defaults to
|
|
1447
|
+
`--deck-figure-caption-color`);
|
|
1448
|
+
`--deck-agenda-current-color`, `--deck-agenda-done-color`, `--deck-agenda-rule`,
|
|
1449
|
+
`--deck-agenda-marker`, `--deck-agenda-size`, `--deck-agenda-gap`;
|
|
1450
|
+
`--deck-icon-size`, `--deck-icon-color`, `--deck-icon-stroke`;
|
|
1451
|
+
`--deck-check-yes`, `--deck-check-no`, `--deck-check-size`,
|
|
1452
|
+
`--deck-check-no-color`, `--deck-checklist-rule`;
|
|
1453
|
+
`--deck-kpi-value-size` (statement size by default · a slide with room can go
|
|
1454
|
+
fluid with `clamp(2.25rem, 6cqw, 7rem)`, where `cqw` measures the nearest
|
|
1455
|
+
declared container and falls back to the viewport when the deck declares
|
|
1456
|
+
none), `--deck-kpi-value-color`,
|
|
1457
|
+
`--deck-kpi-label-color`,
|
|
1458
|
+
`--deck-kpi-note-color`, `--deck-kpi-mass`, `--deck-kpi-mass-text`,
|
|
1459
|
+
`--deck-kpi-block-pad-x` (set it on the grid or above, never on one figure ·
|
|
1460
|
+
the grid offsets itself by this value so the first column's ink lands on the
|
|
1461
|
+
slide's text edge), `--deck-kpi-block-pad-y`,
|
|
1462
|
+
`--deck-kpi-grid-cols`, `--deck-kpi-grid-gap`, `--deck-kpi-grid-row-gap`,
|
|
1463
|
+
`--deck-kpi-grid-rule`, `--deck-kpi-grid-rule-width`;
|
|
1464
|
+
`--deck-pull-rule`, `--deck-pull-size`, `--deck-pull-width`, `--deck-pull-font`;
|
|
1465
|
+
`--deck-persona-avatar-size`, `--deck-persona-avatar-bg`,
|
|
1466
|
+
`--deck-persona-initials-color`, `--deck-persona-initials-size`,
|
|
1467
|
+
`--deck-persona-name-size`, `--deck-persona-name-color`,
|
|
1468
|
+
`--deck-persona-role-color`, `--deck-persona-context-color`,
|
|
1469
|
+
`--deck-persona-gap`, `--deck-persona-name-lift`, `--deck-persona-compact-avatar-size`,
|
|
1470
|
+
`--deck-persona-compact-name-size`;
|
|
1471
|
+
`--deck-versus-winner-ring`, `--deck-versus-loser-opacity`, `--deck-versus-pivot-color`,
|
|
1472
|
+
`--deck-versus-slide-bg`, `--deck-versus-eyebrow-color`, `--deck-versus-side-align`,
|
|
1473
|
+
`--deck-versus-footer-gap` (defaults to `--rik-space-3`);
|
|
1474
|
+
`--deck-flow-gap`, `--deck-flow-step-accent`;
|
|
1475
|
+
`--deck-timeline-axis`, `--deck-milestone-dot`;
|
|
1476
|
+
`--deck-graph-edge`, `--deck-graph-edge-width`, `--deck-graph-ratio`, `--deck-node-rule`,
|
|
1477
|
+
`--deck-node-bg`, `--deck-group-border`, `--deck-lane-rule`;
|
|
1478
|
+
`--deck-table-mark-bg`, `--deck-table-mark-color`, `--deck-table-col-color`,
|
|
1479
|
+
`--deck-table-col-on-mark`;
|
|
1480
|
+
`--deck-figure-gap`, `--deck-figure-radius`, `--deck-figure-border`, `--deck-figure-bg`,
|
|
1481
|
+
`--deck-figure-image-fit`, `--deck-figure-image-position`, `--deck-figure-max-height`,
|
|
1482
|
+
`--deck-figure-caption-color`, `--deck-figure-source-color` (forwarded to the
|
|
1483
|
+
`deck-source` it renders internally, alongside `--deck-source-color` and
|
|
1484
|
+
`--deck-source-gap`, §6).
|
|
1485
|
+
|
|
1486
|
+
Five are shared and change every component here at once: `--rik-extras-mass`
|
|
1487
|
+
and `--rik-extras-mass-text` (the one filled area), `--rik-extras-statement` and
|
|
1488
|
+
`--rik-extras-reading` (the two sizes), and `--rik-extras-edge` (the load-bearing
|
|
1489
|
+
line).
|
|
1490
|
+
|
|
1491
|
+
### The look these share
|
|
1492
|
+
|
|
1493
|
+
One direction, four rules, repeated by every component here. They come from the
|
|
1494
|
+
medium rather than from a catalogue: a slide is read from three to ten metres in
|
|
1495
|
+
about forty seconds while someone talks over it, and at that distance area, size
|
|
1496
|
+
and position survive while hairlines, small caps, thin strokes and pale tints do
|
|
1497
|
+
not.
|
|
1498
|
+
|
|
1499
|
+
1. **One mass at most.** A single filled area per component, carrying whatever
|
|
1500
|
+
the markup marks. Nothing marked means nothing filled.
|
|
1501
|
+
2. **Two sizes.** A statement size and a reading size, with nothing in between.
|
|
1502
|
+
The absent third step is why no component here has a micro-label.
|
|
1503
|
+
3. **No label above content.** Context is written after the thing, at reading
|
|
1504
|
+
size, in sentence case. No all-caps tag, no tracked-out eyebrow.
|
|
1505
|
+
4. **A line only where two things would otherwise touch.** A table header, a
|
|
1506
|
+
timeline axis, a graph edge. Never as decoration.
|
|
1507
|
+
|
|
1508
|
+
Numbers appear in exactly two components, `deck-flow` and `deck-agenda`, because
|
|
1509
|
+
those two genuinely are sequences. Numbering anything else labels an order the
|
|
1510
|
+
content does not have.
|
|
1511
|
+
|
|
1512
|
+
`reveal` on `deck-flow`, `deck-timeline` and `deck-graph` **emphasises**, it
|
|
1513
|
+
does not hide: at step 0 the whole chain, span or diagram is visible and
|
|
1514
|
+
neutral, because its shape is half the message. `deck-annotate` is the
|
|
1515
|
+
exception and shows nothing at step 0 · there the screenshot must speak first.
|
|
1516
|
+
|
|
1517
|
+
A block is `boxed`. The theme's raised surface measures 1.10 against the page,
|
|
1518
|
+
which is invisible on a projector, so a node that must READ as a block uses the
|
|
1519
|
+
inverse surface: dark on light is the one high-contrast ground this palette has.
|
|
1520
|
+
`tone` fills it with an accent or a status colour instead.
|
|
1521
|
+
|
|
1522
|
+
```html
|
|
1523
|
+
<deck-graph>
|
|
1524
|
+
<deck-lane at="4,40" label="edge"></deck-lane>
|
|
1525
|
+
<deck-group at="46,50,50,44" label="vpc · eu-west-3"></deck-group>
|
|
1526
|
+
<deck-node id="cdn" at="32,22" boxed icon="cloud" label="CDN" note="edge cache"></deck-node>
|
|
1527
|
+
<deck-node id="api" at="58,68" boxed tone="accent" icon="code" label="API"></deck-node>
|
|
1528
|
+
<deck-edge from="cdn" to="api" label="origin"></deck-edge>
|
|
1529
|
+
</deck-graph>
|
|
1530
|
+
```
|
|
1531
|
+
|
|
1532
|
+
```html
|
|
1533
|
+
<deck-graph layout="row">
|
|
1534
|
+
<deck-node id="a" label="Collect" note="raw"></deck-node>
|
|
1535
|
+
<deck-node id="b" label="Decide" note="verdict"></deck-node>
|
|
1536
|
+
<deck-edge from="a" to="b" label="rules"></deck-edge>
|
|
1537
|
+
</deck-graph>
|
|
1538
|
+
|
|
1539
|
+
<deck-graph>
|
|
1540
|
+
<deck-node id="client" at="8,50" label="Client"></deck-node>
|
|
1541
|
+
<deck-node id="api" at="64,25" label="API" note="node 24"></deck-node>
|
|
1542
|
+
<deck-edge from="client" to="api" label="https"></deck-edge>
|
|
1543
|
+
</deck-graph>
|
|
1544
|
+
```
|
|
1545
|
+
|
|
1546
|
+
`deck-graph` places nodes where the author puts them and never runs a layout
|
|
1547
|
+
solver: an automatic layout moves every node when you add one, which breaks
|
|
1548
|
+
"source = output" and makes the file unreadable a year later. `at="x,y"` in
|
|
1549
|
+
percent is the whole layout language, plus `row` and `column` for the two cases
|
|
1550
|
+
that would otherwise be typed out every time. `layout="row"` and
|
|
1551
|
+
`layout="column"` space nodes evenly along one axis and **ignore `at`
|
|
1552
|
+
entirely** · there is no automatic placement beyond these two canned
|
|
1553
|
+
arrangements, and no `serpentine`, `fan-in` or `fan-out` layout, for the same
|
|
1554
|
+
reason: placement is the diagram, not a computed side effect. Hand-placed
|
|
1555
|
+
nodes that end up on top of each other are caught by `rikiki check`, which
|
|
1556
|
+
reports `GRAPH_NODE_OVERLAPS_NODE` (§12b) · that check is the net for hand
|
|
1557
|
+
placement, not a layout solver.
|
|
1558
|
+
|
|
1559
|
+
```html
|
|
1560
|
+
<deck-annotate
|
|
1561
|
+
src="dashboard.png"
|
|
1562
|
+
alt="The ops dashboard"
|
|
1563
|
+
marks="20,30,Queue depth|55,60,Latency spike|82,25,Retries"
|
|
1564
|
+
></deck-annotate>
|
|
1565
|
+
|
|
1566
|
+
<deck-agenda></deck-agenda>
|
|
1567
|
+
```
|
|
1568
|
+
|
|
1569
|
+
`deck-annotate` publishes one step per marker onto its slide, so the reveal
|
|
1570
|
+
works with the arrow keys like any other step · no plugin, no configuration. On
|
|
1571
|
+
paper every marker prints. `deck-agenda` marks the chapter in progress with
|
|
1572
|
+
`aria-current` and each line is a real button, so a reader can tab to a chapter
|
|
1573
|
+
and jump.
|
|
1574
|
+
|
|
1575
|
+
```html
|
|
1576
|
+
<deck-bar value="160" total="538" label="Worth a second look"></deck-bar>
|
|
1577
|
+
|
|
1578
|
+
<deck-bar
|
|
1579
|
+
label="Four thousand findings"
|
|
1580
|
+
segments="blocker:137:danger|major:921:warn|minor:1544:info|info:812:ok|noise:586:muted"
|
|
1581
|
+
></deck-bar>
|
|
1582
|
+
|
|
1583
|
+
<deck-quote author="Marie Dupont" author-role="CTO, Acme">
|
|
1584
|
+
We stopped arguing about the diff and started arguing about the design.
|
|
1585
|
+
</deck-quote>
|
|
1586
|
+
```
|
|
1587
|
+
|
|
1588
|
+
A stacked bar's printed percentages always add to exactly 100 · the rounding
|
|
1589
|
+
drift is absorbed by the largest slice, where it is least visible. A bar given
|
|
1590
|
+
an explicit `total` keeps the honest figure instead: `160 / 538` reads 30% and
|
|
1591
|
+
leaves the rest of the track empty, which is the whole point of drawing it.
|
|
1592
|
+
|
|
1593
|
+
---
|
|
1594
|
+
|
|
1595
|
+
## 21 · Comparison, chains, tables and density
|
|
1596
|
+
|
|
1597
|
+
Four knobs added to components that already existed, chosen over four new
|
|
1598
|
+
elements that would have duplicated a vocabulary the project already has.
|
|
1599
|
+
|
|
1600
|
+
**A directed comparison** · `deck-split` takes `pivot` (a symbol or word between
|
|
1601
|
+
the two columns) and `winner` (`left` or `right`, which rings that side in the
|
|
1602
|
+
accent colour). A neutral split stays neutral: both are absent by default.
|
|
1603
|
+
|
|
1604
|
+
```html
|
|
1605
|
+
<deck-split pivot="→" winner="right">
|
|
1606
|
+
<h1 slot="title">Before and after</h1>
|
|
1607
|
+
<deck-card slot="left"><h3>Before</h3><p>Four hours of manual review.</p></deck-card>
|
|
1608
|
+
<deck-card slot="right"><h3>After</h3><p>Twelve minutes, same coverage.</p></deck-card>
|
|
1609
|
+
</deck-split>
|
|
1610
|
+
```
|
|
1611
|
+
|
|
1612
|
+
**A chain across the width** · `deck-step-list direction="row"` lays the steps
|
|
1613
|
+
side by side with a connector between them. `no-connectors` drops the rules.
|
|
1614
|
+
|
|
1615
|
+
**A table with a point of view** · `deck-csv` takes `highlight-rows` and
|
|
1616
|
+
`highlight-cols` (1-based, space-separated) and `reveal`, which shows one body
|
|
1617
|
+
row per step. Hidden rows keep their space, so the slide never jumps under the
|
|
1618
|
+
audience. A revealing table publishes the step count it needs onto its slide.
|
|
1619
|
+
|
|
1620
|
+
The marked row is a dark band and the marked column takes colour and weight ·
|
|
1621
|
+
one fill per table, never two overlapping tints. Both `deck-csv` and
|
|
1622
|
+
`deck-table` follow the same rule, and both are measured: a fill that a room
|
|
1623
|
+
cannot tell from the page fails the theme-contrast test. Knobs:
|
|
1624
|
+
`--deck-csv-mark-bg`, `--deck-csv-mark-color`, `--deck-csv-mark-col-color`,
|
|
1625
|
+
`--deck-csv-mark-col-on-mark`, `--deck-csv-header-bg`, `--deck-csv-header-rule`.
|
|
1626
|
+
|
|
1627
|
+
**A row of figures** · `deck-stat compact` drops the scale so three or four sit
|
|
1628
|
+
together in a `deck-grid` and read as one family, instead of each claiming the
|
|
1629
|
+
slide.
|
|
1630
|
+
|
|
1631
|
+
### Default density
|
|
1632
|
+
|
|
1633
|
+
`spread` and `fill` (§19) are per-slide, because density is a per-slide
|
|
1634
|
+
judgement. When a whole deck wants a different default, set it once in the theme
|
|
1635
|
+
rather than on every slide:
|
|
1636
|
+
|
|
1637
|
+
```css
|
|
1638
|
+
:root { --rik-slide-spread: space-between; }
|
|
1639
|
+
```
|
|
1640
|
+
|
|
1641
|
+
A per-slide `spread` still wins, and `spread="theme"` says "use the default"
|
|
1642
|
+
explicitly.
|
|
1643
|
+
|
|
1644
|
+
---
|
|
1645
|
+
|
|
1646
|
+
## 22 · Recipes for things that are NOT components
|
|
1647
|
+
|
|
1648
|
+
Four requests deliberately answered by composition. Each is a layout problem,
|
|
1649
|
+
not a missing element, and a component would freeze one arrangement.
|
|
1650
|
+
|
|
1651
|
+
**A checklist of what works and what does not**
|
|
1652
|
+
|
|
1653
|
+
```html
|
|
1654
|
+
<deck-grid cols="2" gap="5">
|
|
1655
|
+
<deck-card color="green">
|
|
1656
|
+
<h3><deck-badge type="ok">Yes</deck-badge> Reviewed in CI</h3>
|
|
1657
|
+
<p>Every merge request, no exception.</p>
|
|
1658
|
+
</deck-card>
|
|
1659
|
+
<deck-card color="red">
|
|
1660
|
+
<h3><deck-badge type="bad">No</deck-badge> Reviewed on the branch</h3>
|
|
1661
|
+
<p>Only when someone remembers.</p>
|
|
1662
|
+
</deck-card>
|
|
1663
|
+
</deck-grid>
|
|
1664
|
+
```
|
|
1665
|
+
|
|
1666
|
+
**Several figures side by side**
|
|
1667
|
+
|
|
1668
|
+
```html
|
|
1669
|
+
<deck-grid cols="3" gap="5">
|
|
1670
|
+
<deck-stat compact num="34">components</deck-stat>
|
|
1671
|
+
<deck-stat compact num="23 KB">gzip</deck-stat>
|
|
1672
|
+
<deck-stat compact num="3">engines</deck-stat>
|
|
1673
|
+
</deck-grid>
|
|
1674
|
+
```
|
|
1675
|
+
|
|
1676
|
+
**A pull quote inside a dense slide** · a `deck-punch` in one column of a split,
|
|
1677
|
+
or a `deck-quote` (§20) when the words belong to someone else.
|
|
1678
|
+
|
|
1679
|
+
```html
|
|
1680
|
+
<deck-split cols="2-1">
|
|
1681
|
+
<deck-md slot="left">The long explanation…</deck-md>
|
|
1682
|
+
<deck-punch slot="right" tone="accent" fit>The one line that matters.</deck-punch>
|
|
1683
|
+
</deck-split>
|
|
1684
|
+
```
|
|
1685
|
+
|
|
1686
|
+
**A single record, field by field** · one entity's fields read top to bottom,
|
|
1687
|
+
each with the value and what backs it, rather than pasted sideways as a
|
|
1688
|
+
rotated CSV. `deck-table` (§20) already carries this: `highlight-rows` marks
|
|
1689
|
+
the field that carries the argument, `reveal` discloses one field per step,
|
|
1690
|
+
and a `deck-source` underneath credits the record. No header-row emphasis is
|
|
1691
|
+
needed · the field column sits at reading weight, the value column carries
|
|
1692
|
+
the statement, and the marked row is the one dark band the table already
|
|
1693
|
+
draws. Reach for this composition instead of a `deck-record` component
|
|
1694
|
+
because a record is a table with one row per field, and `deck-table` already
|
|
1695
|
+
has the emphasis and reveal a record needs; a dedicated component would only
|
|
1696
|
+
duplicate `highlight-rows` and `reveal` under a new name.
|
|
1697
|
+
|
|
1698
|
+
```html
|
|
1699
|
+
<deck-table highlight-rows="3" reveal>
|
|
1700
|
+
<table>
|
|
1701
|
+
<thead><tr><th>Field</th><th>Value</th><th>What makes it authoritative</th></tr></thead>
|
|
1702
|
+
<tbody>
|
|
1703
|
+
<tr><td>Incident</td><td>INC-4471</td><td>Assigned by the tracker on file</td></tr>
|
|
1704
|
+
<tr><td>Detected</td><td>2026-09-03 02:14 UTC</td><td>Pager timestamp, not a recollection</td></tr>
|
|
1705
|
+
<tr><td>Root cause</td><td>Connection pool exhaustion</td><td>Confirmed by the on-call engineer, not guessed</td></tr>
|
|
1706
|
+
<tr><td>Owner</td><td>Platform team</td><td>Assignment recorded in the same tracker</td></tr>
|
|
1707
|
+
</tbody>
|
|
1708
|
+
</table>
|
|
1709
|
+
</deck-table>
|
|
1710
|
+
<deck-source href="https://example.com/tracker/INC-4471">Incident tracker, INC-4471</deck-source>
|
|
1711
|
+
```
|
|
1712
|
+
|
|
1713
|
+
---
|
|
1714
|
+
|
|
1715
|
+
## 23 · The slide budget
|
|
1716
|
+
|
|
1717
|
+
Two ways a slide fails a room, and what the suite does about each.
|
|
1718
|
+
|
|
1719
|
+
**Too full is a defect.** The engine never lets content overflow: every slide
|
|
1720
|
+
shell and every cell carries `overflow: hidden`, so an over-filled slide
|
|
1721
|
+
silently loses its last lines and nobody in the room knows.
|
|
1722
|
+
The slide-budget suite walks every shipped deck slide by slide and fails
|
|
1723
|
+
when a clipping box loses more than a few pixels of content.
|
|
1724
|
+
|
|
1725
|
+
**Too empty is a judgement.** A section title is meant to be sparse. The same
|
|
1726
|
+
spec measures how much of the canvas each slide uses and attaches the report to
|
|
1727
|
+
the run, without failing · the numbers are advice, and §19 is the answer.
|
|
1728
|
+
|
|
1729
|
+
## Presentation previews (0.7.2)
|
|
1730
|
+
|
|
1731
|
+
Overview prepares thumbnails incrementally while idle and keeps its grid for reopening. Content or theme changes invalidate the cache. Presenter previews retain their documents and mirror the current slide step, including annotations; the footer reports the current step. Cover layouts display slide numbers unless `no-counter` is set. Custom components can implement `applyStep(step)` to synchronize their reveal state.
|