Letter Roll Hover Text

GSAP split-text hover: each letter rolls up and is replaced by its twin, letter by letter, and always finishes.

GSAPHoverSplit text

Prompt

Build a reusable link component with a letter-by-letter "roll" hover effect using GSAP.

Stack: Next.js (App Router), React, TypeScript and Tailwind CSS v4. Install gsap.

COMPONENT: RollLink({ href, className, children: string }) — a client component wrapping next/link.

MARKUP
- Put aria-label={children} on the link. Inside, an aria-hidden flex span.
- Split children into characters, turning spaces into non-breaking spaces. For each character:
  - Outer span: relative, inline-block, overflow hidden, line-height 1.2.
  - Inner span with data-char, display block, containing the character.
  - A second copy of the character, absolutely positioned at top: 100%, left 0, directly underneath.

ANIMATION (onMouseEnter only)
- gsap.to(all [data-char] in this link, { yPercent: -100, duration: 0.22, ease: "power2.inOut", stagger: 0.015 }).
- Each letter slides up out of view while its twin slides into its place, left to right.
- onComplete: gsap.set(chars, { yPercent: 0 }) to reset instantly, which looks identical.

RULES
- Keep a "playing" ref. Ignore new mouseenter events while playing, and don't reverse on mouseleave, so the roll always finishes even if the pointer leaves early.
- No color, background or opacity change on hover — the motion is the only feedback.
- The link's own className controls layout, so it works for plain nav text and for centered pill buttons (e.g. flex, 40px tall, fully rounded, centered).

More in Animations