Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Text

Pro

Password Text for React

Text hidden behind dots, like a password field, that turns back into itself a character at a time. For React with Base UI, when a key, a code or a password should stay hidden until someone asks to see it.

Framework

Password Text shows a line as a row of dots, one per character, like a password field, with an eye button after it. Press the button and the dots turn into the characters one after another, each dot shrinking away as its character grows in; press it again and they're dots at once. It can also show the text only while the pointer is over it.

Use it for an API key, a recovery code or a Wi-Fi password on a settings page, or for a playful secret in a hero. To hide chosen words inside a sentence, use Redact Text; for text that decodes itself, Decrypted Text. It's monospaced by default, so the dots and the characters are the same width and nothing moves when it turns; each character's fade is a CSS transition, delayed by its place, with no animation library. With reduced motion the dots and characters swap at once.

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 { PasswordText } from "@/components/ui/password-text";
<PasswordText text="correct horse battery staple" />

Demos

Hover

trigger="hover" shows the text while the pointer is over it and hides it again when it leaves, with no button. It's a peek for the pointer alone: use the button wherever someone may need to read the text.

Preview width

Dot

dot is the character each hidden one shows as, • by default, and stagger the time between one character appearing and the next. Every character is hidden, spaces included, as in a password field.

Preview width

Accessibility

While the text is hidden, its characters aren't in the page at all: only the dots are, and screen readers hear "Hidden, 28 characters" (hiddenLabel), never the text. Once it's revealed they read the text, once, from a visually hidden copy; the dots and characters are hidden from them.

The eye is a real button, reached with Tab, named by toggleLabel ("Show"), with aria-pressed saying whether the text shows. Pressing it doesn't read the text out, since a password spoken aloud can be overheard: screen readers read it when they reach it.

Tab
Move focus to the eye button.
Enter
Show or hide the text.
Space
Show or hide the text.

FAQ

Is the hidden text in the page?

No. While it's hidden only the dots are rendered, so it can't be read from the page, selected or copied, and screen readers hear only its length. The characters are rendered when it's revealed and removed the moment it's hidden again.

Is it secure?

It hides the text from the screen and the page, not from the browser: the text still reaches the browser as a prop. For a real secret, fetch it when someone asks to see it, and pass it then.

How do I hold the state myself?

Pass revealed and onRevealedChange: the button and the pointer call it with the new state, and the text shows what revealed says. defaultRevealed starts it shown while it keeps its own state.

Why is it monospaced?

So every dot and every character is the same width, and nothing moves when it turns; it also tells apart look-alikes such as l, 1 and I. Each character takes at least one character's width, so in another font, such as font-sans, a wide letter grows its cell when it shows.

How do I translate it?

hiddenLabel is what screen readers hear while it's hidden, with {count} for the number of characters, and toggleLabel the button's name: hiddenLabel="Masqué, {count} caractères", toggleLabel="Afficher".

What happens with reduced motion?

The dots and characters swap at once, without the fade.

API Reference

PasswordText

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

PropType
revealed?boolean

Whether the text shows, to hold that state yourself.

defaultRevealed?boolean

Whether it starts revealed, when it keeps its own state. @default false.

Default
false
onRevealedChange?(revealed: boolean) → void

Called with the new state each time it's revealed or hidden.

Parameters

revealed – boolean

Returns
void
textstring

The text to hide.

dot?string

The character each hidden one shows as. @default "•".

Default
"•"
hiddenLabel?string

What screen readers hear while it's hidden; {count} is the number of characters. Ark default: Hidden, {count} characters.

Default
"Hidden
stagger?number

The time between one character appearing and the next, in milliseconds.

Default
30
toggleLabel?string

The toggle button's name for screen readers. @default "Show".

Default
"Show"
trigger?"click" | "hover"

What reveals it: a toggle button after the text, or the pointer over the text (hidden again when it leaves).

Type
"click" | "hover"
Default
"click"
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-state?string

"revealed" when shown is true, otherwise "hidden".

CSS variableType
--password-text-indexstring
--password-text-staggerstring

The time between one character appearing and the next (30ms).

All 97 text effects