SensitiveInput
A masked field for API keys and other secrets.
Usage
Basic
A valid, a rejected, and a read-only key.
Loading demo...
Best Practices
- Use it for stored secrets the user may read back; use
TxInput type="password"for a credential being entered and never re-read. - Add
readonlyto a key the host issued and the user can't edit; it stays revealable and copyable, and focus stays on the container. - Steer people to copy rather than reveal-and-select; listen to
revealwhere a credential surface needs an audit trail. - Pass
errorrather thanstatus="error"so the state and the message can't drift apart. - Localize through
labels: seven of its ten strings are only heard by screen readers.
API Reference
Props
| Name | Type | Default | Description |
|---|---|---|---|
modelValue | string | '' | The secret (controlled). |
label | string | '' | Field label; also the masked container's accessible name. |
placeholder | string | '' | Native placeholder, visible only while empty. |
size | 'xs' | 'sm' | 'md' | 'lg' | 'md' | Height, padding, radius, and icon size; md matches TxInput. |
status | 'default' | 'error' | — | Explicit visual state; derived from error when unset. |
description | string | '' | Helper text below the field; replaced by error. |
error | string | '' | Validation message; when set, turns the field red and sets aria-invalid. |
disabled | boolean | false | No reveal, no copy, no edit. |
readonly | boolean | false | Blocks editing but not revealing or copying. |
required | boolean | false | Marks the label required. |
copyable | boolean | true | Renders the copy tab. |
mask | string | '••••••••' | Glyphs drawn in place of the value; fixed, so the secret's length doesn't leak. |
copiedDuration | number | 2000 | How long the copy tab stays confirmed, in ms. |
labels | Partial<SensitiveInputLabels> | — | Overrides every rendered string, merged over SENSITIVE_INPUT_DEFAULT_LABELS. |
Events
| Event | Payload | Description |
|---|---|---|
update:modelValue | (value: string) | Fires when the value changes. |
copy | (value: string) | Fires after the value reaches the clipboard. |
copyError | (error: unknown) | Fires when the clipboard refuses the write. |
reveal | — | Fires when the value becomes visible; worth auditing for credentials. |
mask | — | Fires when the value goes back behind the mask. |
Exposed Methods
| Method | Description |
|---|---|
focus() | Focuses the container while masked, otherwise the input. |
blur() | Blurs the input. |
reveal() | Reveals the value programmatically. |
mask() | Re-masks the value. |
copy() | Runs the copy path; returns a promise. |
Three States
| State | Behavior |
|---|---|
| Masked | The default whenever there is a value. Shows the mask glyphs; the container becomes a role="button" that reveals on click, Enter, or Space. On hover or focus, the glyphs change to Click to reveal. |
| Revealed | type flips to text and focus moves into the input. Blur or Escape re-masks, and Escape returns focus to the container; focusing the eye or copy button is not a blur. |
| Empty | A plain input with no mask, no copy tab, and no role="button". The first typed character switches to revealed; a value arriving from outside lands masked. |
Overview
- Copying never reveals the value.
- The masked container is a
role="button"(it holds buttons, so it can't be a<button>) with its owntabindex,aria-label(<label>, masked.), andaria-describedby; while masked, the<input>isaria-hiddenwithtabindex="-1". - A
role="status" aria-live="polite"region announcesValue hiddenandCopied to clipboard. - Clicking the
<label>reveals instead of forwarding focus. autocomplete="off"anddata-1p-ignore/data-lpignorekeep password-manager overlays off the field.- The only transition, the copy tab's opacity, is off under reduced motion.
Technologies
- Copy tries
navigator.clipboard.writeTextfirst, then falls back to a hidden-textareaexecCommandand removes that node in afinally, so a failed copy never leaves the secret in the DOM. - Source:
packages/tuffex/packages/components/src/sensitive-input/. - Behavior modelled on Kumo's SensitiveInput.
查看源码
packages/tuffex/packages/components/src/sensitive-input/index.ts