Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Text

Pro

Spotlight Text for React

Text lit by a spotlight that follows the pointer, the rest of the line dimming while it's there. For React with Base UI, when a headline should come alive under the pointer.

Framework

Spotlight Text shines a round beam on the text under the pointer. While the pointer is over it, the rest of the line dims and the letters under the beam stay bright; the beam glides after the pointer, and when the pointer leaves, the light comes back up everywhere. At rest the text is fully lit, so it always reads.

Use it for a hero line or a tagline that invites the pointer to explore it, like a torch sweeping a dark wall. To show a different message under the pointer, use Xray Text; to thicken the letters near it instead, Variable Proximity; for a coloured light on an outline, Text Hover Effect. The beam is a CSS mask, a radial gradient centred on two registered CSS properties that each move of the pointer writes and a transition eases, with no animation library and no frame loop.

Preview width

Every detail deserves the spotlight

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 { SpotlightText } from "@/components/ui/spotlight-text";
<h2>
  <SpotlightText text="Every detail deserves the spotlight" />
</h2>

Demos

Edge

edge is the beam's edge: soft, the default, feathers it into the dark like a torch through fog; hard cuts a crisp disc, like a stage light.

Preview width

Ambient

ambient is how much of the text outside the beam still shows while the pointer is over it, from 0, dark, to 1, no dimming; 0.15 by default. radius is the beam's radius in pixels: by default it's twice the text's size, so give body text a smaller one, and the beam reads a few words at a time.

Preview width

Accessibility

Screen readers read the text once, from a visually hidden copy. The text is fully lit whenever the pointer isn't over it, so keyboard users, and anyone who never hovers, read it whole. On a touch screen, a touch lights the spot under the finger, and the light comes back up when it lifts. With reduced motion the beam follows the pointer without gliding; the dimming still fades.

FAQ

How does the beam follow the pointer?

On each move over the text, the pointer's place is written into two CSS variables, --spotlight-text-x and --spotlight-text-y. They're registered as lengths, so a transition eases the beam after the pointer instead of jumping. Nothing re-renders, and nothing runs while the pointer is elsewhere.

Why isn't the text dim before the pointer comes?

So it always reads: someone on a phone, with a keyboard, or simply scrolling past sees the whole line. The dimming fades in only while the pointer is over the text, and back out when it leaves.

Does the beam fly in from the middle?

No. It lands where the pointer comes in, under the dimming as it fades in, and only glides once the pointer moves.

How do I size the beam?

With radius, in pixels, or --spotlight-text-radius in your stylesheet, in any unit: 2em by default, so it grows with the text. --spotlight-text-feather is how far the soft edge reaches past it, 1.5em.

What happens on a touch screen?

A touch lights the spot under the finger and dims the rest; when the finger lifts, or the page starts to scroll, the light comes back up everywhere.

What happens with reduced motion?

The beam follows the pointer without gliding after it, and the rest of the text still fades down and up, which isn't movement.

API Reference

SpotlightText

<span> data-slot="spotlight-text"

PropType
textstring

The text.

ambient?number

How much of the text outside the beam still shows while the beam is on it, from 0 (dark) to 1 (no dimming).

Default
0.15
edge?"soft" | "hard"

The beam's edge: feathered like a torch through fog, or a crisp disc like a stage light.

Type
"soft" | "hard"
Default
"soft"
radius?number

The beam's radius, in pixels. By default twice the text's size (2em), so it scales with the text.

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

Forwarded to the part.

CSS variableType
--spotlight-text-ambientstring

How much of the text outside the beam shows (0.15).

--spotlight-text-featherstring

The beam's soft edge, past its radius (1.5em).

--spotlight-text-radiusstring

The beam's radius (2em).

All 97 text effects