<!-- Protocore Design System — MaskedValue -->
# MaskedValue

- **Category:** Data Display (`data-display`)
- **Slug:** `data-display/masked-value`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { MaskedValue } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/data-display/masked-value

> A sensitive value shown as bullets until an explicit reveal, with optional auto re-mask and copy.

## When to use it

**MaskedValue** is for secrets that must render in place but stay hidden by default — API keys, signing secrets, seed phrases, card numbers. The reveal is always an explicit, deliberate click, and `timeout` re-hides it automatically.

Use **CodeRef** for identifiers that are *not* secret (tx hashes, request ids) — those show their value immediately. When secrets appear inside a structured object, **JsonViewer** auto-masks sensitive keys for you, so prefer it over hand-masking each field.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `className` | `string` | no | — | — |
| `copyable` | `boolean` | no | `false` | Render a copy button that copies the clear value. |
| `label` | `string` | no | `value` | What this is, for the reveal button's aria-label (e.g. "API key"). |
| `masked` | `string` | no | `••••••••` | Masked display form. Defaults to a fixed run of bullets (leaks no length). |
| `style` | `CSSProperties` | no | — | — |
| `timeout` | `number` | no | — | Auto re-mask this many ms after a reveal. Omit to stay revealed. |
| `value` | `string` | yes | — | The sensitive clear value — only rendered after an explicit reveal. |

## Examples

### Basics

Pass the clear `value` and a `label`. The value stays masked as a fixed run of bullets (leaking no length) until the eye button is clicked. The `label` names the value in the reveal button's `aria-label`.

```tsx
import { MaskedValue } from "@protocore/pds";

export default function MaskedValueBasics() {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 12, alignItems: "flex-start" }}>
      <MaskedValue label="API key" value="pk_live_51H8xQ2mVn7Lp0Rs9aF3kQ2m" />
      <MaskedValue label="signing seed" value="tornado clever ridge basin lunar" />
    </div>
  );
}
```

### Copy & auto re-mask

Set `copyable` for a copy button that writes the clear value, and `timeout` (ms) to auto re-mask a reveal after a delay — so a shoulder-surfed secret doesn't linger on screen.

```tsx
import { MaskedValue } from "@protocore/pds";

export default function MaskedValueCopyable() {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 12, alignItems: "flex-start" }}>
      <MaskedValue
        label="secret key"
        value="sk_live_9aF3kQ2mVn7Lp0Rs51H8xQ2m"
        copyable
        timeout={4000}
      />
      <MaskedValue label="webhook secret" value="whsec_2mVn7Lp0Rs9aF3kQ" copyable timeout={4000} />
    </div>
  );
}
```

## Usage

**Do**

- Use it for anything that shouldn't sit in plaintext on screen — keys, secrets, seeds.
- Set a `timeout` so reveals re-mask themselves after a few seconds.
- Give a precise `label` — it becomes the reveal/copy button's accessible name.
- Use the default bullet mask when the value's length is itself sensitive.

**Don't**

- Don't use it as decoration for non-secret ids — that's CodeRef.
- Don't leak the full length via a custom `masked` unless that's intended.
- Don't assume masking is a security boundary — the value is still in the DOM once revealed.
- Don't hand-mask fields inside a JSON blob; let JsonViewer's key patterns do it.

## Accessibility

**Keyboard**

| Keys | Action |
| --- | --- |
| `Tab` | Moves focus between the reveal button and (when present) the copy button. |
| `Enter / Space` | Toggles reveal, or copies the clear value. |

**Notes**

- The reveal button exposes `aria-pressed` reflecting the shown/hidden state, and its label swaps between `Reveal <label>` and `Hide <label>`.
- The copy button is labelled `Copy <label>`.
- Icons are inline decorative SVG (`aria-hidden`); the accessible name comes entirely from the labels.

## Related

`code-ref`, `json-viewer`, `tag`, `relative-time`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
