A button in a field of iron filings that turn toward the pointer and pull in on press.
FreeWeb and MobileMotion
Preview
npx shadcn add @fetaui/attract-buttonPlayground
Label
Disabled
Icons animation
Motion
Installation
Terminal· bash
npx shadcn add @fetaui/attract-button
Label
The button is 144 px wide inside a 272 by 168 px field, so give it open space.
Motion
Accessibility
- A native button. The field is decoration and hidden from screen readers.
Motion
- Filings turn on a 240/21 spring.
- A press pulls them in. Ink depends only on pointer distance, so a press does not darken them.
- The field is always drawn. Its frame loop runs only while filings move.
- With reduced motion, the filings stay static. A disabled button leaves them at rest.
- Swift turns the filings directly, with no spring.
Responsive behavior
- Touch draws the field the same way. Its reaction waits for a press, because a finger has no hover.
Performance
- The filings draw on one canvas. The frame loop runs only while they move, and stops once they settle.
- Only filings within 64 px of the button exist, on a 12 px grid.
- The ResizeObserver, theme observer and frame are cleaned up on unmount. When still it paints once and stays.
Note for AI
Give your coding assistant the Markdown reference instead of screenshots.
- Import from @/components/fetaui/attract-button.
- Children are the label, default Attract. Button props go to the button, and className goes to the field.
- The field is 272 by 168 px, so leave room around it and use one per view.
- The button is 144 px wide, so keep the label to one word.
- Demo clicks do nothing. Wire up onClick.
Related
ButtonComponentOne family for every action, with a label, optional icons and a shortcut key.Gradient ButtonComponentAn accent button that keeps its color in Light and Dark. Hover sweeps a sheen.Expanding Arrow ButtonComponentA wide call to action where a chip opens across the button as its chevrons run.Particle ButtonComponentAn async button that walks Idle, Pending, Success and Error.