feat: ship ES modules, tighten routine types, cross-fade scenes - #3
Merged
Conversation
busker published as CommonJS, so it could not be imported as a module in the browser without a bundler. It now builds and ships ESM. The Routine type also let you write shapes that cannot work — steps with a duration, or moves with no duration at all — and silently picked one. It is now a union of ScriptRoutine and TimedRoutine, so the compiler rejects the mix instead of the runtime guessing. Step is tightened the same way. Two fields go back to names that say what they hold: scene -> initialScene and Countdown.seconds -> startSeconds.
kizu hooks TypeScript in with `-r tsx/cjs`, which an ESM package never reaches, so Node was left to handle the spec files itself. Node 22 and 24 strip types natively and passed; Node 20 does not and could not load a single spec. Loading tsx with `--import` covers all three.
A press that changes the scene takes its own target out of layout, and the ring outlives the press on purpose. With no box left to measure, the target resolved to the root's top-left corner, so the cursor teleported off the mock and the click animation finished where nobody was looking. Selectors now remember where they last had a box, so the ring plays out on the spot that was pressed.
Scene switching was display: none / block, so every consumer that wanted a mock to change screens without popping had to reimplement stacking and fading in its own stylesheet. Logfox did exactly that. Move it into busker.css: scenes stack, cross-fade over --busker-scene-ms, and drop out of the accessibility tree once the fade finishes. Because stacked scenes take no space, the element holding them needs a height of its own. In exchange the mock never changes height mid-demo.
Both sites already loaded the same two typefaces, but the busker splash never set the display treatment, so the headline fell back to Starlight's default weight and tracking and the lead read as body copy. Borrow callspec's scale, weight 600 headline with -0.045em tracking and a weight 550 lead, so the two docs sites look like one family.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Four changes to
@logfox/busker, all of which want to land before anything else depends on the published package.Ship ES modules
0.1.0published CommonJS only. The package is now"type": "module"with ESM output, which is what every consumer of a browser library expects. Tests run through thetsxESM loader so Node 20 (no native type stripping) passes CI alongside 22 and 24.Tighten the routine types
Routinewas one interface wheresteps,duration, andmoveswere all optional, so{steps, duration}typechecked and busker had to guess at runtime. It is now a discriminated union —ScriptRoutine(steps) orTimedRoutine(duration) — and the invalid combination is a compile error.Stepgot the same treatment, so{click, to}no longer typechecks.Two fields were renamed for clarity:
sceneis nowinitialScene(it is only the scene busker starts on), andCountdown.secondsis nowstartSeconds(it counts down from there).Keep the click ring on target
When a click changed the scene, the pressed button stopped having a box, and the cursor slid to the corner of the mock while the ring finished playing. It now holds the last place the target was seen, so the ring lands where you pressed.
Cross-fade scene changes
Scene switching was
display: none/block, so any consumer wanting screens to change without popping reimplemented stacking and fading themselves — the logfox site did exactly that. That now lives inbusker.css: scenes stack, cross-fade over--busker-scene-ms, and leave the accessibility tree when the fade ends.Stacked scenes take no space, so the element holding them needs a height. In exchange the mock never changes height mid-demo. Getting started and Styling both say so.
Test plan
npm run validategreenbusker.csswith only colour tokens overridden