Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Text

Pro

Text Cursor for React

An area whose pointer leaves a trail of characters: sparkles, emoji or a word spelled along the path. For React with Base UI, when a section should sparkle under the pointer.

Framework

Text Cursor leaves a trail behind the pointer, like breadcrumbs. As the pointer moves through its area, the next character of its text is dropped every few pixels, turned the way the pointer is going, and drifts up as it fades: sparkles scatter behind a flourish, emoji take turns, and a word spells itself along the path.

Use it for a playful hero, a celebration, a kids' page or a section that should feel alive under the pointer. For a trail of the text itself, use Echo Text; to light up letters near the pointer, Spotlight Text. The trail is a fixed set of characters reused in turn: a handler writes where the next one goes to CSS variables and restarts a CSS keyframe animation the install adds to your stylesheet, with no state, no animation library and no frame loop. With reduced motion each character only fades where it was dropped.

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Usage

import { TextCursor } from "@/components/ui/text-cursor";

The trail plays over its own children, inside its box.

<TextCursor className="h-64" text="✨">
  <h2>Move the pointer here</h2>
</TextCursor>

Demos

Word

A word is dropped a character at a time and in order, so it spells itself along the pointer's path. spacing is how far the pointer moves between one character and the next, 40 pixels by default: about a letter's width reads best for a word. Here the trail is styled through its slot, [&_[data-slot=text-cursor-char]]:text-xl, and takes the area's colour.

Preview width

Trail

count is the most characters on screen at once, 8 by default, and duration how long each lingers, 1000 ms: more of both makes a longer, denser trail. Several emoji take turns. orient={false} keeps every character upright, whichever way the pointer moves.

Preview width

Accessibility

The trail is decoration: hidden from screen readers and from the pointer, so it's never read out and never blocks a click on the content beneath, and clipped to the area. The content is your children, read and used as usual. On a touch screen a tap drops one character where it lands, and dragging a finger scrolls the page as usual, with no trail. With reduced motion each character appears and fades where it was dropped, without drifting.

FAQ

Does it re-render as the pointer moves?

No. The trail is a fixed set of characters rendered once. As the pointer passes each spacing, a handler moves the next one to the pointer through CSS variables and restarts its animation; nothing else runs, and nothing at all once the pointer stops.

What does a word do?

Its characters are dropped in order, one every spacing pixels, each turned along the path, so moving the pointer writes the word. End it with a space to separate one pass from the next.

How do I size or colour the trail?

The characters take the area's text colour, and each is a data-slot="text-cursor-char" you can style from outside, such as [&_[data-slot=text-cursor-char]]:text-4xl on the component.

Can the trail cover the whole page?

The trail stays inside the component's box, clipped to it. For the whole page, wrap the page's content in it, so its box is the page's.

What happens on a touch screen?

A tap drops one character where the finger lands. Dragging scrolls the page as it always does, with no trail, so the area never gets in the way of scrolling.

What happens with reduced motion?

The trail still follows the pointer, but each character only appears and fades where it was dropped, without growing, drifting or turning.

API Reference

TextCursor

<div> data-slot="text-cursor"

PropType
textstring

What trails the pointer: an emoji, a symbol or a word, dropped a character at a time and in order, so a word spells itself along the path.

children?ReactNode

What the trail plays over: the area's own content.

count?number

The most trail characters on screen at once.

Default
8
duration?number

How long a trail character lingers, drifting up as it fades, in milliseconds.

Default
1000
orient?boolean

Whether each character turns to the way the pointer moves (never upside down). @default true.

Default
true
spacing?number

How far the pointer moves between one trail character and the next, in pixels. @default 40.

Default
40
render?ReactElement | ((props: object, state: object) => ReactElement)

Replace the host element or compose it with another component.

Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string

Merged with the part's classes.

CSS variableType
--text-cursor-durationstring

A trail character's drift and fade (1000ms).

  • Pro

    Echo Text

    Decorative

    Fainter copies trailing the text

  • Pro

    A trail of churning glyphs

  • Pro

    Magnet Text

    Interactive

    Letters pulled toward the pointer

  • Pro

    Letters thicken near the pointer

  • Pro

    Erase Text

    Interactive

    A fading trail through the letters

  • Every detail deserves the spotlight

    Pro

    Spotlight Text

    Interactive

    A beam that follows the pointer

All 97 text effects