Skip to content

slides: discussion #282, both halves — unnumbered slides, and reveal steps within a slide - #464

Merged
nyblnet merged 4 commits into
mainfrom
slides-unnumbered
Sep 13, 2026
Merged

nyblnet merged 4 commits into
mainfrom
slides-unnumbered

Conversation

@nyblnet

@nyblnet nyblnet commented Sep 13, 2026

Copy link
Copy Markdown
Owner

Discussion #282, both options — the maintainer's call: option 1 on its own merits (it covers more than reveals), option 2 as the feature its author preferred.

Commit 1 — unnumbered: true on a slide (Slide panel → Unnumbered, beside Hide slide). In the walk, takes no page number, {{page}} on it continues the previous slide's, the total does not grow. A build of three morph steps reads "18, 18, 18"; a section card sits in the walk without counting. The third answer to paginates beside stateOf and hidden, and the only one still in inLinearFlow — every surface counts by that predicate, so nothing else changed. scripts/test-slides-pagination.ts (20 checks): the pagination rig the hidden-slide work never had.

Commit 2 — fx.step on an element (Presenting → Reveal step). Hidden when the slide appears, revealed on the n-th → running its entrance (a plain fade if none), hidden again by ←; → leaves the slide only when every step is shown; shared steps appear together; gaps are pressed through; arriving backward is fully revealed. One slide stays one slide (page number, morph pairing, note, thumbnail). Decisions DOM-free in slides/src/steps.ts; present.ts is the DOM around them; the speaker counter shows step/max; the presenter's broadcast nav carries the step and audience copies follow it. Old shells show every element at once. scripts/test-slides-steps.ts (30 checks).

Measured in a real browser (manual clock; the driven tab was hidden, so rAF would have lied): opacity 0.00 → 0.08 → 0.66 → 1.00 across the reveal fade; entry hides the steps, → walks 1 / 2+2 / 5, ← hides 5, two more → leave the slide, ← back lands fully revealed; stepped elements stay hidden through a morph arrival.

Also: shape gate + model keys for both keys; six strings in eight catalogs; changelog entries; a DECISIONS entry for why steps are state and not slides. Typecheck, build:single + splice gate, ci-registered 313, i18n, assets, export-secrets all green; no CLAUDE.md/AGENTS.md change.

Appends to [Unreleased] after the broadcast entry — trivial rebase if #463 lands first.

…ous page number

The third answer to "does this slide take a number". A state is a
variant reached by link; a hidden slide is out of the walk; both decline
a number by leaving the walk. Discussion #282's case is the one neither
covers: a build made of three morph steps that the audience reads as one
slide, whose corporate footer must show the page number — and read "18"
three times, not 18, 19, 20. `unnumbered: true` keeps the slide in
inLinearFlow and takes it out of paginates, so every surface that counts
by that predicate — page fields, the presenter's counter, the sidebar —
agrees at once, and the page field on it is the previous slide's number
by the existing rule (count of numbered slides up to and including it).
Absent = counts; every existing file is unchanged. numberHidden is about
hidden slides and does not touch it.

Slide panel: an Unnumbered toggle beside Hide slide, with a hint; the
sidebar shows the continued number dimmed with a trailing dot. Shape
gate and model keys know the key; three strings in all eight catalogs.

scripts/test-slides-pagination.ts is the pagination rig the hidden-slide
work never had: the three ways to decline a number, the page field slide
by slide, the numberHidden and hidden+unnumbered interactions, and a
check that every surface asks the same predicate. 20 checks; registered.
@github-actions

github-actions Bot commented Sep 13, 2026

Copy link
Copy Markdown

Build size

main (ad43bb3) → slides-unnumbered (2da31ab)

app base PR change
bento/slides 691.7 KiB 695.9 KiB +4.1 KiB (+0.60%)
bento/spaces 273.0 KiB 273.0 KiB 0.0 KiB (0.00%)
bento/dash 424.4 KiB 424.4 KiB 0.0 KiB (0.00%)

Updated: 2026-09-13T21:09:40Z

The other half of discussion #282, and the one its author preferred:
"animate on click". An element with fx.step = n is hidden when the slide
appears and revealed on the n-th →, running its entrance (a plain fade
when it has none); ← hides it again; → leaves the slide only once every
step is shown. Elements sharing a step appear together, gaps are pressed
through in one go, and arriving backward lands fully revealed so ← walks
a talk back through the frames it went forward through. One slide stays
one slide — one page number, one morph pairing, one speaker note — and
an older shell shows every element at once.

The decisions are DOM-free in slides/src/steps.ts (StepState:
enter/next/prev/set) and present.ts is the DOM around them: goNext/goPrev
ask the step counter before moving between slides, slidechanged enters
the slide's steps with the direction, stepped elements are hidden by
visibility (not display) so nothing reflows and the entrance can start
from opacity 0, the speaker counter shows step/max, and the presenter's
nav carries the step so an audience copy following a broadcast reveals
and hides in time. Panel: a Reveal step field in the Presenting section.

