{
 "id": "session-expired",
 "name": "Session expired",
 "purpose": "A sign-in-again card that says why the session ended and shows that the person's unsaved work is kept on this device.",
 "use_when": [
  "when a session times out while someone is working, before they lose what they typed",
  "an idle or security timeout signs the person out mid-task",
  "a token refresh fails while there is unsaved input"
 ],
 "avoid_when": [
  "the person has no work in progress: send them to the sign-in page",
  "they lack permission rather than a session: use page-no-access"
 ],
 "type": "states",
 "style": "quiet",
 "width": "narrow",
 "tags": {
  "audience": "work",
  "industries": [
   "any"
  ],
  "keywords": [
   "session",
   "timeout",
   "sign in",
   "draft saved",
   "security"
  ]
 },
 "root": ".odl-session-expired",
 "parts": [
  {
   "name": "title",
   "selector": ".odl-session-expired [data-od-slot=\"title\"]",
   "what": "the heading: what happened, in plain words, as in “Your session ended”",
   "slot": "text"
  },
  {
   "name": "message",
   "selector": ".odl-session-expired [data-od-slot=\"message\"]",
   "what": "one or two sentences: what it means and what to do next, as in “For your security, we signed you out after 30 mi”",
   "slot": "text"
  },
  {
   "name": "draft",
   "selector": ".odl-session-expired [data-od-slot=\"draft\"]",
   "what": "the work that was kept, as in “Draft: Q4 vendor review”",
   "slot": "text"
  },
  {
   "name": "saved",
   "selector": ".odl-session-expired [data-od-slot=\"saved\"]",
   "what": "where and when the work was kept, as in “Kept on this device · saved 2 minutes ago”",
   "slot": "text"
  },
  {
   "name": "sign_in",
   "selector": ".odl-session-expired [data-od-action=\"sign_in\"]",
   "what": "the Sign in again action",
   "slot": "action"
  },
  {
   "name": "switch",
   "selector": ".odl-session-expired [data-od-action=\"switch\"]",
   "what": "the Use another account action",
   "slot": "action"
  }
 ],
 "data": {
  "type": "object",
  "properties": {
   "title": {
    "type": "string",
    "maxLength": 24,
    "part": "title"
   },
   "message": {
    "type": "string",
    "maxLength": 176,
    "part": "message"
   },
   "draft": {
    "type": "string",
    "maxLength": 32,
    "part": "draft"
   },
   "saved": {
    "type": "string",
    "maxLength": 64,
    "part": "saved"
   }
  },
  "required": [
   "title",
   "message",
   "draft",
   "saved"
  ]
 },
 "states": {
  "shown": [
   "expired",
   "hover",
   "focus"
  ],
  "edge": {
   "empty": {
    "status": "not_built",
    "how": "Not applicable: this state screen shows no list of records."
   },
   "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 part is itself an error or system state, written in plain words with a next step.",
    "evidence": "class=\"odl-lead\""
   },
   "disabled": {
    "status": "not_built",
    "how": "No control here is ever disabled; each one always does something."
   },
   "overflow": {
    "status": "handled",
    "how": "A long draft name ends in an ellipsis on one line.",
    "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-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-surface-overlay",
  "--ds-color-surface-raised",
  "--ds-color-surface-sunken",
  "--ds-color-text-link",
  "--ds-color-text-on-action",
  "--ds-color-text-primary",
  "--ds-color-text-secondary",
  "--ds-color-text-success",
  "--ds-color-text-warning",
  "--ds-elevation-overlay",
  "--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-radius-full",
  "--ds-radius-nested",
  "--ds-radius-overlay",
  "--ds-size-control-lg",
  "--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-inset-xl",
  "--ds-space-stack-lg",
  "--ds-space-stack-md",
  "--ds-space-stack-sm",
  "--ds-space-stack-xl",
  "--ds-text-body-md",
  "--ds-text-body-sm",
  "--ds-text-label-lg",
  "--ds-text-title-md"
 ],
 "a11y": {
  "summary": "The title and reason sit in an alert, read as soon as the card appears. Move focus to Sign in again when you show it: the part never moves focus on its own, so a page that only displays it isn't hijacked. The saved draft is described in text, not only by an icon.",
  "roles": [
   "alert",
   "region"
  ],
  "keyboard": [
   "Sign in again is the first focusable control",
   "Tab then reaches Use another account"
  ],
  "controls": {
   "button": 0,
   "input": 0,
   "link": 2,
   "select": 0,
   "textarea": 0,
   "summary": 0
  },
  "focus_visible": true,
  "reduced_motion": true,
  "min_target": true
 },
 "files": {
  "html": "components/session-expired/component.html",
  "bytes": 6830,
  "script": false
 },
 "source": null,
 "photos": 0,
 "urls": {
  "html": "https://opendesigner.dev/library/session-expired.html",
  "json": "https://opendesigner.dev/library/session-expired.json",
  "page": "https://opendesigner.dev/library/session-expired/"
 },
 "get": {
  "curl": "curl -fsSLo session-expired.html https://opendesigner.dev/library/session-expired.html",
  "opendesigner": "python3 path/to/skills/opendesigner/scripts/library.py add session-expired --from https://opendesigner.dev",
  "prompt": "Add the OpenDesigner component session-expired to this project: https://opendesigner.dev/library/session-expired.html. Keep its markup and states; map its --ds-* variables to my tokens."
 }
}
