{"name":"select","title":"Select","description":"Displays a list of options for the user to pick from, triggered by a button.","installCommand":"bunx marko-ui add select -y","usageTags":"<Select>","importSnippet":"import Select from \"@/components/ui/select/select.marko\";","usageSnippet":"static const fruits = [\n  { value: \"apple\", label: \"Apple\" },\n  { value: \"banana\", label: \"Banana\" },\n];\n\n<Select items=fruits placeholder=\"Select a fruit\"/>","tags":["Select"],"parts":[{"name":"option","attributes":[{"name":"value","type":"string","required":true},{"name":"label","type":"string","required":true},{"name":"disabled","type":"boolean","required":false}],"repeatable":true}],"props":[{"name":"autoComplete","type":"string | undefined","required":false,"description":"The autocomplete attribute for the hidden select. Enables browser autofill (e.g. \"address-level1\" for state)."},{"name":"closeOnSelect","type":"boolean | undefined","required":false,"default":"true","description":"Whether the select should close after an item is selected"},{"name":"composite","type":"boolean | undefined","required":false,"default":"true","description":"Whether the select is a composed with other composite widgets like tabs or combobox"},{"name":"defaultHighlightedValue","type":"string | null | undefined","required":false,"description":"The initial value of the highlighted item when opened.\nUse when you don't need to control the highlighted value of the select."},{"name":"defaultOpen","type":"boolean | undefined","required":false,"description":"Whether the select's open state is controlled by the user"},{"name":"defaultValue","type":"string[] | undefined","required":false,"description":"The initial default value of the select when rendered.\nUse when you don't need to control the value of the select."},{"name":"deselectable","type":"boolean | undefined","required":false,"description":"Whether the value can be cleared by clicking the selected item.\n\n**Note:** this is only applicable for single selection"},{"name":"dir","type":"'ltr' | 'rtl' | undefined","required":false,"default":"ltr","description":"The document's text/writing direction."},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Whether the select is disabled"},{"name":"form","type":"string | undefined","required":false,"description":"The associate form of the underlying select."},{"name":"getRootNode","type":"(() => ShadowRoot | Document | Node) | undefined","required":false,"description":"A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron."},{"name":"groups","type":"SelectGroup[]","required":false},{"name":"highlightedValue","type":"string | null | undefined","required":false,"description":"The controlled key of the highlighted item"},{"name":"ids","type":"ElementIds | undefined","required":false,"description":"The ids of the elements in the select. Useful for composition."},{"name":"invalid","type":"boolean | undefined","required":false,"description":"Whether the select is invalid"},{"name":"items","type":"SelectItem[]","required":false},{"name":"label","type":"string","required":false,"description":"Field label rendered above the trigger (NOT the shadcn listbox group\nlabel — see `select-label` note on the group label below)."},{"name":"loopFocus","type":"boolean | undefined","required":false,"default":"false","description":"Whether to loop the keyboard navigation through the options"},{"name":"multiple","type":"boolean | undefined","required":false,"description":"Whether to allow multiple selection"},{"name":"name","type":"string | undefined","required":false,"description":"The `name` attribute of the underlying select."},{"name":"open","type":"boolean | undefined","required":false,"description":"Whether the select menu is open"},{"name":"placeholder","type":"string","required":false},{"name":"positioning","type":"PositioningOptions | undefined","required":false,"description":"The positioning options of the menu."},{"name":"readOnly","type":"boolean | undefined","required":false,"description":"Whether the select is read-only"},{"name":"required","type":"boolean | undefined","required":false,"description":"Whether the select is required"},{"name":"scrollToIndexFn","type":"((details: ScrollToIndexDetails) => void) | undefined","required":false,"description":"Function to scroll to a specific index"},{"name":"size","type":"'default' | 'sm'","required":false},{"name":"translations","type":"IntlTranslations | undefined","required":false,"description":"Specifies the localized strings that identifies the accessibility elements and their states"},{"name":"value","type":"string[] | undefined","required":false,"description":"The controlled keys of the selected items"}],"events":[{"name":"onFocusOutside","arg":"FocusOutsideEvent","description":"Function called when the focus is moved outside the component"},{"name":"onHighlightChange","arg":"HighlightChangeDetails<T>","description":"The callback fired when the highlighted item changes."},{"name":"onInteractOutside","arg":"InteractOutsideEvent","description":"Function called when an interaction happens outside the component"},{"name":"onOpenChange","arg":"OpenChangeDetails","description":"Function called when the popup is opened"},{"name":"onPointerDownOutside","arg":"PointerDownOutsideEvent","description":"Function called when the pointer is pressed down outside the component"},{"name":"onSelect","arg":"SelectionDetails","description":"Function called when an item is selected"},{"name":"onValueChange","arg":"ValueChangeDetails<T>","description":"The callback fired when the selected item changes."},{"name":"valueChange","arg":"string[]"}],"keyboard":[{"keys":"Space / Enter","description":"Opens the listbox. When open, selects the highlighted item."},{"keys":"ArrowDown / ArrowUp","description":"Opens the listbox, or moves the highlight to the next/previous item."},{"keys":"Home / End","description":"Moves the highlight to the first/last item."},{"keys":"Type-ahead","description":"Typing characters jumps the highlight to the next matching item's label."},{"keys":"Escape","description":"Closes the listbox without changing the selection."},{"keys":"Tab","description":"Closes the listbox and moves focus to the next focusable element."}],"accessibilityNotes":["The trigger renders as a native `<button>` with `aria-haspopup`, `aria-expanded`, and `aria-controls` wired by the Zag select machine.","A hidden native `<select>` mirrors the current items and value so the component participates in native form submission and browser autofill.","Pass `label` for a visible field label, or omit it to fall back to a screen-reader-only label built from `placeholder`.","Set `invalid` on a wrapping `Field` plus `aria-invalid` on `Select` to announce an error state — see the Invalid example."],"examples":[{"id":"select-demo","title":"Basic","source":"import Select from \"@marko-ui/shadcn/ui/select/select.marko\";\n\nstatic const fruits = [\n  { value: \"apple\", label: \"Apple\" },\n  { value: \"banana\", label: \"Banana\" },\n  { value: \"blueberry\", label: \"Blueberry\" },\n  { value: \"grapes\", label: \"Grapes\" },\n  { value: \"pineapple\", label: \"Pineapple\" },\n];\n\n<Select items=fruits placeholder=\"Select a fruit\"/>","description":"Pass an `items` array of `{ value, label }` entries."},{"id":"select-align-item","title":"Align item with trigger","source":"import Select from \"@marko-ui/shadcn/ui/select/select.marko\";\nimport Field from \"@marko-ui/shadcn/ui/field/field.marko\";\nimport FieldContent from \"@marko-ui/shadcn/ui/field/field-content.marko\";\nimport FieldDescription from \"@marko-ui/shadcn/ui/field/field-description.marko\";\nimport FieldGroup from \"@marko-ui/shadcn/ui/field/field-group.marko\";\nimport FieldLabel from \"@marko-ui/shadcn/ui/field/field-label.marko\";\nimport Switch from \"@marko-ui/shadcn/ui/switch/switch.marko\";\n\nstatic const fruits = [\n  { value: \"apple\", label: \"Apple\" },\n  { value: \"banana\", label: \"Banana\" },\n  { value: \"blueberry\", label: \"Blueberry\" },\n  { value: \"grapes\", label: \"Grapes\" },\n  { value: \"pineapple\", label: \"Pineapple\" },\n];\n\n<let/alignItemWithTrigger=true>\n\n<FieldGroup class=\"w-full max-w-xs\">\n  <Field orientation=\"horizontal\">\n    <FieldContent>\n      <FieldLabel for=\"select-align-item-switch\">Align Item</FieldLabel>\n      <FieldDescription>Toggle to align the item with the trigger.</FieldDescription>\n    </FieldContent>\n    <Switch id=\"select-align-item-switch\" ids={ hiddenInput: \"select-align-item-switch\" } checked:=alignItemWithTrigger/>\n  </Field>\n  <Field>\n    <Select\n      items=fruits\n      defaultValue=[\"banana\"]\n      positioning={ placement: alignItemWithTrigger ? \"bottom-start\" : \"bottom\" }\n    />\n  </Field>\n</FieldGroup>","description":"Upstream toggles a real item-aligned positioning mode; @zag-js/select has no such concept, so this demo wires the switch to the closest analog — a `positioning.placement` change, which swaps edge anchoring from bottom to top but never makes the selected item overlap the trigger the way upstream's mode does."},{"id":"select-groups","title":"Groups","source":"import Select from \"@marko-ui/shadcn/ui/select/select.marko\";\n\nstatic const groups = [\n  {\n    label: \"Fruits\",\n    items: [\n      { value: \"apple\", label: \"Apple\" },\n      { value: \"banana\", label: \"Banana\" },\n      { value: \"blueberry\", label: \"Blueberry\" },\n    ],\n  },\n  {\n    label: \"Vegetables\",\n    items: [\n      { value: \"carrot\", label: \"Carrot\" },\n      { value: \"broccoli\", label: \"Broccoli\" },\n      { value: \"spinach\", label: \"Spinach\" },\n    ],\n  },\n];\n\n<Select groups=groups placeholder=\"Select a fruit\" class=\"w-full max-w-48\"/>","description":"Pass `groups=` — an array of `{ label, items }` — to render labeled, separated option groups."},{"id":"select-scrollable","title":"Scrollable","source":"import Select from \"@marko-ui/shadcn/ui/select/select.marko\";\n\nstatic const groups = [\n  {\n    label: \"North America\",\n    items: [\n      { value: \"est\", label: \"Eastern Standard Time\" },\n      { value: \"cst\", label: \"Central Standard Time\" },\n      { value: \"mst\", label: \"Mountain Standard Time\" },\n      { value: \"pst\", label: \"Pacific Standard Time\" },\n      { value: \"akst\", label: \"Alaska Standard Time\" },\n      { value: \"hst\", label: \"Hawaii Standard Time\" },\n    ],\n  },\n  {\n    label: \"Europe & Africa\",\n    items: [\n      { value: \"gmt\", label: \"Greenwich Mean Time\" },\n      { value: \"cet\", label: \"Central European Time\" },\n      { value: \"eet\", label: \"Eastern European Time\" },\n      { value: \"west\", label: \"Western European Summer Time\" },\n      { value: \"cat\", label: \"Central Africa Time\" },\n      { value: \"eat\", label: \"East Africa Time\" },\n    ],\n  },\n  {\n    label: \"Asia\",\n    items: [\n      { value: \"msk\", label: \"Moscow Time\" },\n      { value: \"ist\", label: \"India Standard Time\" },\n      { value: \"cst_china\", label: \"China Standard Time\" },\n      { value: \"jst\", label: \"Japan Standard Time\" },\n      { value: \"kst\", label: \"Korea Standard Time\" },\n      { value: \"ist_indonesia\", label: \"Indonesia Central Standard Time\" },\n    ],\n  },\n  {\n    label: \"Australia & Pacific\",\n    items: [\n      { value: \"awst\", label: \"Australian Western Standard Time\" },\n      { value: \"acst\", label: \"Australian Central Standard Time\" },\n      { value: \"aest\", label: \"Australian Eastern Standard Time\" },\n      { value: \"nzst\", label: \"New Zealand Standard Time\" },\n      { value: \"fjt\", label: \"Fiji Time\" },\n    ],\n  },\n  {\n    label: \"South America\",\n    items: [\n      { value: \"art\", label: \"Argentina Time\" },\n      { value: \"bot\", label: \"Bolivia Time\" },\n      { value: \"brt\", label: \"Brasilia Time\" },\n      { value: \"clt\", label: \"Chile Standard Time\" },\n    ],\n  },\n];\n\n<Select groups=groups placeholder=\"Select a timezone\" class=\"w-full max-w-64\"/>","description":"A select with many grouped items that scrolls within the viewport."},{"id":"select-disabled","title":"Disabled","source":"import Select from \"@marko-ui/shadcn/ui/select/select.marko\";\n\nstatic const fruits = [\n  { value: \"apple\", label: \"Apple\" },\n  { value: \"banana\", label: \"Banana\" },\n  { value: \"blueberry\", label: \"Blueberry\" },\n  { value: \"grapes\", label: \"Grapes\" },\n  { value: \"pineapple\", label: \"Pineapple\" },\n];\n\n<Select items=fruits placeholder=\"Select a fruit\" disabled/>","description":"A disabled select is skipped by the tab order and ignores pointer input."},{"id":"select-invalid","title":"Invalid","source":"import Select from \"@marko-ui/shadcn/ui/select/select.marko\";\nimport Field from \"@marko-ui/shadcn/ui/field/field.marko\";\nimport FieldError from \"@marko-ui/shadcn/ui/field/field-error.marko\";\nimport FieldLabel from \"@marko-ui/shadcn/ui/field/field-label.marko\";\n\nstatic const fruits = [\n  { value: \"apple\", label: \"Apple\" },\n  { value: \"banana\", label: \"Banana\" },\n  { value: \"blueberry\", label: \"Blueberry\" },\n];\n\n<Field invalid class=\"w-full max-w-48\">\n  <FieldLabel>Fruit</FieldLabel>\n  <Select items=fruits placeholder=\"Select a fruit\" aria-invalid=\"true\"/>\n  <FieldError>Please select a fruit.</FieldError>\n</Field>","description":"Set `invalid` on `Field` and `aria-invalid` on `Select` to show an error state."},{"id":"select-rtl","title":"RTL","source":"import Select from \"@marko-ui/shadcn/ui/select/select.marko\";\n\nstatic const groups = [\n  {\n    label: \"الفواكه\",\n    items: [\n      { value: \"apple\", label: \"تفاح\" },\n      { value: \"banana\", label: \"موز\" },\n      { value: \"blueberry\", label: \"توت أزرق\" },\n      { value: \"grapes\", label: \"عنب\" },\n      { value: \"pineapple\", label: \"أناناس\" },\n    ],\n  },\n  {\n    label: \"الخضروات\",\n    items: [\n      { value: \"carrot\", label: \"جزر\" },\n      { value: \"broccoli\", label: \"بروكلي\" },\n      { value: \"spinach\", label: \"سبانخ\" },\n    ],\n  },\n];\n\n<Select groups=groups placeholder=\"اختر فاكهة\" dir=\"rtl\" class=\"w-32\"/>","description":"Pass `dir=\"rtl\"` — a real machine prop — to drive both the DOM attribute and Zag's RTL-aware keyboard and positioning logic."},{"id":"select-with-label","title":"With label","source":"import Select from \"@marko-ui/shadcn/ui/select/select.marko\";\n\nstatic const fruits = [\n  { value: \"apple\", label: \"Apple\" },\n  { value: \"banana\", label: \"Banana\" },\n  { value: \"blueberry\", label: \"Blueberry\" },\n  { value: \"grapes\", label: \"Grapes\" },\n  { value: \"pineapple\", label: \"Pineapple\" },\n];\n\n<Select items=fruits label=\"Fruit\" placeholder=\"Select a fruit\"/>","description":"Pass `label` to render a visible label instead of a screen-reader-only one."},{"id":"select-default-value","title":"Default value","source":"import Select from \"@marko-ui/shadcn/ui/select/select.marko\";\n\nstatic const fruits = [\n  { value: \"apple\", label: \"Apple\" },\n  { value: \"banana\", label: \"Banana\" },\n  { value: \"blueberry\", label: \"Blueberry\" },\n  { value: \"grapes\", label: \"Grapes\" },\n  { value: \"pineapple\", label: \"Pineapple\" },\n];\n\n<Select items=fruits defaultValue=[\"banana\"] placeholder=\"Select a fruit\"/>","description":"Pass `defaultValue` to set the initial selection without controlling it."},{"id":"select-disabled-items","title":"Disabled items","source":"import Select from \"@marko-ui/shadcn/ui/select/select.marko\";\n\nstatic const fruits = [\n  { value: \"apple\", label: \"Apple\" },\n  { value: \"banana\", label: \"Banana\", disabled: true },\n  { value: \"blueberry\", label: \"Blueberry\" },\n  { value: \"grapes\", label: \"Grapes\", disabled: true },\n  { value: \"pineapple\", label: \"Pineapple\" },\n];\n\n<Select items=fruits placeholder=\"Select a fruit\"/>","description":"Set `disabled: true` on individual entries in `items` to skip them."},{"id":"select-controlled","title":"Controlled","source":"import Select from \"@marko-ui/shadcn/ui/select/select.marko\";\n\nstatic const fruits = [\n  { value: \"apple\", label: \"Apple\" },\n  { value: \"banana\", label: \"Banana\" },\n  { value: \"blueberry\", label: \"Blueberry\" },\n  { value: \"grapes\", label: \"Grapes\" },\n  { value: \"pineapple\", label: \"Pineapple\" },\n];\n\n<let/value=[\"apple\"]/>\n\n<div class=\"flex items-center gap-4\">\n  <Select\n    items=fruits\n    value=value\n    valueChange=(next) => { value = next; }\n    placeholder=\"Select a fruit\"\n  />\n  <span class=\"text-sm text-muted-foreground\">value: ${value.join(\", \")}</span>\n</div>","description":"Zag machines are controlled: a `value` prop without a change handler never moves. Pair it with `valueChange`.","essential":true},{"id":"select-compound","title":"Compound (attr tags)","source":"import Select from \"@marko-ui/shadcn/ui/select/select.marko\";\n\n<Select placeholder=\"Select a fruit\">\n  <@option value=\"apple\" label=\"Apple\"/>\n  <@option value=\"banana\" label=\"Banana\"/>\n  <@option value=\"blueberry\" label=\"Blueberry\"/>\n  <@option value=\"grapes\" label=\"Grapes\"/>\n  <@option value=\"pineapple\" label=\"Pineapple\"/>\n</Select>","description":"Use `<@option>` attribute tags instead of `items=` to compose each option directly in markup.","essential":true}],"importInstallCommand":"bun add @marko-ui/shadcn marko-zag","nativeAttributes":"div","itemTypes":[{"prop":"groups","typeName":"SelectGroup","fields":[{"name":"label","type":"string","required":true},{"name":"items","type":"SelectItem[]","required":true}]},{"prop":"SelectGroup.items","typeName":"SelectItem","fields":[{"name":"value","type":"string","required":true},{"name":"label","type":"string","required":true},{"name":"disabled","type":"boolean","required":false}]}],"composition":"Select is a single unsplit component — it has no separate trigger/content/item\nparts to compose. Its anatomy (all internal, rendered from `items=` or\n`groups=`) mirrors upstream's tree:\n\n```text\nSelect\n├── select-field-label      (visible label, or sr-only when omitted)\n├── select-control\n│   └── select-trigger\n│       ├── select-value\n│       └── select-trigger-icon\n└── select-positioner        (portalled)\n    └── select-content\n        ├── select-scroll-up-button\n        ├── select-viewport\n        │   └── select-group        (only when `groups=` is used)\n        │       ├── select-label\n        │       └── select-item × N\n        │           ├── select-item-indicator\n        │           └── select-item-text\n        └── select-scroll-down-button\n```\n\nUse `items=` for a flat list, `groups=` for the grouped/labeled/separated\nlayout above, or the `<@option>` attribute tag to compose options directly in\nmarkup (see the Compound example below)."}
