Overview
Masked display for API keys, tokens, and webhook secrets with accessible copy action.
Overview
SecretValueField renders a secret credential in masked form by default, with a one-click copy action and an optional reveal toggle. It is designed for settings pages and API key management screens where you need to:
- Show a newly-created secret exactly once (use
initiallyRevealed). - Display an existing key masked, with only safe metadata (prefix/suffix) visible.
- Let users copy the value without it appearing in accessible labels, titles, or data attributes.
Security contract: The value prop is never written to any passive attribute. The copy announcement says only "Copied" and never contains the value. Reveal is opt-in and off by default.
Usage
Accessibility
SecretValueField keeps the secret out of all accessible attributes. See secret-value-field.a11y.md for the full accessibility contract.
- The value display has an
aria-labelthat names the field and its state ("masked" or "revealed") without including the value itself. - Copy success is announced by a
role="status" aria-live="polite"region witharia-atomic="true". The announcement says "Copied" (or your customcopiedLabel), never the value. - The reveal toggle uses
aria-pressedto communicate its state, and itsaria-labelflips between "Reveal {label}" and "Hide {label}". - Prefix and suffix elements carry
aria-hidden="true"to prevent double-reading; the value region'saria-labelalready describes the field. - The row of controls is wrapped in
role="group"labelled viaaria-labelledbypointing to the field label.
When to use
- Showing a newly-created API key or token that the user must copy before it is gone.
- Displaying an existing masked key in a settings table where the full value should stay hidden.
- The value is not sensitive and can be shown as plain text — use a code or input component.
- You need inline editing of the secret value — use a password input instead.
Examples
Masked API key
Default masked display for an existing API key. The secret value is never rendered in attributes.
Newly-created secret
One-time reveal for a newly-created API key. The value is shown on first render with a warning to copy it now.
Multiple keys in a settings list
Multiple masked keys with prefix/suffix metadata, as they would appear in a settings table.
With reveal toggle
Optional reveal/hide toggle for settings pages where the consumer explicitly enables it.
Props
| Name | Type | Default | Required | Bindable | Description |
|---|---|---|---|---|---|
value | text | req | The secret value to copy. Never rendered in attributes or visible text post-copy. Required. | ||
prefix | text | Visible prefix shown before the masked region (e.g. example_live_). Does not contain the secret. | |||
suffix | text | Visible suffix shown after the masked region (e.g. last 4 chars "a3f9"). Does not contain the secret. | |||
label | text | 'Secret value' | Accessible label for the field and copy button region. Defaults to "Secret value". | ||
revealAllowed | boolean | false | When true, allows the user to reveal/hide the full secret. Opt-in; false by default for security. | ||
initiallyRevealed | boolean | false | Shows the full unmasked value on initial render. This is an explicit
one-time reveal for the "secret was just created, copy it now" flow and is
INDEPENDENT of revealAllowed: it does not add a reveal/hide toggle, it just
starts unmasked. Only set this when the surrounding UI makes the one-time
exposure intentional (e.g. a "copy your new key" panel). | ||
confirmDuration | number | 1500 | Duration in milliseconds to show the copy confirmation state. Default 1500. | ||
copiedLabel | text | 'Copied' | Accessible label announced after a successful copy. Defaults to "Copied". | ||
warning | snippet | Optional advisory content rendered below the field (e.g. "Copy this now; it will not be shown again"). |