Skip to content

fix(onboarding): Clip the SCM reveal during its exit tween - #121495

Draft
jaydgoss wants to merge 1 commit into
masterfrom
jaygoss/vdy-150-clip-scm-collapsible-reveal-exit
Draft

fix(onboarding): Clip the SCM reveal during its exit tween#121495
jaydgoss wants to merge 1 commit into
masterfrom
jaygoss/vdy-150-clip-scm-collapsible-reveal-exit

Conversation

@jaydgoss

@jaydgoss jaydgoss commented Aug 6, 2026

Copy link
Copy Markdown
Member

TLDR

ScmCollapsibleReveal did not clip its content while collapsing, so the exit tween spilled over whatever sat below it. Overflow now rides the animation targets instead of React state, which is the only way to reach an exiting child.

Details

AnimatePresence renders an exiting child from renderedChildren, React state holding the element captured when it was last present. This component drove overflow through useState into style={{overflow}}, and onAnimationStart fired setOverflow('hidden') on collapse. That re-render produces a new element which is then discarded, because AnimatePresence keeps rendering the frozen one carrying overflow: visible. The whole collapse ran unclipped.

The existing openRef was a workaround for the same trap one level over, in the completion callback's closure. It does not help here: nothing routed through React props reaches an exiting child.

Overflow now comes from the animation targets, which bypass reconciliation and write through the value pipeline:

  • initial and exit set overflow: hidden
  • animate releases it with transitionEnd: {overflow: 'visible'}

Two framer-motion behaviors this leans on, both verified in 12.38.0 rather than assumed:

  • isAnimatable('hidden') is false, so canAnimate fails and AsyncMotionValueAnimation applies the value immediately, before makeAnimationInstant. The clip lands at the start of the collapse instead of being tweened across it.
  • With initial={false}, makeLatestValues uses the animate target and folds transitionEnd keys into the starting values, so a settled-open mount begins at overflow: visible. That matches the previous useState(open ? 'visible' : 'hidden').

Open behavior is unchanged. The state, the ref, and both animation callbacks are no longer needed.

This was latent rather than new: every consumer (ScmCollapsibleSection, ScmAlertOptionCard, ScmAlertFrequencySection, ScmIssueAlertNotificationOptions) had the same unclipped collapse. Their content is short and none of them sit inside a bordered card, which is probably why it went unnoticed.

Refs VDY-150

Legal Boilerplate

Look, I get it. The entity doing business as "Sentry" was incorporated in the State of Delaware in 2015 as Functional Software, Inc. and is gonna need some rights from me in order to utilize my contributions in this here PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Sentry can use, modify, copy, and redistribute my contributions, under Sentry's choice of terms.

AnimatePresence renders an exiting child from a frozen snapshot of its last present props, so the state-driven overflow style never reached the DOM on collapse and the content spilled over the sections below.

Drive overflow through the animation targets instead, which bypass reconciliation. framer-motion applies non-animatable values immediately, so the clip lands at the start of the exit rather than being tweened. The state, ref, and both animation callbacks are no longer needed.
@jaydgoss jaydgoss self-assigned this Aug 6, 2026
@linear-code

linear-code Bot commented Aug 6, 2026

Copy link
Copy Markdown

VDY-150

@github-actions github-actions Bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant