{
 "id": "approval-prompt",
 "name": "Approval prompt",
 "purpose": "Asks the person before something that changes data happens: what will happen, the details that matter, a warning when it cannot be undone, and Cancel or the action itself.",
 "use_when": [
  "just before an action that sends, pays, books or deletes, so the person confirms it first",
  "an assistant is about to do something that changes data (send, pay, book, delete) and the person must say yes first"
 ],
 "avoid_when": [
  "the action already happened: use receipt",
  "the person still has to fill in values: use form-fields",
  "a bill or request that goes through several approvers: use approval-panel"
 ],
 "type": "overlay",
 "style": "quiet",
 "width": "narrow",
 "tags": {
  "audience": "work",
  "industries": [
   "any"
  ],
  "keywords": [
   "confirm",
   "approval",
   "dialog",
   "warning",
   "destructive action"
  ]
 },
 "root": ".odl-approval-prompt",
 "parts": [
  {
   "name": "title",
   "selector": ".odl-approval-prompt h3",
   "what": "what will happen, as a question",
   "slot": "text"
  },
  {
   "name": "summary",
   "selector": ".odl-summary",
   "what": "one line on what confirming does",
   "slot": "text"
  },
  {
   "name": "details",
   "selector": ".odl-approval-prompt dl > div",
   "what": "one fact about the action: who, what, how much, when",
   "slot": "list"
  },
  {
   "name": "warning",
   "selector": ".odl-warning",
   "what": "an optional caution, for actions that cannot be undone",
   "slot": "text"
  },
  {
   "name": "cancel",
   "selector": ".odl-cancel",
   "what": "the quiet way out, first in tab order",
   "slot": "action"
  },
  {
   "name": "approve",
   "selector": ".odl-approve",
   "what": "the primary button that does the action",
   "slot": "action"
  }
 ],
 "data": {
  "type": "object",
  "required": [
   "title",
   "approve",
   "cancel"
  ],
  "properties": {
   "title": {
    "type": "string",
    "maxLength": 60,
    "part": "title"
   },
   "summary": {
    "type": "string",
    "maxLength": 140,
    "part": "summary"
   },
   "details": {
    "type": "array",
    "minItems": 0,
    "maxItems": 6,
    "part": "details",
    "items": {
     "type": "object",
     "required": [
      "label",
      "value"
     ],
     "properties": {
      "label": {
       "type": "string",
       "maxLength": 24
      },
      "value": {
       "type": "string",
       "maxLength": 80
      }
     }
    }
   },
   "warning": {
    "type": "string",
    "maxLength": 140,
    "part": "warning"
   },
   "approve": {
    "type": "object",
    "part": "approve",
    "properties": {
     "label": {
      "type": "string",
      "maxLength": 40
     },
     "event": {
      "type": "object"
     }
    },
    "required": [
     "label",
     "event"
    ]
   },
   "cancel": {
    "type": "object",
    "part": "cancel",
    "properties": {
     "label": {
      "type": "string",
      "maxLength": 40
     },
     "event": {
      "type": "object"
     }
    },
    "required": [
     "label",
     "event"
    ]
   }
  }
 },
 "states": {
  "shown": [
   "with warning",
   "without details",
   "hover",
   "focus",
   "disabled"
  ],
  "edge": {
   "empty": {
    "status": "handled",
    "how": "with no details the details box is hidden, so only the question and the buttons show",
    "evidence": "dl:not(:has(dt:not(:empty))) { display: none; }"
   },
   "loading": {
    "status": "handled",
    "evidence": "data-od-slot",
    "how": "the Smart UI renderer draws each marked slot as a quiet block of its size while the data arrives; the static file shows the filled part"
   },
   "error": {
    "status": "not_built",
    "how": "if the action fails after confirming, replace the prompt with error-retry"
   },
   "disabled": {
    "status": "shown",
    "how": "a disabled or still-loading button turns quiet neutral (secondary text on a subtle fill), still readable at AA",
    "evidence": "button:disabled { cursor: not-allowed;"
   },
   "overflow": {
    "status": "handled",
    "how": "at most six details; on a phone each detail stacks label over value and the buttons share the row",
    "evidence": "@container (max-width: 26rem)"
   },
   "long_text": {
    "status": "handled",
    "how": "titles, values and button labels wrap, also long addresses with no spaces",
    "evidence": "overflow-wrap: anywhere"
   },
   "missing_image": {
    "status": "none",
    "how": "the part has no photo"
   }
  }
 },
 "tokens": [
  "--ds-border-width-default",
  "--ds-color-bg-action-primary",
  "--ds-color-bg-action-primary-hover",
  "--ds-color-bg-action-primary-pressed",
  "--ds-color-bg-neutral-subtle",
  "--ds-color-bg-warning-subtle",
  "--ds-color-border-default",
  "--ds-color-border-focus",
  "--ds-color-border-subtle",
  "--ds-color-icon-default",
  "--ds-color-surface-raised",
  "--ds-color-surface-sunken",
  "--ds-color-text-on-action",
  "--ds-color-text-primary",
  "--ds-color-text-secondary",
  "--ds-color-text-warning",
  "--ds-elevation-floating",
  "--ds-focus-ring-offset",
  "--ds-focus-ring-width",
  "--ds-font-weight-label",
  "--ds-icon-stroke-md",
  "--ds-motion-duration-short",
  "--ds-motion-easing-standard",
  "--ds-radius-container",
  "--ds-radius-control",
  "--ds-radius-nested",
  "--ds-size-control-lg",
  "--ds-size-control-md",
  "--ds-size-icon-md",
  "--ds-size-icon-sm",
  "--ds-size-target-min",
  "--ds-space-2",
  "--ds-space-inline-md",
  "--ds-space-inline-sm",
  "--ds-space-inset-lg",
  "--ds-space-inset-md",
  "--ds-space-inset-xl",
  "--ds-space-inset-xs",
  "--ds-space-stack-lg",
  "--ds-space-stack-sm",
  "--ds-space-stack-xs",
  "--ds-text-body-md",
  "--ds-text-label-lg",
  "--ds-text-title-md"
 ],
 "a11y": {
  "summary": "A labelled section whose heading says what will happen; the details are a description list, and Cancel comes first in tab order so a stray Enter does not confirm.",
  "roles": [
   "region"
  ],
  "keyboard": [
   "Tab reaches Cancel first, then the action",
   "Enter or Space presses the focused button",
   "Escape cancels when the renderer shows it"
  ],
  "controls": {
   "button": 2,
   "input": 0,
   "link": 0,
   "select": 0,
   "textarea": 0,
   "summary": 0
  },
  "focus_visible": true,
  "reduced_motion": true,
  "min_target": true
 },
 "files": {
  "html": "components/approval-prompt/component.html",
  "bytes": 7671,
  "script": false
 },
 "source": null,
 "photos": 0,
 "urls": {
  "html": "https://opendesigner.dev/library/approval-prompt.html",
  "json": "https://opendesigner.dev/library/approval-prompt.json",
  "page": "https://opendesigner.dev/library/approval-prompt/"
 },
 "get": {
  "curl": "curl -fsSLo approval-prompt.html https://opendesigner.dev/library/approval-prompt.html",
  "opendesigner": "python3 path/to/skills/opendesigner/scripts/library.py add approval-prompt --from https://opendesigner.dev",
  "prompt": "Add the OpenDesigner component approval-prompt to this project: https://opendesigner.dev/library/approval-prompt.html. Keep its markup and states; map its --ds-* variables to my tokens."
 }
}
