{
 "id": "page-banners",
 "name": "Page banners",
 "purpose": "Four banners for the top of a page or section (info, success, warning and error), each with a bold first phrase, one sentence and one action.",
 "use_when": [
  "for news about the whole page or account that should stay until it's handled or dismissed",
  "something affects the whole page or account and stays true until it's handled"
 ],
 "avoid_when": [
  "a quick confirmation of something the person just did: use toast-undo",
  "a problem with one field: use field-error",
  "the whole page can't load: use page-error"
 ],
 "type": "states",
 "style": "quiet",
 "width": "wide",
 "tags": {
  "audience": "work",
  "industries": [
   "any"
  ],
  "keywords": [
   "banner",
   "alert",
   "info",
   "warning",
   "error"
  ]
 },
 "root": ".odl-page-banners",
 "parts": [
  {
   "name": "banners",
   "selector": ".odl-page-banners [data-od-list=\"banners\"]",
   "what": "the banners, one item each",
   "slot": "list"
  },
  {
   "name": "banners.tone",
   "selector": ".odl-page-banners [data-od-list=\"banners\"] [data-od-var=\"tone\"]",
   "what": "info, success, warning or error",
   "slot": "text"
  },
  {
   "name": "banners.title",
   "selector": ".odl-page-banners [data-od-list=\"banners\"] [data-od-slot=\"title\"]",
   "what": "the heading: what happened, in plain words, as in “New: approval rules.”",
   "slot": "text"
  },
  {
   "name": "banners.message",
   "selector": ".odl-page-banners [data-od-list=\"banners\"] [data-od-slot=\"message\"]",
   "what": "one or two sentences: what it means and what to do next, as in “Bills over $5,000 now need a second approver.”",
   "slot": "text"
  },
  {
   "name": "banners.action",
   "selector": ".odl-page-banners [data-od-list=\"banners\"] [data-od-action=\"action\"]",
   "what": "the Set up rules action",
   "slot": "action"
  },
  {
   "name": "banners.dismiss",
   "selector": ".odl-page-banners [data-od-list=\"banners\"] [data-od-action=\"dismiss\"]",
   "what": "the dismiss action",
   "slot": "action"
  }
 ],
 "data": {
  "type": "object",
  "properties": {
   "banners": {
    "type": "array",
    "minItems": 1,
    "maxItems": 8,
    "items": {
     "type": "object",
     "properties": {
      "tone": {
       "enum": [
        "danger",
        "info",
        "success",
        "warning"
       ],
       "part": "banners.tone"
      },
      "title": {
       "type": "string",
       "maxLength": 32,
       "part": "banners.title"
      },
      "message": {
       "type": "string",
       "maxLength": 64,
       "part": "banners.message"
      }
     },
     "required": [
      "tone",
      "title",
      "message"
     ]
    },
    "part": "banners"
   }
  },
  "required": [
   "banners"
  ]
 },
 "states": {
  "shown": [
   "info",
   "success",
   "warning",
   "error",
   "dismissed",
   "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": "shown",
    "how": "The error banner is an alert and stays until the problem is fixed.",
    "evidence": "role=\"alert\""
   },
   "disabled": {
    "status": "not_built",
    "how": "No control here is ever disabled; each one always does something."
   },
   "overflow": {
    "status": "handled",
    "how": "Text wraps beside the icon; the action follows the sentence.",
    "evidence": "minmax(0, 1fr)"
   },
   "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-color-bg-action-primary",
  "--ds-color-bg-action-primary-hover",
  "--ds-color-bg-action-primary-pressed",
  "--ds-color-bg-danger-subtle",
  "--ds-color-bg-info-subtle",
  "--ds-color-bg-neutral-subtle",
  "--ds-color-bg-success-subtle",
  "--ds-color-bg-warning-subtle",
  "--ds-color-border-danger",
  "--ds-color-border-default",
  "--ds-color-border-focus",
  "--ds-color-border-info",
  "--ds-color-border-subtle",
  "--ds-color-border-success",
  "--ds-color-border-warning",
  "--ds-color-icon-subtle",
  "--ds-color-surface-raised",
  "--ds-color-text-danger",
  "--ds-color-text-info",
  "--ds-color-text-link",
  "--ds-color-text-on-action",
  "--ds-color-text-primary",
  "--ds-color-text-success",
  "--ds-color-text-warning",
  "--ds-focus-ring-offset",
  "--ds-focus-ring-width",
  "--ds-font-weight-heading",
  "--ds-font-weight-label",
  "--ds-icon-stroke-md",
  "--ds-motion-duration-short",
  "--ds-motion-easing-standard",
  "--ds-opacity-disabled-container",
  "--ds-radius-container",
  "--ds-radius-control",
  "--ds-size-control-md",
  "--ds-size-icon-md",
  "--ds-size-icon-sm",
  "--ds-size-target-min",
  "--ds-space-inline-md",
  "--ds-space-inline-sm",
  "--ds-space-inset-lg",
  "--ds-space-inset-md",
  "--ds-space-inset-sm",
  "--ds-space-stack-sm",
  "--ds-state-error-bg",
  "--ds-state-error-border",
  "--ds-state-error-inset",
  "--ds-state-error-text",
  "--ds-text-body-md",
  "--ds-text-label-lg"
 ],
 "a11y": {
  "summary": "Info, success and warning are polite status regions; the error is an alert and can't be dismissed until it's fixed; dismiss buttons are named after their banner, and focus moves to the next banner.",
  "roles": [
   "alert",
   "region",
   "status"
  ],
  "keyboard": [
   "Tab reaches each banner's action, then its dismiss button",
   "Dismissing moves focus to the next banner"
  ],
  "controls": {
   "button": 7,
   "input": 0,
   "link": 0,
   "select": 0,
   "textarea": 0,
   "summary": 0
  },
  "focus_visible": true,
  "reduced_motion": true,
  "min_target": true
 },
 "files": {
  "html": "components/page-banners/component.html",
  "bytes": 13358,
  "script": true
 },
 "source": null,
 "photos": 0,
 "urls": {
  "html": "https://opendesigner.dev/library/page-banners.html",
  "json": "https://opendesigner.dev/library/page-banners.json",
  "page": "https://opendesigner.dev/library/page-banners/"
 },
 "get": {
  "curl": "curl -fsSLo page-banners.html https://opendesigner.dev/library/page-banners.html",
  "opendesigner": "python3 path/to/skills/opendesigner/scripts/library.py add page-banners --from https://opendesigner.dev",
  "prompt": "Add the OpenDesigner component page-banners to this project: https://opendesigner.dev/library/page-banners.html. Keep its markup and states; map its --ds-* variables to my tokens."
 }
}
