Enter
Buttons

PushToggle

Press it and the key travels down until it bottoms out, then stays there. Press again and it pops back up.

Start pressed
Disabled

Usage

<PushToggle
  size={72}
  travel={10}
  intensity="normal"
  spring="smooth"
  label="Mute"
>
  <MinusIcon />
</PushToggle>

How the motion works

The deformation is the library's standard press — Y compresses while X widens — and the extruded bottom edge is a hard shadow, so the same transform squashes the shadow along with the face instead of sliding a separate slab around underneath. The widening is read from the spring's velocity rather than its position: a latching key holds its down state indefinitely, and a position-driven flare would park it permanently wider than it started, so the key flares only while travelling and is back to its original width by the time it settles at either end. What separates this from SquishButton is where the edge ends up: a momentary key spends three quarters of its extrude and keeps the rest, so it still reads as raised while held, whereas this one spends all of it. At full press the offset reaches zero and the face covers the shadow exactly, leaving a silhouette with no edge at all. Nothing fades — the key runs out of extrude to show, and that absence is what makes the down state read as pressed rather than as a recoloured button. The two directions do not share a spring config: a real key is pushed down against its spring and thrown back up by it, so the descent runs slow and heavy — slow enough to watch the squash — while the release stays snappy. The overshoot is asymmetric for the same reason: past 0 the key rings above rest and stretches on the rebound; past 1 it can neither sink nor shorten further, so the extra force goes into squash, which is both how the descent lands and the jolt you get from pressing a key that is already down.

useSpringValuevolume-preserving squashextruded edge

Props

PropTypeDefaultDescription
pressedbooleanControlled latch state. Omit for uncontrolled use.
defaultPressedbooleanfalseInitial uncontrolled state.
onChange(pressed: boolean) => voidFires on every toggle.
sizenumber72Edge length of the key face in px.
travelnumber10Height of the extruded bottom edge in px; also how far the key sinks.
intensity"subtle" | "normal" | "strong""normal"Scales how hard the surface squashes.
springSpringLike"bouncy"Spring for the pop back up.
pressSpringSpringLike{ stiffness: 140, damping: 19, mass: 1.25 }Spring for the push down. Slower than the release, as on a real key.
labelstringAccessible name when the key has only an icon.