{
 "id": "toast-undo",
 "name": "Toast with undo",
 "purpose": "A toast that confirms an archive and offers Undo, which puts the item back where it was. It stays until it's used or closed.",
 "use_when": [
  "for reversible actions such as archive, move or remove, instead of asking 'Are you sure?' first",
  "the action can be undone for a while",
  "the person should keep working without a dialog"
 ],
 "avoid_when": [
  "the action can't be undone (deleting for good, sending money): use confirm-dialog",
  "news about the whole page: use page-banners"
 ],
 "type": "states",
 "style": "quiet",
 "width": "medium",
 "tags": {
  "audience": "work",
  "industries": [
   "any"
  ],
  "keywords": [
   "toast",
   "undo",
   "snackbar",
   "archive",
   "confirmation"
  ]
 },
 "root": ".odl-toast-undo",
 "parts": [
  {
   "name": "messages",
   "selector": ".odl-toast-undo [data-od-list=\"messages\"]",
   "what": "the messages, one item each",
   "slot": "list"
  },
  {
   "name": "messages.from",
   "selector": ".odl-toast-undo [data-od-list=\"messages\"] [data-od-slot=\"from\"]",
   "what": "the from, as in “Quorbin Studio”",
   "slot": "text"
  },
  {
   "name": "messages.subject",
   "selector": ".odl-toast-undo [data-od-list=\"messages\"] [data-od-slot=\"subject\"]",
   "what": "the subject, as in “Revised quote for the spring catalogue”",
   "slot": "text"
  },
  {
   "name": "messages.archive",
   "selector": ".odl-toast-undo [data-od-list=\"messages\"] [data-od-action=\"archive\"]",
   "what": "the Archive action",
   "slot": "action"
  },
  {
   "name": "message",
   "selector": ".odl-toast-undo [data-od-slot=\"message\"]",
   "what": "one or two sentences: what it means and what to do next, as in “Archived”",
   "slot": "text"
  },
  {
   "name": "undo",
   "selector": ".odl-toast-undo [data-od-action=\"undo\"]",
   "what": "the Undo action",
   "slot": "action"
  },
  {
   "name": "close",
   "selector": ".odl-toast-undo [data-od-action=\"close\"]",
   "what": "the close action",
   "slot": "action"
  }
 ],
 "data": {
  "type": "object",
  "properties": {
   "messages": {
    "type": "array",
    "minItems": 1,
    "maxItems": 6,
    "items": {
     "type": "object",
     "properties": {
      "from": {
       "type": "string",
       "maxLength": 24,
       "part": "messages.from"
      },
      "subject": {
       "type": "string",
       "maxLength": 56,
       "part": "messages.subject"
      }
     },
     "required": [
      "from",
      "subject"
     ]
    },
    "part": "messages"
   },
   "message": {
    "type": "string",
    "maxLength": 24,
    "part": "message"
   }
  },
  "required": [
   "messages",
   "message"
  ]
 },
 "states": {
  "shown": [
   "archived",
   "restored",
   "closed",
   "hover",
   "focus"
  ],
  "edge": {
   "empty": {
    "status": "handled",
    "evidence": "data-od-list",
    "how": "the Smart UI renderer puts one plain 'Nothing to show yet.' line in an empty list"
   },
   "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 archive fails, put the row back and say so in the toast with Try again."
   },
   "disabled": {
    "status": "not_built",
    "how": "No control here is ever disabled; each one always does something."
   },
   "overflow": {
    "status": "handled",
    "how": "Long subjects and toast messages end in an ellipsis.",
    "evidence": "text-overflow: ellipsis"
   },
   "long_text": {
    "status": "handled",
    "how": "Titles balance and body text wraps at word boundaries inside a capped measure.",
    "evidence": "text-wrap"
   },
   "missing_image": {
    "status": "none",
    "how": "the part has no photo"
   }
  }
 },
 "tokens": [
  "--ds-border-width-default",
  "--ds-border-width-emphasis",
  "--ds-color-bg-action-primary",
  "--ds-color-bg-action-primary-hover",
  "--ds-color-bg-action-primary-pressed",
  "--ds-color-bg-inverse",
  "--ds-color-bg-neutral-subtle",
  "--ds-color-border-default",
  "--ds-color-border-focus",
  "--ds-color-border-separator",
  "--ds-color-border-subtle",
  "--ds-color-surface-raised",
  "--ds-color-text-inverse",
  "--ds-color-text-link",
  "--ds-color-text-on-action",
  "--ds-color-text-primary",
  "--ds-color-text-secondary",
  "--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-duration-toast",
  "--ds-motion-easing-standard",
  "--ds-motion-easing-toast",
  "--ds-opacity-disabled-container",
  "--ds-radius-container",
  "--ds-radius-control",
  "--ds-size-control-md",
  "--ds-size-icon-sm",
  "--ds-size-row-two-line",
  "--ds-size-target-min",
  "--ds-space-8",
  "--ds-space-inline-md",
  "--ds-space-inline-sm",
  "--ds-space-inset-lg",
  "--ds-space-inset-md",
  "--ds-space-inset-sm",
  "--ds-space-inset-xl",
  "--ds-space-inset-xs",
  "--ds-space-stack-lg",
  "--ds-space-stack-sm",
  "--ds-text-body-md",
  "--ds-text-body-sm",
  "--ds-text-label-lg"
 ],
 "a11y": {
  "summary": "A polite live region that is always on the page reads what was archived; after Archive, focus moves to Undo so keyboard users can reach it, and returns to the restored row or the list after Undo or close. Escape closes the toast. There is no timer, so nobody loses the chance to undo.",
  "roles": [
   "group",
   "list",
   "region",
   "status"
  ],
  "keyboard": [
   "Tab reaches each Archive button",
   "After Archive, focus moves to Undo; after Undo, it returns to the restored row"
  ],
  "controls": {
   "button": 5,
   "input": 0,
   "link": 0,
   "select": 0,
   "textarea": 0,
   "summary": 0
  },
  "focus_visible": true,
  "reduced_motion": true,
  "min_target": true
 },
 "files": {
  "html": "components/toast-undo/component.html",
  "bytes": 8808,
  "script": true
 },
 "source": null,
 "photos": 0,
 "urls": {
  "html": "https://opendesigner.dev/library/toast-undo.html",
  "json": "https://opendesigner.dev/library/toast-undo.json",
  "page": "https://opendesigner.dev/library/toast-undo/"
 },
 "get": {
  "curl": "curl -fsSLo toast-undo.html https://opendesigner.dev/library/toast-undo.html",
  "opendesigner": "python3 path/to/skills/opendesigner/scripts/library.py add toast-undo --from https://opendesigner.dev",
  "prompt": "Add the OpenDesigner component toast-undo to this project: https://opendesigner.dev/library/toast-undo.html. Keep its markup and states; map its --ds-* variables to my tokens."
 }
}
