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

PropTypeDescription
variant"solid" | "ghost"default "solid"Filled, or an outline.
size"md" | "lg"default "md"46px tall, or 64px with wider padding.
hrefstringRenders an <a> instead of a <button>.
asChildbooleanRender your one child (a Next Link, a router link) as the button; its children are the label.
iconReactNodeSits before or after the label.
iconPosition"start" | "end"default "start"Which side the icon goes.
widebooleanFull width.
classNamestringMerged with cn(), so your classes win.
...restbutton / a propsEverything 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.json

How 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.

0