Measured in a real browser on the manual clock, not believed: the
revealed element's opacity went 0.00 → 0.08 → 0.66 → 1.00 across the
fade; entry hides the steps, → walks 1, 2 (two elements together), 5, ←
hides 5, two more → leave the slide, ← back lands fully revealed; on a
morph arrival the stepped elements sat hidden while the carried element
morphed. scripts/test-slides-steps.ts: 30 checks, registered. Shape gate
and model keys know the key; three strings in eight catalogs; changelog
and DECISIONS entries.
@nyblnet nyblnet changed the title slides: an unnumbered slide stays in the show and continues the previous page number slides: discussion #282, both halves — unnumbered slides, and reveal steps within a slide Sep 13, 2026
…like the sidebar

slideLabel counted by position (!stateOf), so with an unnumbered — or a
hidden — slide in the deck the picker said 'slide 5' while the sidebar
and footer said 4. Found by the lead reviewing #464 against the code; it
predates the PR for hidden slides and the PR states the invariant, so it
lands here. The label is now the number the sidebar shows (paginates),
with '(hidden)' or '(unnumbered)' after it so two entries can share a
number without being confused. Pinned in test-slides-pagination (21).
…h the 22 language packs

The core catalogs were complete but the packs were not: two marker
strings took the source from 800 to 802 keys and the packs' 720 fell to
89.8%, under the 90% floor (fffe694 had sat at exactly 90.0%). The eight
strings this PR adds are now in every pack — 728/802, 90.8%. tk's header
records that its eight are machine-drafted pending its named translator;
the other packs are machine-drafted by convention. The 74 other strings
the packs lack (broadcast, code palette, embed) predate this PR.
@nyblnet
nyblnet merged commit b3ac101 into main Sep 13, 2026
2 checks passed
nyblnet added a commit that referenced this pull request Sep 13, 2026
lasjoh-toho added a commit to lasjoh-toho/bento that referenced this pull request Sep 15, 2026
…pstream)

Adopted the reveal-steps half of upstream nyblnet/bento's own nyblnet#464
("discussion nyblnet#282, both halves — unnumbered slides, and reveal steps
within a slide"). The "unnumbered slides" half is a separate, unrelated
concern bundled in the same upstream commit — deliberately NOT adopted
here, to keep this change scoped to what was actually asked about.

An element with fx.step = n is hidden when the slide appears and
revealed on the n-th → (running its own Enter animation, or a plain
fade when it has none); ← hides it again; → only leaves the slide once
every step has been shown. Elements sharing a step appear together,
gaps are pressed through in one go, and arriving at a slide backward
(← from the next slide) lands with every step already revealed, so ←
walks back through the same frames → walked forward through. One
slide stays one slide throughout — one page number, one morph pairing,
one speaker note.

slides/src/steps.ts copied verbatim from upstream — genuinely
DOM-free, self-contained decision logic (StepState: enter/next/prev/
set) with no dependency on anything specific to this fork, so no
adaptation was needed there at all.

present.ts required careful, deliberate integration rather than a
blind merge, since this fork's own goNext/goPrev/hasNext/hasPrev have
been extensively customized this session already (loop, auto-advance,
the citations end-screen, staged Escape). The step check is inserted
as the FIRST thing each of those four functions does — a pending step
takes priority over slide navigation, exactly as upstream's own design
intends — with every one of this fork's own additions (hideEndScreen,
resetAutoAdvance, the loop wrap-around, exitInsteadOfEndScreen)
preserved entirely intact beneath it. The live-broadcast/presenter-
follow parts of upstream's own present.ts diff (sendNav carrying a
step, followStep) were NOT ported — this fork has no live-broadcast
presenter feature at all for a step number to travel across, confirmed
by checking for bc?.presenter/follow.nav before assuming otherwise.

runEnterFx gained the same only/revealing/atStep parameters upstream
added, letting a reveal-step call restrict which elements animate (and
give a plain fade to one with no fx.enter of its own) without
disturbing its own existing slide-entrance behavior at all.

Editor UI: a new "Schritt" field (own German label, matching this
session's own established convention throughout — everything else
upstream's own diff added stayed in English, including the row label
itself, which would have been the one inconsistently-English label in
an otherwise fully German sidebar) in the element's own Effects
section, right after Enter secs, with a tooltip and a conditional hint
showing the currently-set step number.

Verified: tsc -b clean, full build:single succeeds. Extracted the
copied steps.ts and ran it directly (node --experimental-strip-types)
against the exact walkthrough upstream's own commit message describes
— → revealing step 1, then step 2 (two elements together), then step
5 (pressing through the gap in one go), ← hiding step 5's element,
→ re-revealing it, → finally leaving the slide once every step is
shown, and a backward slide-entry landing fully revealed with
hasNext() correctly false — every single step of that sequence matched
expectations exactly. Also decompressed the actual built .bento.html
to confirm the new German tooltip/hint text and the .bento-step-hidden
CSS rule both landed in what ships.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant