Enter
Overlays

AttachmentButton

A file-attach affordance. Press the circle and it grows into a rounded panel while the clip icon shrinks and slides into the corner, turning into a close button as a dashed drop zone fades in beneath it.

Usage

<AttachmentButton
  panelSize={240}
  spring="smooth"
/>

How the motion works

One progress spring drives every number: the panel's edge length, the chip's size and its left/top offset, and the two glyphs' opacity and rotation. The chip's corner position is computed from the panel's own current size rather than sprung on its own path, which is what keeps the shrink and the slide reading as one move instead of two things that happen to overlap. Panel and chip share a single fixed radius instead of interpolating one: at the closed size that radius is exactly half the box, so it draws a circle for free, and at the open size the same number reads as an ordinary corner — nothing about the shape needs its own spring. The drop zone only starts fading in past the halfway point of the panel's growth, so it trails the move rather than starting from nothing at the first frame.

useSpringValueusePress

Props

PropTypeDefaultDescription
open / defaultOpenbooleanControlled or initial state.
onOpenChange(open: boolean) => voidFires when the panel opens or closes.
onFilesSelected(files: FileList) => voidFires with files from the picker or a drop.
closedSizenumber40Edge length of the resting circle, in px.
panelSizenumber240Edge length of the expanded panel, in px.