{
 "id": "error-retry",
 "name": "Error with retry",
 "purpose": "Says in plain words what failed and that nothing else broke, with an optional error code, a Try again button and one other way forward.",
 "use_when": [
  "when a load, search or action failed and trying again may work",
  "something the person asked for failed (a load, a search, a payment that did not start) and trying again may work"
 ],
 "avoid_when": [
  "the action went through, or was refused for a known reason: use receipt with the danger tone",
  "a list loaded and is simply empty: use empty-state",
  "a warning about something that has not failed yet: use approval-prompt"
 ],
 "type": "feedback",
 "style": "quiet",
 "width": "medium",
 "tags": {
  "audience": "work",
  "industries": [
   "any"
  ],
  "keywords": [
   "error",
   "retry",
   "failed",
   "try again",
   "offline"
  ]
 },
 "root": ".odl-error-retry",
 "parts": [
  {
   "name": "title",
   "selector": ".odl-error-retry h3",
   "what": "what failed, in a few words",
   "slot": "text"
  },
  {
   "name": "message",
   "selector": ".odl-message",
   "what": "what happened in plain words and what was not affected",
   "slot": "text"
  },
  {
   "name": "detail",
   "selector": ".odl-detail",
   "what": "an optional error code or reference for support",
   "slot": "text"
  },
  {
   "name": "retry",
   "selector": ".odl-retry",
   "what": "the primary Try again button",
   "slot": "action"
  },
  {
   "name": "secondary",
   "selector": ".odl-other",
   "what": "an optional other way forward",
   "slot": "action"
  }
 ],
 "data": {
  "type": "object",
  "required": [
   "title",
   "message",
   "retry"
  ],
  "properties": {
   "title": {
    "type": "string",
    "maxLength": 60,
    "part": "title"
   },
   "message": {
    "type": "string",
    "maxLength": 200,
    "part": "message"
   },
   "detail": {
    "type": "string",
    "maxLength": 60,
    "part": "detail"
   },
   "retry": {
    "type": "object",
    "part": "retry",
    "properties": {
     "label": {
      "type": "string",
      "maxLength": 40
     },
     "event": {
      "type": "object"
     }
    },
    "required": [
     "label",
     "event"
    ]
   },
   "secondary": {
    "type": "object",
    "part": "secondary",
    "properties": {
     "label": {
      "type": "string",
      "maxLength": 40
     },
     "event": {
      "type": "object"
     }
    },
    "required": [
     "label",
     "event"
    ]
   }
  }
 },
 "states": {
  "shown": [
   "with error code",
   "hover",
   "focus",
   "disabled while retrying"
  ],
  "edge": {
   "empty": {
    "status": "not_built",
    "how": "an error always says what failed; there is no empty version"
   },
   "loading": {
    "status": "shown",
    "how": "while a retry runs the button is disabled and quiet, so it cannot be pressed twice",
    "evidence": "button:disabled { cursor: not-allowed;"
   },
   "error": {
    "status": "shown",
    "how": "this component is the error state: an icon and a border in the danger colour, never a red block",
    "evidence": "var(--ds-color-border-danger)"
   },
   "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": "the buttons wrap, and on a phone they stack at full width under the text",
    "evidence": "@container (max-width: 26rem)"
   },
   "long_text": {
    "status": "handled",
    "how": "title, message and error code wrap, also long codes 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-danger-subtle",
  "--ds-color-bg-neutral-subtle",
  "--ds-color-border-danger",
  "--ds-color-border-default",
  "--ds-color-border-focus",
  "--ds-color-border-subtle",
  "--ds-color-surface-raised",
  "--ds-color-surface-sunken",
  "--ds-color-text-danger",
  "--ds-color-text-on-action",
  "--ds-color-text-primary",
  "--ds-color-text-secondary",
  "--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-control-sm",
  "--ds-radius-full",
  "--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-sm",
  "--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-code-sm",
  "--ds-text-label-lg",
  "--ds-text-title-md"
 ],
 "a11y": {
  "summary": "A section named by its heading; the icon is decorative, so the failure is said in words, and Try again is a real button that comes first in tab order.",
  "roles": [
   "region"
  ],
  "keyboard": [
   "Tab reaches Try again, then the other action",
   "Enter or Space presses either"
  ],
  "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/error-retry/component.html",
  "bytes": 5464,
  "script": false
 },
 "source": null,
 "photos": 0,
 "urls": {
  "html": "https://opendesigner.dev/library/error-retry.html",
  "json": "https://opendesigner.dev/library/error-retry.json",
  "page": "https://opendesigner.dev/library/error-retry/"
 },
 "get": {
  "curl": "curl -fsSLo error-retry.html https://opendesigner.dev/library/error-retry.html",
  "opendesigner": "python3 path/to/skills/opendesigner/scripts/library.py add error-retry --from https://opendesigner.dev",
  "prompt": "Add the OpenDesigner component error-retry to this project: https://opendesigner.dev/library/error-retry.html. Keep its markup and states; map its --ds-* variables to my tokens."
 }
}
