---
title: Secret Reveal
description: A credential shown once: it wraps rather than scrolls, one click selects all of it, and the copy button sits under it rather than over it.
source: https://adamjurek.com/components/secret-reveal
---

## Home


A token, a one-time link or a recovery code, at the single moment it is
visible. Reach for it wherever something is shown that cannot be shown again -
after minting an API key, after generating an invitation, after resetting a
password - and where the cost of the reader copying nine tenths of it is a
support conversation.

<!-- ::start:showcase demo="secret-reveal" height="380" -->
<!-- ::end:showcase -->

## Why it is built this way

This was written out five times before it became a component, and the five
copies were not identical - which is the actual cost. One of them scrolled
horizontally and one wrapped, so one of them showed a token with its tail off
the right-hand edge.

So it wraps, always. A document that scrolls loses nothing, because the reader
scrolls it. A credential whose end is out of view looks complete and is not.

The second decision is `user-select: all`, which makes one click take the whole
value. The clipboard API only exists in a secure context, so on a laptop over
plain `http` the copy button silently never confirms - selecting by hand is the
path that always works, and this makes it a single gesture rather than a
careful drag.

## What it does not do

It does not know the value is secret. Nothing is redacted, obscured or omitted
from the DOM; this is a presentation component, and keeping a credential out of
logs and out of a second render is the caller's job.

> [!NOTE] Install commands are not written here
> Anything in `packages/ui/registry.ts` gets its TanStack, shadcn and pnpm
> commands appended to the bottom of this tab, along with its version,
> dependencies and files. Do not add your own - the generated ones cannot go
> stale, and a second copy immediately does.


## Install

<!-- ::start:tabs -->

### TanStack

```shell
tanstack add https://adamjurek.com/r/tanstack/secret-reveal.json
```

### shadcn

```shell
pnpm dlx shadcn@latest add https://adamjurek.com/r/shadcn/secret-reveal.json
```

### pnpm

```shell
pnpm add @sushindustries/ui @sushindustries/atoms
```

<!-- ::end:tabs -->

## What you get

| | |
| --- | --- |
| Version | 0.1.0 |
| Category | content · Rendering |
| Files | `secret-reveal.tsx` |
| Dependencies | None |
| Also installs | `copy-button` |
| Tags | clipboard, no-deps |

> [!NOTE] No runtime dependencies
> It brings nothing with it beyond the stylesheet.

## Guides


## Composing it

It does not confirm that the secret was stored, and it does not dismiss itself.
Whether there is a "Done" button, and what pressing it costs, belongs to the
page - so it takes `children` and puts them in the action row beside the copy
button.

```tsx
<SecretReveal value={token} label="Copy the token">
	<Button variant="ghost" onClick={dismiss}>
		I have stored it
	</Button>
</SecretReveal>
```

## When not to use it

**Do not reach for it to mask a value behind a reveal toggle.** A masked secret
with a show button is a pattern from password fields, where the point is
shoulder surfing on a value the user already knows. This is for a value the
user is seeing for the first and only time, and hiding it adds a click before
the one thing they came to do.

**Do not use it for a snippet that merely contains a credential.** A
registration command with a truncated prefix in it is an illustration, and a
copy button on an illustration hands somebody a command that does not work.
Pass `copy={false}`:

```tsx
<SecretReveal
	copy={false}
	value={`claude mcp add --transport http example \\\n  --header "Authorization: Bearer ${prefix}…"`}
/>
```

## If the copy button never confirms

It needs a secure context. `navigator.clipboard` does not exist over plain
`http`, so on a laptop the button will look like it did nothing - which is also
the truthful rendering of what happened.

That is the reason the value carries `user-select: all`: one click selects the
whole thing, and selecting by hand is the path that works everywhere. If you
are testing copy behaviour, test it over `https` or on `localhost`, which
browsers treat as secure.
