Enter
Toggles

DownloadButton

Press it and the arrow drops, the tray flexes under the impact, then the arrow re-enters from above.

Usage

<DownloadButton
  size="md"
  dropDistance={7}
  trayFlex={2.6}
  intensity="normal"
  spring="smooth"
/>

How the motion works

The sequence is three coupled springs rather than a keyframed timeline: the arrow falls under a bouncy spring, the tray flexes and rebounds when the arrow arrives, and the arrow then returns from above. Driving the tray from the arrow's arrival — instead of running both on independent fixed delays — is what makes the impact read as a collision. The arrow fades as it sinks so it enters the tray rather than overlapping its stroke.

useSpringStateusePressuseReducedMotion

Limitations

Known gap. Impact timing uses a tuned delay rather than reading the arrow spring's position, because the fall and the flex are separate springs. Changing the fall spring to a much slower preset would desynchronise the impact.

Props

PropTypeDefaultDescription
onDownload() => voidFires immediately on press, before the animation.
dropDistancenumber7How far the arrow falls, in SVG units.
trayFlexnumber2.6How far the tray bows on impact.
resetDelaynumber220Pause before the arrow re-enters, in ms.