typstage

0.2.0

Animated HTML presentations from a single Typst file, and a PDF handout from the same source. Typst typesets, the browser moves: magic-move morphing, step-by-step reveals, slide transitions, media and a speaker view in the same file.

What it cannot do#

The limits, in one place, so they are not discovered in front of an audience.

Accessibility#

The hardest limit, and it follows from the design decision on the first page. The slides are SVG outlines: the letters in them are drawn as paths, not as text. Nothing is selectable, nothing is searchable, and a screen reader finds nothing to read – no text alternative, no reading order.

What does work: the document carries a lang attribute from text.lang, navigation is fully operable from the keyboard, and colour and contrast are the theme’s and therefore yours to set. A viewer whose system asks for less motion gets less: prefers-reduced-motion is read at run time. For the same everywhere, set transition: "none" and enter: "none".

Careful
If someone in the room reads with a screen reader, hand out the PDF as well and say what is on each slide. The PDF from the same source carries real text.

A tracked element with no area#

A tracked element takes its place in the browser from a rectangle Typst paints around it. Content with no area leaves that rectangle with none either, and a viewport of zero scales everything inside it to nothing: the element is in the page and cannot be seen. On paper it stands.

The two usual cases – a vertical rule and a place – are handled by the package itself.

#anim(at: 2, place(top + left, dx: 20pt, dy: 50pt,
                   rect(width: 20pt, height: 20pt)))

The rest is reported, not lost: a marker with no width, one with no height, and one nested deeper than four tracked elements each print once to the browser’s console.

typstage: the tracked element 3 on slide 4 has a marker with no width.
Its sprite is given a viewport of that extent, and a viewport of zero
scales everything inside it to nothing: the element is in the page, with
its path and its colour, and cannot be seen. On paper it stands. Put it
in a box with a size, or give the element a width.

The check can only run in the browser. Whether content has an area is not a question the document can answer; only there is the rectangle measurable.

Reach#

Tested in Chrome, Firefox and Safari on macOS, and on an iPhone. Not tested: older browsers, Windows, Android. The runtime uses the Web Animations API, ResizeObserver, PointerEvent and CSS zoom, so a browser from before about 2023 is likely to fall short somewhere.

Size and speed#

A slide is typeset once per state, and every tracked element once more, in a frame of its own. Compile time therefore grows with steps, not with slides, and flipbook grows with frames.

The example decks compile in seconds, and as HTML they weigh between 0.70 and 6.22 MB, the tour with its 48 slides the most. A hundred slides with a flip book on each is a different matter – measure it rather than guess.