Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Buttons

Pro

Spotlight Button for React

A button lit by a soft light that follows the pointer across it. For React with Base UI, when a call to action should respond to the pointer before it's pressed.

Framework
UI library

As the pointer moves over the button, a soft circle of light follows it, and the button's edge catches the light where it's closest. On keyboard focus the light sits in the middle. It fades out when the pointer leaves.

Use it on a hero call to action or a pricing card's button, where a quiet response to the pointer makes the button feel ready; for a button that moves toward the pointer instead, use the Magnetic Button. It wraps the Button, so variant and size work as usual. The light is the label's color by default, so it shows on every variant. Each pointer move writes where the pointer is into two CSS variables that place a radial mask, so nothing re-renders as it moves, and a CSS transition fades the light in and out. With reduced motion the light stays in the middle.

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 { SpotlightButton } from "@/components/ui/spotlight-button";
<SpotlightButton>Book a demo</SpotlightButton>

Demos

Intensity

intensity sets how bright the light is and how wide it spreads: subtle, medium (the default) or strong. A large button can carry a strong light; on a small one, subtle keeps the label clear.

Preview width

Color

spotlightColor colors the light and the edge it catches, any CSS color or a theme variable. By default they take the label's color. Here an outline and a ghost button are lit in var(--primary), so the light brings the brand color into a quiet button.

Preview width

Accessibility

The light is decoration and hidden from assistive tech: the button is announced and activated as any Button. On keyboard focus the light shows in the middle of the button, so people who tab through the page see the same cue as people with a pointer.

Enter
Activate the button.
Space
Activate the button.

FAQ

Is following the pointer expensive?

No. Each pointer move sets two CSS variables on the light; nothing re-renders and no animation runs. The browser only repaints the light.

How do I make the light brighter or dimmer?

Pass intensity: subtle, medium (the default) or strong. It sets both the strength and the size of the light, as in the Intensity demo.

How do I change the light's color?

Pass spotlightColor, any CSS color, such as var(--primary). By default it's the label's color, which shows on every variant, in light and dark mode.

Does anything happen on click?

No, the light stays where the pointer is, and the button presses as usual. For feedback on the press itself, use the Ripple Button.

Where is the light for keyboard users?

In the middle of the button. A keyboard focus has no pointer, so it puts the light back in the center, where it stays until the pointer moves over the button again.

What happens with reduced motion?

The light still shows on hover and focus, but it stays in the middle of the button instead of following the pointer.

API Reference

SpotlightButton

data-slot="spotlight-button-light"

PropType
children?ReactNode

The label, above the light.

focusableWhenDisabled?boolean

Whether the button should be focusable when disabled.

Default
false
intensity?"subtle" | "medium" | "strong"

How bright the light is and how far it spreads.

Type
"subtle" | "medium" | "strong"
Default
"medium"
nativeButton?boolean

Whether the component renders a native <button> element when replacing it via the render prop. Set to false if the rendered element is not a button (for example, <div>).

Default
true
spotlightColor?string

The light's color and the edge it catches, any CSS color. By default the label's color, so it shows on every variant.

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
--spotlight-button-colorstring

The light's color (the label's by default).

--spotlight-button-opacitystring
--spotlight-button-rimstring
--spotlight-button-xstring

Where the light is, from the left (50%).

--spotlight-button-ystring

Where the light is, from the top (50%).

All 35 buttons