Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Text

Pro

Stamp Text for React

Text pressed onto the page like a rubber stamp, each letter landing with a snap and a slight lean. For React with Base UI, when a word should feel printed by hand.

Framework

Stamp Text presses a line onto the page a letter at a time: each letter lands from a little above and larger, snaps to its size with a flash of ink, and stays leaning a few degrees, as if stamped by hand. It plays once, as soon as the page shows it, or when it scrolls into view.

Use it for a status such as "Approved" or "Shipped", a badge, a product mark or a short heading with a handmade feel. For a bouncier, cartoon landing with a burst, use Pop Text; for letters that slide in smoothly, Splitting Text. The landing is a CSS keyframe animation the install adds to your stylesheet, and each letter's lean is a sin() of its place in the text, so it looks random but is the same on every render, with no animation library. With reduced motion the text is simply there, still leaning.

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 { StampText } from "@/components/ui/stamp-text";
<h2>
  <StampText text="Signed and sealed" />
</h2>

Demos

Tilt

tilt is the most a letter leans either way, 4 degrees by default: 0 keeps every letter upright, and 10 gives a hurried, ransom-note look.

Preview width

Words

by="words" stamps whole words, 220 ms apart, each with its own lean; inside a bordered label it reads as a rubber stamp. Use it too for scripts whose letters join, such as Arabic, which a split between letters would break.

Preview width

Accessibility

Screen readers read the whole text once, as plain text: the stamped letters are hidden from them, and a visually hidden copy carries it. Words wrap whole, and the line keeps its direction on a right-to-left page. Each letter's ink dips once as it lands, never a repeated flash. With reduced motion every letter is in place from the start.

FAQ

Are the angles random?

They look random but aren't: each letter leans by the sine of its place in the text times tilt, worked out in CSS, so the server and the browser draw the same angles and every render agrees.

Can it wait until it's scrolled into view?

Yes: trigger="view" starts it once a quarter of the text is in view. By default it plays as soon as the page shows it, from CSS alone, before the page's script loads: a stamp is usually where the eye already is.

How do I make it stamp faster or slower?

duration is how long one stamp takes to land, 450 ms by default, and stagger the time between one stamp and the next, 80 ms for letters and 220 for words. A short stagger lands the letters almost together; a long one, one by one.

Does the lean stay once it has landed?

Yes, it's the look: the letters stay tilted, as a real stamp leaves them, and keep their place in the line, since the lean doesn't change the layout. Pass tilt={0} for upright letters.

How do I run something after it finishes?

Pass onComplete: it's called once, when the last letter or word has landed.

What happens with reduced motion?

Nothing lands or flashes: the text is there from the start, fully readable, with each letter at its lean.

API Reference

StampText

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

PropType
textstring

The text.

by?"characters" | "words"

What's stamped on its own: each character, or each word (for scripts whose letters join, such as Arabic).

Type
"characters" | "words"
Default
"characters"
duration?number

How long one stamp takes to land, in milliseconds. @default 450.

onComplete?() → void

Called once the last character or word has landed.

Returns
void
stagger?number

The time between one stamp and the next, in milliseconds.

Default
80 (characters), 220 (words)
tilt?number

The most a character or word leans once stamped, either way, in degrees; 0 keeps them upright.

Default
4
trigger?"mount" | "view"

When it plays: as soon as it's on the page, or once it scrolls into view.

Type
"mount" | "view"
Default
"mount"
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.

AttributeType
data-last?string
data-view?string

"in" when visible is true, otherwise "out".

CSS variableType
--stamp-text-durationstring

One stamp's landing.

--stamp-text-tiltstring

The most a unit leans, either way (4deg).

All 97 text effects