Skip to content

fix(lint): flag seek-unsafe CSS transitions - #3797

Merged
miguel-heygen merged 6 commits into
heygen-com:mainfrom
Ftgn-dpA:fix/css-transition-lint
Oct 2, 2026
Merged

miguel-heygen merged 6 commits into
heygen-com:mainfrom
Ftgn-dpA:fix/css-transition-lint

Conversation

@Ftgn-dpA

@Ftgn-dpA Ftgn-dpA commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

What

Add a css_transition_used lint error for seek-unsafe CSS transition
declarations in <style> blocks and inline styles.

The rule covers standard and -webkit- transition properties, while allowing
explicit transition: none / transition-property: none declarations and
all-zero transition / transition-duration / transition-delay times (the
reduced-motion and render-lock reset the registry uses in about 20 files), and
ignoring custom properties.

Linting all 669 registry HTML files with the rule finds one real case:
.hero-section in the product-promo example had transition: transform 0.8s
while the timeline tweens its y, so the browser eased GSAP's per-frame writes on
the wall clock. That declaration is removed.

Why

CSS transitions run on the browser clock rather than the seekable Hyperframes
timeline. Class or attribute changes can therefore restart a transition on
fresh render workers, causing parallel renders and snapshots to produce
different frames.

Fixes #3493.

How

Use PostCSS to inspect actual declarations instead of matching raw CSS text.
Unsafe declarations report an error with guidance to keep state changes in
classes or attributes and move the visual animation onto the paused GSAP
timeline.

Test plan

  • Unit tests added/updated

  • Manual testing performed — not required for this parser-only rule

  • Documentation updated — docs/packages/lint.mdx lists the rule

  • bun run --filter @hyperframes/lint test — 648 passed

  • bun run --filter @hyperframes/lint typecheck

  • bunx oxlint packages/lint/src/rules/core.ts packages/lint/src/rules/core.test.ts

  • bunx oxfmt --check packages/lint/src/rules/core.ts packages/lint/src/rules/core.test.ts

Severity

css_transition_used reports a warning, not an error. The slideshow skill deliberately uses a presenter-only CSS camera glide for live navigation (rendered video must not depend on it), and an error would fail hyperframes lint on every deck built from it. A warning still tells authors that a CSS transition will not seek deterministically in a render.

@miguel-heygen miguel-heygen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for adding this — catching a wall-clock transition next to a paused GSAP timeline is a good rule to have.

One issue with the current exemption: it only allows the literal value none, so transition-duration: 0s (and !important variants) gets flagged as an error too. That's the pattern used for a reduced-motion / render-lock reset, and it's already used that way in about 20 files in this repo's own registry — with the current rule there's no way to keep using it without triggering an error. Could the rule treat a zero duration the same as none? That should unblock those existing files without weakening the check for anything that actually animates on the wall clock.

The registry's reduced-motion and render-lock resets use transition-duration: 0s and
transition-delay: 0s, which never run on the browser clock. Also drops the one real
seek-unsafe transition the rule finds in the product-promo example.
@miguel-heygen
miguel-heygen merged commit f2eb6d9 into heygen-com:main Oct 2, 2026
169 of 210 checks passed
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.

lint: flag CSS transition (seek-unsafe; adapter only covers @keyframes)

2 participants