One deck, from start to finish#
One talk in a single file, from the empty line to the handout. Every step adds exactly one thing, and together they cover what an ordinary deck needs.
The subject is a school exercise: How tall is the tower? A pole 1.20 m high casts a shadow of 0.90 m; the tower casts a shadow of 21 m. Find its height.
The empty file#
Two lines are a deck: one fetches the package, one says this document is a presentation.
#import "@preview/typstage:0.2.0": *
#show: presentation.with(title: [How tall is the tower?])It is compiled twice, from the same file:
typst compile tower.typ tower.html --format html --features html
typst compile tower.typ tower.pdfOpen the HTML and page with the arrow keys. So far there is only the title slide – title: alone produces it.
The first slide#
== is a slide, the text below it its body; = is a section slide.
= The question
== A pole and a tower
A pole 1.20 m high casts a shadow of 0.90 m.
The tower casts 21 m. How tall is it?No more structure than this is needed.
What is to appear one after another#
stagger splits a bullet list at its items: one step per item.
== What we see
#stagger[
- The sun stands equally high for both.
- So the angle is the same.
- So the triangles are similar.
]The slide now has three steps: the first point stands there with the body, and each of the other two comes one step later.
A box that has to stick#
The sentence that matters does not belong in the list. callout sets it apart, with a bar down its left side.
== What we see
#stagger[
- The sun stands equally high for both.
- So the angle is the same.
- So the triangles are similar.
]
#callout[
In similar triangles corresponding sides stand in the same ratio.
]The caption of the box follows the document language. title: changes it, title: none leaves it off.
The formula that rewrites itself#
The same formula stands on two slides, and between them it flies – glyph by glyph, as far as they recognise one another. Both slides call it by the same name; a label is all it takes.
== The ratio
#align(center, morph(<tower>, $ h / 21 = 1.2 / 0.9 $))
== Solved for h
#align(center, morph(<tower>, $ h = 21 dot 1.2 / 0.9 $))In the browser h, the fraction bar and the numbers travel to their new place instead of vanishing and coming back. On paper the chain becomes the calculation, one slide per line.
A note only you see#
speaker-note belongs to the slide and appears nowhere on the screen.
== The result
#statement[$ h = 28 "m" $]
#speaker-note[
Let them work it out first, then show it. Anyone saying 28 has rounded --
28.0 is more precise than the measurement allows.
]It appears in the speaker view – opened in a second window with n – and in the handout, beside its slide.
A note the room can read#
#footnote works, and it does not look like it does in a book: the note stands at the foot of its slide, under a short rule, and the numbering starts again on every slide. A footnote on slide seven is number one there.
== The measurement
The pole is 1.20 m high#footnote[Measured at the base, not at the tip.] and
casts a shadow of 0.90 m.It reaches all three outputs: the browser, the PDF, and the handout beside its slide. A footnote standing inside a reveal chain appears with its marker: in the browser the note is revealed on the same step, so the foot of the slide gives nothing away that the talk has not shown yet. And it goes with its marker, out of a chain inside a chain as well: a stagger inside a version of an alternatives takes its notes along when the version goes. Its place is held from the start, so nothing jumps when it arrives.
alternatives only the last version stands, and so only its note; the place of the others is kept free, and the numbers are the browser’s. pages: "step" sets the same slide once per step, and there the paper shows what the browser reveals: a note stands on the pages on which its marker is revealed, with the number it has in the browser, and its place is kept free on the others.figure, an #align(center) – reaches both outputs, but not the same place: the browser centres it, the paper starts it at the beginning of the line.#footnote[…] – only the setting is the deck’s own.Not in a heading. A title is repeated – as a running head above the slides of its section, in the contents, in the speaker view – and every repetition sets the footnote again: the slides after it carried the note of their section title instead of their own, and their own numbering shifted from 1 to
- A footnote in a title stops the compilation and says so.
A PDF that unfolds#
pages: "step" sets one page per step instead of one per slide. What is not there yet is not there yet, and what has gone is gone – the paper turns the way the talk does.
#import "@preview/typstage:0.2.0": *
#show: presentation.with(
title: [How tall is the tower?],
pages: "step",
)
== Two ways
#stagger([The shadow], [The angle])Everything that reveals takes part: #pause, anim, stagger, tiles, alternatives, build, cue and scene – a scene gets one page per stop, not one per tween frame. A piece that is not due yet keeps its space, so nothing shifts from one page to the next.
Two things are worth knowing. A cue group is called out at the keyboard, so on paper it can only follow the written order. And a camera move has no page of its own: on paper there is no camera, so its page would stand there twice.
And two things concern the Typst document underneath. A figure, an equation and a heading carry their label on the first page of a slide only; the pages after it set them without. So @fig finds its target exactly once, leads to where the slide opens and gives the same number as every page of it, and query(<fig>) finds one per slide. A show rule on such a label therefore does not reach the later pages; one on the kind, such as show figure, reaches all of them. Inside a card, callout, statement, fit, side-by-side(equal: true) or build, in a list item – also as a point of a cue group – and in a scene-layer, cue-layer or stagger-layer, the label stays on every page, and a reference to it stops the compilation: a figure that is referred to then goes beside the card or the list rather than into it.
A deck’s own state, on the other hand, runs on across the pages of a slide. Every page carries out its update again: Task #context task.get() after task.update(n => n + 1) counts 1 and 2 on the two pages of a slide with a #pause instead of 1 twice, and the next slide says 3. The package cannot set it back, because Typst reveals neither what a state starts from nor what an update does to it. For numbering, a counter does the job, and the pages set that one back; and an update with a value rather than a function gives the same on every page.
Expect two to three pages per slide – the example decks come out at that.
The handout#
One argument turns the deck into a sheet to write on: three slides per page, the note beside each one, ruled lines beside any slide that has none.
#import "@preview/typstage:0.2.0": *
#show: presentation.with(
title: [How tall is the tower?],
handout: 3,
)The whole source#
Nothing in it that was not explained above.
#import "@preview/typstage:0.2.0": *
#show: presentation.with(
title: [How tall is the tower?],
author: [Year 9],
theme: themes.lesson,
)
= The question
== A pole and a tower
A pole 1.20 m high casts a shadow of 0.90 m.
The tower casts 21 m. How tall is it?
== What we see
#stagger[
- The sun stands equally high for both.
- So the angle is the same.
- So the triangles are similar.
]
#callout[
In similar triangles corresponding sides stand in the same ratio.
]
= The calculation
== The ratio
#align(center, morph(<tower>, $ h / 21 = 1.2 / 0.9 $))
== Solved for h
#align(center, morph(<tower>, $ h = 21 dot 1.2 / 0.9 $))
== The result
#statement[$ h = 28 "m" $]
#speaker-note[
Let them work it out first, then show it. Anyone saying 28 has rounded --
28.0 is more precise than the measurement allows.
]side-by-side – a drawing on the left, the words on the right – and theme:, which changes the whole look without moving a line of content.