Roll button
A pill button whose letters roll up from the middle on hover, with a lift and a springy press.
Behaviour
- A string label rolls up letter by letter, starting from the middle; the old letter fades out as the new one fades in.
- Lifts 2px on hover and presses down to 97%.
- Hover motion only runs on devices that can hover.
- Long labels, joined scripts (Arabic, Indic) and non-string children skip the roll and wrap as plain text.
- Reduced motion: no lift, no roll.
Props
| Prop | Type | Description |
|---|---|---|
| variant | "solid" | "ghost"default "solid" | Filled, or an outline. |
| size | "md" | "lg"default "md" | 46px tall, or 64px with wider padding. |
| href | string | Renders an <a> instead of a <button>. |
| asChild | boolean | Render your one child (a Next Link, a router link) as the button; its children are the label. |
| icon | ReactNode | Sits before or after the label. |
| iconPosition | "start" | "end"default "start" | Which side the icon goes. |
| wide | boolean | Full width. |
| className | string | Merged with cn(), so your classes win. |
| ...rest | button / a props | Everything else (onClick, disabled, ref, aria-*, data-*) goes to the element. data-hover="true" shows the hover state without a pointer. |
Installation
npx shadcn@latest add https://purrfectui.com/r/roll-button.jsonHow to use
import Link from "next/link";
import { Rocket } from "lucide-react";
import { RollButton } from "@/components/ui/roll-button";
<RollButton icon={<Rocket className="size-4" />}>Ship it</RollButton>
<RollButton variant="ghost" asChild>
<Link href="/docs">Read the docs</Link>
</RollButton>Source code
Loading…
Credits
Ported from armour.vaibhavtomar.com.
License
MIT. Copy it into your project and change it as you like.