feat(registry): add kinetic center build component - #3269
Conversation
miga-heygen
left a comment
There was a problem hiding this comment.
LGTM with nits -- clean port, solid seek-safe architecture, one functional gap in font loading.
Medium
Font link only loads weight 600, but the variable offers 500/600/700/800
kinetic-center-build.html line (inside <template>):
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Geist:wght@600&display=block"
/>The font_weight variable exposes four options (500, 600, 700, 800) and the JS correctly applies the chosen weight to the stage via stage.style.fontWeight. But the Google Fonts request only fetches the 600 slice. When a user picks 700 or 800, the browser either synthesizes bold from the 600 file or ignores the weight entirely -- neither produces the correct Geist rendering.
Fix: request the range you advertise.
href="https://fonts.googleapis.com/css2?family=Geist:wght@500;600;700;800&display=block"The same link appears in the docs MDX source accordion and in the base64-encoded payload in kinetic-center-build.json -- all three need updating.
Nits
-
Static
syncPointsoffset vs. dynamic word count --registry-item.jsondeclares"offset": 1.2, which is correct for the default 3-word text (10/30 + 2 * 13/30 = 1.2s). With longer or shorter phrases the actual lock time shifts (the timing-scale logic compresses it), so the sync point becomes inaccurate. Not a blocker -- sync points are hints -- but worth a comment inregistry-item.jsonnoting the offset is calibrated to the default text. -
No trailing newline in
docs/public/catalog/components/kinetic-center-build.json-- the diff ends with\ No newline at end of file. Most editors and linters prefer a final newline. -
Dead CSS custom-property fallbacks --
#rootand.kcb-stageboth declarecolor: var(--color, #171717), but no code ever sets the--colorcustom property. The JS applies color viastage.style.color, which overrides the CSS declaration. The fallbacks are harmless but misleading -- future maintainers might think changing--colorexternally would work when it won't (the inline style wins). Consider removing thecolor:line from.kcb-stageCSS since the JS handles it, or switching the JS to setstage.style.setProperty('--color', value)so the CSS custom property path actually works.
What I verified
- Deterministic rendering: no
Date.now(), noMath.random(), no unseeded randomness. Font loads usedisplay=block(standard HyperFrames pattern). - Seek safety: GSAP timeline created with
{ paused: true }, registered onwindow.__timelines["kinetic-center-build"]. All word entries usefromTowith explicit start/end states. Prior-word repositioning uses absolute.to()targets (not relative deltas), so every frame resolves correctly on arbitrary seek.immediateRendercorrectly set totrueonly for index 0; other words default to CSS opacity 0 before their tween starts. - Clip structure:
class="kcb-clip clip"present on the clip div withdata-start,data-duration,data-track-index. - Variable system: all 5 variables (
text,font_size,entry_offset,color,font_weight) defined consistently acrossdata-composition-variableson<html>, the JS runtime reader,registry-item.json, the docs MDXVariablesExplorer, and the catalog index. Defaults match everywhere. Numeric validation vianumberBetweenwith correct min/max. Enum validation via explicit allowlist. - Attribution: full MIT license from Remocn in the HTML comment header, source commit URL,
author/authorUrl/licensein registry-item.json, attribution line in docs footer. - Registry integration:
registry.json,docs.json, andcatalog-index.jsonentries all in correct alphabetical order. - Demo composition: proper 1280x720 frame, white background clip, component mounted via
data-composition-src, own paused timeline registered. - Responsive sizing: auto-shrink logic correctly scales font down to floor of 24px when text exceeds 90% of container width, with re-measurement.
- Accessibility:
role="img"witharia-labelon stage, individual wordsaria-hidden="true". - Position pre-computation:
positionsAt[n]array correctly computes center-aligned x offsets for every intermediate word-count state, ensuring smooth recentering as each word lands.
Review by Miga
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…-center-build # Conflicts: # registry/catalog-artifact/local-vectors.bin # registry/catalog-artifact/local-vectors.json # registry/registry.json
|
@miguel-heygen @miga-heygen Thanks for the feedback. I made the following changes:
Please let me know if anything else is needed. |
What
The Catalog did not have a text effect where each new word pushes the existing phrase left and recenters the complete line. This adds Kinetic Center Build as an installable component.
Fixes #3268.
Interactive preview: https://hyperframes.dev/p/456c3191-c11c-4c1e-85fe-f6089dc03238
Why
Hyfrme already includes this Remocn effect, but using it in HyperFrames meant carrying a compiled React runtime. A native Catalog component makes the motion readable, editable, and reusable through
npx hyperframes add kinetic-center-build.How
Rebuilt the pinned Hyfrme/Remocn motion as seek-safe HTML and GSAP. The original two-second timing and centering behavior remain intact. Text, font size, entry offset, color, and weight are exposed as Catalog variables, and longer phrases shrink to stay inside the host frame.
The component retains Remocn's attribution and full MIT notice. This also adds the generated Catalog page, player payload, navigation, and registry entries.
Test plan
Validated with:
bun run buildbun run lint:registry-items kinetic-center-buildnpx hyperframes checkagainst the mounted component with 25 samples and 11 transition samplesbunx oxfmt --checkon the added source and generated filesThe browser gate reports zero runtime, layout, motion, or contrast errors. Its only warning is the expected Google Fonts advisory for Geist, which HyperFrames resolves during compilation. The pre-commit hook also notes that a maintainer will regenerate the on-device search vector before merge.
Source and license
Example
comparison.mp4