Slides
The contents below link to each definition. Function entries show the signature, then a description, then the parameters with their types and defaults; variable entries show the declared type.
Creates one logical slide command.
slide(
layout: auto,
numbered: auto,
invert: false,
cells: (:),
background: auto,
foreground: auto,
..bodies
) -> contentA logical slide is one unit of content, which may render as several physical frames once incremental steps are applied.
#mosaic.slide[
== Structure
Every slide resolves to a grid tree.
]Choosing a layout
The selection is the one positional subject, so slide("content", variant: "body")[...] and slide(layout: "content", variant: "body")[...] are the same slide.
auto: the configuredcontentlayout. The default."content","title","section": the matching entry insetup(layouts:). The name also determines numbering and the section lifecycle.- A
mosaic.layouts.*value: used directly, carrying its own semantic name. - A raw
mosaic.grids.*tree: used directly and treated as a content layout.
Supplying content
Use one of the two forms, never both on the same slide:
- Positional bodies, filling cells in depth-first layout order.
- A
cells:dictionary keyed by cell id, which is order-independent and lets a slide skip cells.
#mosaic.slide(cells: (
header: [== Named cells],
body: [Order does not matter here.],
))Planes
background: and foreground: are full-slide layers rather than grid cells, so they have parameters of their own. auto inherits the plane declared on setup, none suppresses it for this slide, and content overrides it.
#mosaic.slide(
cells: (body: [Over a photograph.]),
background: mosaic.components.image("cover.webp"),
)Layout fields
Any other named argument is a field of the selected layout, so the slide refines the configured layout rather than replacing it, and fields the theme set survive:
#mosaic.slide(layout: "title", variant: "academic")This requires layout: auto or a layout name. With an explicit mosaic.layouts.* value the constructor is already at hand, so pass the fields to it instead.
layout | auto | str | dictionaryWhich layout resolves this slide: auto for the configured content layout, one of the names "content", "title", "section", or "image", a mosaic.layouts.* value, or a raw mosaic.grids.* tree. Also accepted as the leading positional argument. |
numbered | auto | boolWhether the slide contributes to logical slide numbering. auto numbers every layout except title and section, which are deck chrome; an explicit boolean always wins. |
invert | boolWhether to invert this slide’s polarity: the slide ground takes the deck’s text color, type is knocked out in the canvas color, and the muted and line colors are derived to match. Works with any layout, so an inverted title, section plate, or big-number slide are all one flag. Cell text and components follow the inverted palette, including fills a theme pins on <mosaic-cell-*> labels; colors applied inside the content itself, such as an explicit text(fill: ..), keep their own values. |
cells | dictionaryCell bodies keyed by cell id. Mutually exclusive with positional bodies. |
background | auto | content | noneFull-slide layer drawn behind the grid. auto inherits the deck background from setup, none suppresses it. |
foreground | auto | content | noneFull-slide layer drawn over the grid. auto inherits the deck foreground from setup, none suppresses it. |
..bodies | argumentsPositional cell bodies in depth-first layout order, plus any named arguments forwarded as fields of the selected layout. |
Reads what the deck knows about itself: the metadata declared on setup, and the position of the slide being rendered. This is what a custom composition reads instead of restating the deck, and what deck chrome reads instead of counting for itself.
info() -> dictionaryReturns a dictionary with six fields. Four are the deck metadata, exactly as setup received it:
title: the deck title.subtitle: the deck subtitle.authors: always an array of resolved author records, whether the deck wrote a bare name or a fulllayouts.authorrecord. Every entry carriesname,affiliations,email,orcid, andcorresponding.date: the deck date.
Two are the position of the slide being rendered, which is what makes the reader contextual:
slide: a dictionary ofnumber,total, andnumbered. The count is of logical slides rather than pages, so one incremental slide is one number however many frames it prints. Unnumbered slides (titles and sections, by default) are passed over by the count and reportnumbered: false, which is the signal deck furniture uses to quiet itself on those pages.section: a dictionary ofnumber,total, andtitle. The number is the current section’s, counting slides that use thesectionlayout, and the title is that section’s own text with any heading stripped. Before the deck’s first section slide the number is0and the title isnone.
Call it inside a context block (slide bodies, planes, and show rules already are one):
#mosaic.slide(
background: mosaic.components.image("cover.webp", scrim: black.transparentize(45%)),
)[
#context {
let deck = mosaic.info()
place(top + left, text(size: 2.2em, weight: "bold", deck.title))
place(bottom + left, deck.authors.map(author => author.name).join([, ]))
}
]The metadata half is the escape hatch for title pages the built-in variants do not draw: declare the information once on setup, and a hand-built cover reads it back instead of duplicating it. The position half is what a footline or a headline is made of, and it is the same reading components.progress does, so a theme drawing its own chrome keeps no counters of its own:
#let footline = context {
let deck = mosaic.info()
grid(
columns: (1fr, 1fr),
deck.section.title,
align(right)[#deck.slide.number\/#deck.slide.total],
)
}Attaches non-rendering speaker notes to a logical slide.
note(body) -> contentNotes never appear in the slides themselves. They are collected and shown by the "speaker" and "notes" outputs of setup.
#show: mosaic.setup.with(output: "speaker")
#mosaic.slide[
== Results
#mosaic.note[Mention the confidence interval before the table.]
The estimate holds under both specifications.
]Multiple note blocks on one slide accumulate in source order. Wrap a note in steps.on, steps.reveal, or steps.replace to tie it to the same physical frames as the incremental content it belongs with, so the speaker view shows it beside the frame it describes.
body | contentThe note text. Ordinary content, so lists and emphasis work as usual. |
Scales one block of content to the space it is given.
fit(
body,
width: auto,
height: auto,
wrap: true,
grow: false,
shrink: true
) -> contentMosaic never resizes body content on its own, so a slide holding more than it can show reports an overflow rather than shrinking. fit is the explicit per-block exception, for content whose size the author does not control: a wide table, a chart, a generated list, a number meant to fill the slide.
It measures the content against the region the call sits in and scales it geometrically, so proportions are preserved and the surrounding layout accounts for the new size. With no width or height it fits the whole region.
#mosaic.slide[
== A long argument
#mosaic.fit(generated-list)
]Fitting works in cells, in the background and foreground planes, and in ordinary content. Pass grow: true for display type that should fill its cell rather than merely avoid overflowing it:
#mosaic.fit(grow: true)[42%]Content that must not be re-laid out
By default the content is offered the region’s width first, so text and lists wrap into the cell and are scaled only if they are still too tall. A table, chart, or diagram would rearrange its own columns instead, which changes the composition rather than its size. Pass wrap: false to scale such a block exactly as it stands:
#mosaic.fit(wrap: false, my-wide-table)Overflow
A fitted block cannot overflow, so it emits no <mosaic-overflow-warning> record and never fails an overflow: "error" compile. A cell that fits its content therefore stops reporting how full it is.
Incremental content and speaker notes
Fitting measures its body, which means holding it inside a closure that the slide runtime cannot look into. Incremental markers and speaker notes are found by walking the slide’s content, so anything inside a fitted block would be invisible to that walk: the reveals would collapse into one frame and the notes would vanish. fit rejects such a body rather than dropping it silently. Keep pause, steps, and note outside the fitted block, or fit each revealed part on its own.
body | contentThe content to scale. |
width | auto | length | relative | fractionWidth to fit into. auto uses the full width of the region. |
height | auto | length | relative | fractionHeight to fit into. auto uses the full height of the region. |
wrap | boolLet the content re-lay out at the available width before it is measured. Pass false for a block whose own arrangement must be preserved. |
grow | boolScale content up when it is smaller than the space available. |
shrink | boolScale content down when it is larger than the space available. |