shadcn.io is not affiliated with official shadcn/ui
Paint Text lets the pointer paint a headline. Every letter the brush passes takes the paint colour at once and keeps it for a moment after the brush moves on, so a stroke leaves a trail of colour through the words that fades back, letter by letter, to the text's own colour.
Use it for a hero line, a playful heading or a call to action that rewards a sweep of the pointer. For a weight that follows the pointer, use Variable Proximity; for a highlighter mark that draws itself, Highlight Text. The letters' centres are measured once as the pointer enters; each move marks the letters inside the brush with a data attribute, and CSS does the rest: a quick colour transition paints them and, once a letter is unmarked, a delayed one fades it back. There's no animation frame loop, and nothing re-renders as the pointer moves.
Installation
Usage
import { PaintText } from "@/components/ui/paint-text";<h1>
<PaintText text="Run the pointer through the words" />
</h1>Demos
Colours
paintColor is the paint, any CSS colour, including your theme's variables such as var(--destructive). By default it's the theme's --chart-2.
Brush
radius is the brush's size: letters whose centre is that close to the pointer, in pixels, take the paint. resetDelay is how long the paint stays on a letter before it fades, in milliseconds.
Accessibility
Screen readers read the text once, from a visually hidden copy, never letter by letter. At rest the text is in its own colour, fully readable; choose a paintColor that also contrasts with the page, since painted letters are read too. The colour carries no meaning, so keyboard and touch users miss nothing; inside a link with keyboard focus the whole text shows painted. A colour fade isn't motion, so reduced motion keeps it.
FAQ
How long does the paint stay?
resetDelay after the brush leaves a letter, 1,200 ms by default, then it fades over --paint-text-fade, 900 ms. Pass a long resetDelay, a minute say, for paint that stays while the reader looks around.
How big is the brush?
radius sets it, 48 pixels by default: every letter whose centre is that close to the pointer takes the paint. A larger brush paints whole words at once; a smaller one, letter by letter.
Why --chart-2 by default?
--chart-2 by default?The paint has to stand apart from the text in light and dark mode, and many themes' primary colour is the text colour itself. Every shadcn theme defines --chart-2 as a mid-tone. Pass any colour, such as var(--primary) when your primary is a colour.
Does it run on every frame?
No. It measures the letters once as the pointer comes over the text; each move then compares the pointer with every letter's centre and marks the ones under the brush. The colour change and the fade are CSS transitions. Nothing runs while the pointer is elsewhere.
API Reference
PaintText
<span> data-slot="paint-text"
textstring
The text.
paintColor?string
The paint's colour, any CSS colour. @default "var(--chart-2)".
radius?number
The brush's size: letters this close to the pointer take the paint, in pixels. @default 48.
- Default
48
resetDelay?number
How long the paint stays on a letter before it fades, in milliseconds. @default 1200.
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.
--paint-text-colorstring
The paint's colour (var(--chart-2)).
--paint-text-fadestring
How long the paint takes to fade (900ms).
--paint-text-holdstring
How long the paint stays before it fades (1200ms).
Related
- Pro
Erase Text
InteractiveLetters that fade under the pointer
- Pro
Outline Text
DecorativeHollow letters that flood with colour
- Pro
Every detail deserves the spotlightEvery detail deserves the spotlight
Spotlight Text
InteractiveLight that follows the pointer
- Pro
Text Hover Effect
InteractiveAn outline lit in a gradient
Highlight Text
DecorativeA highlighter band drawn across
- Pro
Annotation Text
DecorativeA pen stroke drawn round a word