Skip to content

feat(registry): add kinetic center build component - #3269

Open
AksharP5 wants to merge 4 commits into
heygen-com:mainfrom
AksharP5:feat/registry-kinetic-center-build
Open

feat(registry): add kinetic center build component#3269
AksharP5 wants to merge 4 commits into
heygen-com:mainfrom
AksharP5:feat/registry-kinetic-center-build

Conversation

@AksharP5

@AksharP5 AksharP5 commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

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

  • Unit tests added/updated
  • Manual testing performed
  • Documentation updated

Validated with:

  • bun run build
  • bun run lint:registry-items kinetic-center-build
  • npx hyperframes check against the mounted component with 25 samples and 11 transition samples
  • Catalog page, payload, and preview generators
  • 62 focused Catalog payload, preview, artifact, and registry tests
  • bunx oxfmt --check on the added source and generated files
  • High-quality 1280x720 render at 30 fps

The 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

@miga-heygen miga-heygen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

  1. Static syncPoints offset vs. dynamic word count -- registry-item.json declares "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 in registry-item.json noting the offset is calibrated to the default text.

  2. 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.

  3. Dead CSS custom-property fallbacks -- #root and .kcb-stage both declare color: var(--color, #171717), but no code ever sets the --color custom property. The JS applies color via stage.style.color, which overrides the CSS declaration. The fallbacks are harmless but misleading -- future maintainers might think changing --color externally would work when it won't (the inline style wins). Consider removing the color: line from .kcb-stage CSS since the JS handles it, or switching the JS to set stage.style.setProperty('--color', value) so the CSS custom property path actually works.


What I verified

  • Deterministic rendering: no Date.now(), no Math.random(), no unseeded randomness. Font loads use display=block (standard HyperFrames pattern).
  • Seek safety: GSAP timeline created with { paused: true }, registered on window.__timelines["kinetic-center-build"]. All word entries use fromTo with explicit start/end states. Prior-word repositioning uses absolute .to() targets (not relative deltas), so every frame resolves correctly on arbitrary seek. immediateRender correctly set to true only 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 with data-start, data-duration, data-track-index.
  • Variable system: all 5 variables (text, font_size, entry_offset, color, font_weight) defined consistently across data-composition-variables on <html>, the JS runtime reader, registry-item.json, the docs MDX VariablesExplorer, and the catalog index. Defaults match everywhere. Numeric validation via numberBetween with correct min/max. Enum validation via explicit allowlist.
  • Attribution: full MIT license from Remocn in the HTML comment header, source commit URL, author/authorUrl/license in registry-item.json, attribution line in docs footer.
  • Registry integration: registry.json, docs.json, and catalog-index.json entries 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" with aria-label on stage, individual words aria-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

miga-heygen and others added 3 commits August 18, 2026 22:12
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
@AksharP5

AksharP5 commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

@miguel-heygen @miga-heygen Thanks for the feedback. I made the following changes:

  • Geist now loads weights 500, 600, 700, and 800.
  • The sync-point metadata notes that 1.2s is calibrated to the default three-word text.
  • The generated payload now has a trailing newline.
  • Color now flows through the root --color variable, with the redundant stage override removed.

Please let me know if anything else is needed.

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.

Add Kinetic Center Build to the Catalog

3 participants