{
 "id": "result-list",
 "name": "Result list",
 "purpose": "Up to eight results as cards: a photo, the name, one meta line, an optional detail and badge, a price and one button each.",
 "use_when": [
  "when someone asks to find or be shown a few places, stays, products or services and will open one",
  "a short list of results to scan and open one: stays, restaurants, products, classes or venues"
 ],
 "avoid_when": [
  "two to four options compared on the same attributes: use comparison",
  "one item in detail: use product-card",
  "rows of records with many columns: use data-table"
 ],
 "type": "content",
 "style": "friendly",
 "width": "medium",
 "tags": {
  "audience": "consumer",
  "industries": [
   "travel",
   "food",
   "retail",
   "events",
   "home",
   "any"
  ],
  "keywords": [
   "results",
   "search",
   "list",
   "cards",
   "recommendations"
  ]
 },
 "root": ".odl-result-list",
 "parts": [
  {
   "name": "title",
   "selector": ".odl-result-list h3",
   "what": "what was searched for",
   "slot": "text"
  },
  {
   "name": "note",
   "selector": ".odl-sub",
   "what": "how many results, and the filters that apply",
   "slot": "text"
  },
  {
   "name": "results",
   "selector": ".odl-result-list li",
   "what": "one result card",
   "slot": "list"
  },
  {
   "name": "image",
   "selector": ".odl-thumb",
   "what": "a square photo of the result",
   "slot": "media"
  },
  {
   "name": "result_title",
   "selector": ".odl-title",
   "what": "the result's name",
   "slot": "text"
  },
  {
   "name": "badge",
   "selector": ".odl-badge",
   "what": "one short fact worth a badge, such as 'Free cancellation'",
   "slot": "text"
  },
  {
   "name": "meta",
   "selector": ".odl-meta",
   "what": "one line: kind, rating, distance",
   "slot": "text"
  },
  {
   "name": "detail",
   "selector": ".odl-detail",
   "what": "one sentence about it",
   "slot": "text"
  },
  {
   "name": "value",
   "selector": ".odl-value",
   "what": "the price or headline value",
   "slot": "text"
  },
  {
   "name": "value_note",
   "selector": ".odl-per",
   "what": "what the value covers, such as 'a night'",
   "slot": "text"
  },
  {
   "name": "action",
   "selector": ".odl-act",
   "what": "opens or picks this result",
   "slot": "action"
  }
 ],
 "data": {
  "type": "object",
  "required": [
   "title",
   "results"
  ],
  "properties": {
   "title": {
    "type": "string",
    "maxLength": 48,
    "part": "title"
   },
   "note": {
    "type": "string",
    "maxLength": 80,
    "part": "note"
   },
   "results": {
    "type": "array",
    "minItems": 1,
    "maxItems": 8,
    "part": "results",
    "items": {
     "type": "object",
     "required": [
      "title",
      "meta",
      "action"
     ],
     "properties": {
      "image": {
       "type": "object",
       "part": "image",
       "properties": {
        "src": {
         "type": "string",
         "maxLength": 2048
        },
        "alt": {
         "type": "string",
         "maxLength": 200
        }
       },
       "required": [
        "src",
        "alt"
       ]
      },
      "title": {
       "type": "string",
       "maxLength": 40,
       "part": "result_title"
      },
      "badge": {
       "type": "string",
       "maxLength": 22,
       "part": "badge"
      },
      "meta": {
       "type": "string",
       "maxLength": 60,
       "part": "meta"
      },
      "detail": {
       "type": "string",
       "maxLength": 110,
       "part": "detail"
      },
      "value": {
       "type": "string",
       "maxLength": 12,
       "part": "value"
      },
      "value_note": {
       "type": "string",
       "maxLength": 20,
       "part": "value_note"
      },
      "action": {
       "type": "object",
       "part": "action",
       "properties": {
        "label": {
         "type": "string",
         "maxLength": 40
        },
        "event": {
         "type": "object"
        }
       },
       "required": [
        "label",
        "event"
       ]
      }
     }
    }
   }
  }
 },
 "states": {
  "shown": [
   "with photo",
   "without photo",
   "badge",
   "price",
   "hover",
   "focus",
   "disabled",
   "stacks on a phone"
  ],
  "edge": {
   "empty": {
    "status": "handled",
    "how": "no results: the list shows one dashed line saying there is nothing to show; better still, answer in text with what to change",
    "evidence": ".od-empty"
   },
   "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": "handled",
    "how": "a photo that fails to load keeps its square, with the photo's description written in it",
    "evidence": ".od-missing-image"
   },
   "disabled": {
    "status": "shown",
    "how": "a result that cannot be opened (sold out) has its button disabled and dimmed",
    "evidence": ".odl-act:disabled"
   },
   "overflow": {
    "status": "handled",
    "how": "on a phone the photo stays beside the text and the price and button move to one line underneath",
    "evidence": "@container (max-width: 32rem)"
   },
   "long_text": {
    "status": "handled",
    "how": "names, badge, meta and detail wrap; the price never wraps",
    "evidence": "overflow-wrap: anywhere"
   },
   "missing_image": {
    "status": "handled",
    "evidence": "data-od-media",
    "how": "the Smart UI renderer swaps a photo that fails to load for a block of the same size with its alt text"
   }
  }
 },
 "tokens": [
  "--ds-border-width-default",
  "--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-surface-sunken",
  "--ds-color-text-primary",
  "--ds-color-text-secondary",
  "--ds-color-text-tertiary",
  "--ds-elevation-raised",
  "--ds-focus-ring-offset",
  "--ds-focus-ring-width",
  "--ds-font-weight-heading",
  "--ds-font-weight-label",
  "--ds-motion-duration-short",
  "--ds-motion-easing-standard",
  "--ds-radius-container",
  "--ds-radius-control",
  "--ds-radius-full",
  "--ds-radius-nested",
  "--ds-size-control-md",
  "--ds-size-control-sm",
  "--ds-size-target-min",
  "--ds-space-2",
  "--ds-space-inline-md",
  "--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-md",
  "--ds-space-stack-sm",
  "--ds-space-stack-xs",
  "--ds-text-body-md",
  "--ds-text-body-sm",
  "--ds-text-label-lg",
  "--ds-text-label-md",
  "--ds-text-label-sm",
  "--ds-text-numeric-md",
  "--ds-text-title-md",
  "--ds-text-title-sm"
 ],
 "a11y": {
  "summary": "A list of results, each with its name as text and its photo described; each button is named with its result (\"View, Casa da Calçada\").",
  "roles": [
   "banner",
   "list",
   "region"
  ],
  "keyboard": [
   "Tab moves through the result buttons in list order",
   "Enter or Space presses one"
  ],
  "controls": {
   "button": 4,
   "input": 0,
   "link": 0,
   "select": 0,
   "textarea": 0,
   "summary": 0
  },
  "focus_visible": true,
  "reduced_motion": true,
  "min_target": true
 },
 "files": {
  "html": "components/result-list/component.html",
  "bytes": 8959,
  "script": false
 },
 "source": null,
 "photos": 4,
 "urls": {
  "html": "https://opendesigner.dev/library/result-list.html",
  "json": "https://opendesigner.dev/library/result-list.json",
  "page": "https://opendesigner.dev/library/result-list/"
 },
 "get": {
  "curl": "curl -fsSLo result-list.html https://opendesigner.dev/library/result-list.html",
  "opendesigner": "python3 path/to/skills/opendesigner/scripts/library.py add result-list --from https://opendesigner.dev",
  "prompt": "Add the OpenDesigner component result-list to this project: https://opendesigner.dev/library/result-list.html. Keep its markup and states; map its --ds-* variables to my tokens."
 }
}
