{
  "example": "import { CredentialReveal } from \"@godxjp/ui/data-display\";\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from \"@godxjp/ui/feedback\";\n\n<Dialog open={open} onOpenChange={setOpen}>\n  <DialogContent>\n    <DialogHeader>\n      <DialogTitle>APIキーを発行しました</DialogTitle>\n    </DialogHeader>\n    <CredentialReveal\n      label=\"APIキー\"\n      secret=\"gxp_live_8Fh2kQ9wR7nZ1xV4bT6mL0cD\"\n      downloadable\n      onAcknowledge={() => setOpen(false)}\n    />\n  </DialogContent>\n</Dialog>",
  "group": "data-display",
  "importPath": "@godxjp/ui/data-display",
  "name": "CredentialReveal",
  "props": [
    {
      "description": "The one-time secret value.",
      "name": "secret",
      "required": true,
      "type": "string"
    },
    {
      "description": "Accessible name / caption for the secret (e.g. 'API key').",
      "name": "label",
      "type": "string"
    },
    {
      "description": "Caution banner copy; defaults to a localized 'shown only once' warning. Pass null to suppress the banner.",
      "name": "warning",
      "type": "React.ReactNode | null"
    },
    {
      "description": "Controlled reveal state (with defaultRevealed / onRevealedChange).",
      "name": "revealed",
      "type": "boolean"
    },
    {
      "defaultValue": "false",
      "description": "Uncontrolled initial reveal state.",
      "name": "defaultRevealed",
      "type": "boolean"
    },
    {
      "description": "Reveal toggle handler.",
      "name": "onRevealedChange",
      "type": "(revealed: boolean) => void"
    },
    {
      "description": "Called after the secret is written to the clipboard.",
      "name": "onCopy",
      "type": "(secret: string) => void"
    },
    {
      "description": "Renders a confirm button; wire it to the Dialog's onOpenChange(false).",
      "name": "onAcknowledge",
      "type": "() => void"
    },
    {
      "description": "Copy on the button `onAcknowledge` creates. Defaults to a localized \"I've saved it\" — override it when the confirmation claims something more specific than having read the secret (\"保管しました\", \"Stored in 1Password\"). Consumer-owned wording: route it through t().",
      "name": "acknowledgeLabel",
      "type": "React.ReactNode"
    },
    {
      "defaultValue": "false",
      "description": "Offer a download-as-file button.",
      "name": "downloadable",
      "type": "boolean"
    },
    {
      "defaultValue": "\"credential.txt\"",
      "description": "Name of the file `downloadable` writes. The default is deliberately anonymous; set it when the user will hold several at once (`api-key-prod.txt`) so the saved files are still telling apart in a downloads folder.",
      "name": "downloadFileName",
      "type": "string"
    },
    {
      "defaultValue": "\"md\"",
      "description": "Action button size tier.",
      "name": "size",
      "type": "\"xs\" | \"sm\" | \"md\" | \"lg\""
    },
    {
      "defaultValue": "\"warning\"",
      "description": "Caution banner severity.",
      "name": "tone",
      "type": "\"warning\" | \"destructive\" | \"info\""
    },
    {
      "description": "DOM id on the root. Useful here because the surface is usually inside a Dialog: it is what a `aria-describedby` on the dialog, or a deep link back to the issued credential, can point at.",
      "name": "id",
      "type": "string"
    },
    {
      "description": "Accessible name for the credential region when `label` is not set or is a non-string node. `label` is the VISIBLE caption and already names the region when it is a plain string, so reach for this only when the caption is rich content or when the surrounding dialog title is the only thing saying which secret this is.",
      "name": "aria-label",
      "type": "string"
    }
  ],
  "related": [
    "PasswordInput — editable password/secret ENTRY with a show/hide toggle (data-entry); CredentialReveal is read-only DISPLAY of an issued secret.",
    "Dialog — the modal CredentialReveal is designed to live inside.",
    "Alert — the caution banner CredentialReveal composes internally."
  ],
  "rules": [
    3,
    6,
    23
  ],
  "storyPath": "data-display/credential-reveal.tsx",
  "tagline": "One-time secret surface — masked-by-default value with a show/hide toggle, a copy button that confirms the copy, optional download, and an optional acknowledge action to pair with Dialog. The GitHub/Stripe token-reveal pattern as a real primitive so consumers stop hand-rolling it.",
  "usage": [
    "DO use for a secret shown exactly once after creation (device credential, API key, service-account secret) — it masks by default and confirms the copy.",
    "DO pair it inside a Dialog and reset via controlled `revealed`/`onRevealedChange` (or let it re-blur automatically when the `secret` prop changes) so a reopened dialog starts masked.",
    "DO pass `onAcknowledge` to gate the dialog close behind an explicit 'I've saved it' confirmation.",
    "DON'T use it for an editable password field — that's PasswordInput. CredentialReveal is read-only display of an issued secret.",
    "DON'T hand-roll the copy button + copied-state + aria-live announcement; it's built in."
  ],
  "useCases": [
    "Device credential issued after enrollment",
    "API key / personal access token shown once on creation",
    "Service-account secret / client secret reveal",
    "Recovery code or one-time bootstrap password"
  ]
}
