{"name":"toggle-group","title":"Toggle Group","description":"A set of two-state buttons that can be toggled on or off.","installCommand":"bunx marko-ui add toggle-group -y","usageTags":"<ToggleGroup>","importSnippet":"import ToggleGroup from \"@/components/ui/toggle-group/toggle-group.marko\";","usageSnippet":"<ToggleGroup items=[{ value: \"left\", label: \"Left\" }, { value: \"center\", label: \"Center\" }] value=[\"center\"]/>","tags":["ToggleGroup"],"parts":[{"name":"item","attributes":[{"name":"value","type":"string","required":true},{"name":"disabled","type":"boolean","required":false}],"repeatable":true}],"props":[{"name":"defaultValue","type":"string[] | undefined","required":false,"description":"The initial selected value of the toggle group when rendered.\nUse when you don't need to control the selected value of the toggle group."},{"name":"deselectable","type":"boolean | undefined","required":false,"default":"true","description":"Whether the toggle group allows empty selection.\n**Note:** This is ignored if `multiple` is `true`."},{"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 toggle is disabled."},{"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":"ids","type":"ElementIds | undefined","required":false,"description":"The ids of the elements in the toggle. Useful for composition."},{"name":"items","type":"ToggleGroupItem[]","required":false},{"name":"loopFocus","type":"boolean | undefined","required":false,"default":"true","description":"Whether to loop focus inside the toggle group."},{"name":"multiple","type":"boolean | undefined","required":false,"description":"Whether to allow multiple toggles to be selected."},{"name":"orientation","type":"Orientation | undefined","required":false,"default":"horizontal","description":"The orientation of the toggle group."},{"name":"rovingFocus","type":"boolean | undefined","required":false,"default":"true","description":"Whether to use roving tab index to manage focus."},{"name":"spacing","type":"number","required":false},{"name":"value","type":"string[] | undefined","required":false,"description":"The controlled selected value of the toggle group."}],"events":[{"name":"onValueChange","arg":"ValueChangeDetails","description":"Function to call when the toggle is clicked."},{"name":"valueChange","arg":"string[]"}],"keyboard":[{"keys":"Tab / Shift+Tab","description":"Moves focus into and out of the group, landing on the currently pressed item (or the first item if none is pressed)."},{"keys":"Arrow Right / Arrow Left","description":"Moves focus between items when `orientation` is `horizontal` (the default); wraps at the ends."},{"keys":"Arrow Down / Arrow Up","description":"Moves focus between items when `orientation=\"vertical\"`; wraps at the ends."},{"keys":"Space / Enter","description":"Toggles the focused item."},{"keys":"Home / End","description":"Moves focus to the first / last item."}],"accessibilityNotes":["The root renders `role=\"group\"`; each item is a native `<button type=\"button\">` with `aria-pressed` reflecting its toggled state, so assistive tech announces the set and each item's state without extra ARIA wiring.","Use `aria-label` or `aria-labelledby` on `ToggleGroup` to give the group an accessible name, especially when it has no visible heading (the font-weight-selector example instead pairs it with a visible `FieldLabel`).","Icon-only items need their own accessible name. A per-item `<@item>` forwards `value`/`disabled`/`content` (and an `items=` entry adds `label`) — there is no per-item `aria-label` passthrough, and the item button does not receive one — so an icon-only item must carry a visually-hidden label in its content (see toggle-group-vertical.marko).","Disabling `ToggleGroup` itself (not a single item) removes every item from the tab order and blocks pointer input across the whole group."],"examples":[{"id":"toggle-group-demo","title":"Default","source":"import ToggleGroup from \"@marko-ui/shadcn/ui/toggle-group/toggle-group.marko\";\n\nstatic const ALIGNMENT = [\n  { value: \"left\", label: \"Left\" },\n  { value: \"center\", label: \"Center\" },\n  { value: \"right\", label: \"Right\" },\n];\n\n<ToggleGroup items=ALIGNMENT defaultValue=[\"center\"]/>","description":"Pass an `items: { value, label, disabled? }[]` array and the component renders every item internally — or compose items in markup with `<@item>` attribute tags (see the Compound example). By default only one item can be pressed at a time."},{"id":"toggle-group-multiple","title":"Multiple selection","source":"import ToggleGroup from \"@marko-ui/shadcn/ui/toggle-group/toggle-group.marko\";\n\nstatic const FORMATTING = [\n  { value: \"bold\", label: \"B\" },\n  { value: \"italic\", label: \"I\" },\n  { value: \"underline\", label: \"U\", disabled: true },\n];\n\n<ToggleGroup items=FORMATTING multiple value=[\"bold\"]/>","description":"Pass `multiple` to allow more than one item to be pressed at once."},{"id":"toggle-group-controlled","title":"Controlled","source":"import ToggleGroup from \"@marko-ui/shadcn/ui/toggle-group/toggle-group.marko\";\n\nstatic const ALIGNMENT = [\n  { value: \"left\", label: \"Left\" },\n  { value: \"center\", label: \"Center\" },\n  { value: \"right\", label: \"Right\" },\n];\n\n<let/value=[\"center\"]/>\n\n<div class=\"flex flex-col items-start gap-4\">\n  <ToggleGroup\n    items=ALIGNMENT\n    value=value\n    valueChange=(next) => { value = next; }\n  />\n  <span class=\"text-sm text-muted-foreground\">value: ${value.join(\", \") || \"none\"}</span>\n</div>","description":"Zag machines are controlled: a `value` prop without a change handler never moves. Pair it with `valueChange`, or use Marko's bind shorthand `value:=state`.","essential":true},{"id":"toggle-group-compound","title":"Compound (attr tags)","source":"import ToggleGroup from \"@marko-ui/shadcn/ui/toggle-group/toggle-group.marko\";\n\n<ToggleGroup value=[\"center\"]>\n  <@item value=\"left\">Left</@item>\n  <@item value=\"center\">Center</@item>\n  <@item value=\"right\">Right</@item>\n</ToggleGroup>","description":"Use `<@item>` attribute tags instead of `items=` to compose each option directly in markup.","essential":true},{"id":"toggle-group-outline","title":"Outline","source":"import ToggleGroup from \"@marko-ui/shadcn/ui/toggle-group/toggle-group.marko\";\n\nstatic const ALIGNMENT = [\n  { value: \"left\", label: \"Left\" },\n  { value: \"center\", label: \"Center\" },\n  { value: \"right\", label: \"Right\" },\n];\n\n<ToggleGroup items=ALIGNMENT variant=\"outline\" value=[\"left\"]/>","description":"Pass `variant=\"outline\"` for an outline style."},{"id":"toggle-group-sizes","title":"Size","source":"import ToggleGroup from \"@marko-ui/shadcn/ui/toggle-group/toggle-group.marko\";\n\nstatic const ALIGNMENT = [\n  { value: \"left\", label: \"Left\" },\n  { value: \"center\", label: \"Center\" },\n  { value: \"right\", label: \"Right\" },\n];\n\n<div class=\"flex flex-col items-start gap-4\">\n  <ToggleGroup items=ALIGNMENT size=\"sm\" value=[\"left\"]/>\n  <ToggleGroup items=ALIGNMENT value=[\"left\"]/>\n  <ToggleGroup items=ALIGNMENT size=\"lg\" value=[\"left\"]/>\n</div>","description":"Pass `size` as `sm`, `default`, or `lg` to change the size of every item."},{"id":"toggle-group-spacing","title":"Spacing","source":"import ToggleGroup from \"@marko-ui/shadcn/ui/toggle-group/toggle-group.marko\";\n\nstatic const SIDES = [\n  { value: \"top\", label: \"Top\" },\n  { value: \"bottom\", label: \"Bottom\" },\n  { value: \"left\", label: \"Left\" },\n  { value: \"right\", label: \"Right\" },\n];\n\n<ToggleGroup items=SIDES size=\"sm\" variant=\"outline\" spacing=2 value=[\"top\"]/>","description":"Pass `spacing` (in Tailwind spacing-scale units) to add gap between items — `spacing={0}` renders connected items with shared borders instead."},{"id":"toggle-group-vertical","title":"Vertical","source":"import ToggleGroup from \"@marko-ui/shadcn/ui/toggle-group/toggle-group.marko\";\nimport Icon from \"@marko-ui/shadcn/ui/icon/icon.marko\";\n\n<ToggleGroup multiple orientation=\"vertical\" spacing=1 value=[\"bold\", \"italic\"]>\n  <@item value=\"bold\">\n    <Icon name=\"Bold\"/>\n    <span class=\"sr-only\">Bold</span>\n  </@item>\n  <@item value=\"italic\">\n    <Icon name=\"Italic\"/>\n    <span class=\"sr-only\">Italic</span>\n  </@item>\n  <@item value=\"underline\">\n    <Icon name=\"Underline\"/>\n    <span class=\"sr-only\">Underline</span>\n  </@item>\n</ToggleGroup>","description":"Pass `orientation=\"vertical\"` for a vertical toggle group; arrow-key navigation follows the same axis."},{"id":"toggle-group-disabled","title":"Disabled","source":"import ToggleGroup from \"@marko-ui/shadcn/ui/toggle-group/toggle-group.marko\";\n\nstatic const ALIGNMENT = [\n  { value: \"left\", label: \"Left\" },\n  { value: \"center\", label: \"Center\" },\n  { value: \"right\", label: \"Right\" },\n];\n\n<ToggleGroup items=ALIGNMENT value=[\"left\"] disabled/>","description":"Pass `disabled` on `ToggleGroup` to disable every item in the group."},{"id":"toggle-group-font-weight-selector","title":"Custom","source":"import ToggleGroup from \"@marko-ui/shadcn/ui/toggle-group/toggle-group.marko\";\nimport Field from \"@marko-ui/shadcn/ui/field/field.marko\";\nimport FieldLabel from \"@marko-ui/shadcn/ui/field/field-label.marko\";\nimport FieldDescription from \"@marko-ui/shadcn/ui/field/field-description.marko\";\n\n<let/fontWeight=\"normal\"/>\n\n<Field>\n  <FieldLabel>Font Weight</FieldLabel>\n  <ToggleGroup\n    value=[fontWeight]\n    valueChange=(next) => { fontWeight = next[0] ?? fontWeight; }\n    variant=\"outline\"\n    spacing=2\n    size=\"lg\"\n  >\n    <@item value=\"light\">\n      <span class=\"flex size-16 flex-col items-center justify-center rounded-xl\">\n        <span class=\"text-2xl leading-none font-light\">Aa</span>\n        <span class=\"text-xs text-muted-foreground\">Light</span>\n      </span>\n    </@item>\n    <@item value=\"normal\">\n      <span class=\"flex size-16 flex-col items-center justify-center rounded-xl\">\n        <span class=\"text-2xl leading-none font-normal\">Aa</span>\n        <span class=\"text-xs text-muted-foreground\">Normal</span>\n      </span>\n    </@item>\n    <@item value=\"medium\">\n      <span class=\"flex size-16 flex-col items-center justify-center rounded-xl\">\n        <span class=\"text-2xl leading-none font-medium\">Aa</span>\n        <span class=\"text-xs text-muted-foreground\">Medium</span>\n      </span>\n    </@item>\n    <@item value=\"bold\">\n      <span class=\"flex size-16 flex-col items-center justify-center rounded-xl\">\n        <span class=\"text-2xl leading-none font-bold\">Aa</span>\n        <span class=\"text-xs text-muted-foreground\">Bold</span>\n      </span>\n    </@item>\n  </ToggleGroup>\n  <FieldDescription>\n    Use <code class=\"rounded-md bg-muted px-1 py-0.5 font-mono\">font-${fontWeight}</code> to set the font weight.\n  </FieldDescription>\n</Field>","description":"A custom toggle group example: `<@item>` bodies can render arbitrary markup (not just text), here paired with `Field`/`FieldLabel`/`FieldDescription` to build a font-weight selector."},{"id":"toggle-group-rtl","title":"RTL","source":"import ToggleGroup from \"@marko-ui/shadcn/ui/toggle-group/toggle-group.marko\";\n\n<ToggleGroup variant=\"outline\" value=[\"list\"] dir=\"rtl\">\n  <@item value=\"list\">قائمة</@item>\n  <@item value=\"grid\">شبكة</@item>\n  <@item value=\"cards\">بطاقات</@item>\n</ToggleGroup>","description":"Toggle groups restyle correctly under `dir=\"rtl\"` — the same prop drives both the machine's arrow-key navigation direction and the logical-property layout, so pass it straight to `ToggleGroup` rather than only wrapping it in a `dir` attribute."}],"importInstallCommand":"bun add @marko-ui/shadcn marko-zag","nativeAttributes":"div","itemTypes":[{"prop":"items","typeName":"ToggleGroupItem","fields":[{"name":"value","type":"string","required":true},{"name":"label","type":"string","required":true},{"name":"disabled","type":"boolean","required":false}]}],"composition":"A single-file component whose anatomy is expressed through the `items=` array or `<@item>` attribute tags, not separate parts — api-reference.json sees one part, so this prose stands in for upstream's Composition tree:\n\n```text\nToggleGroup\n└── item (one per entry in `items=`, or one per `<@item>` attribute tag)\n```\n\nUpstream expresses this as `ToggleGroup` > `ToggleGroupItem` children; our port has no separate `ToggleGroupItem` tag — each item is either a plain object (`{ value, label, disabled? }`) in `items=`, or a `<@item value=\"...\">` attribute tag whose body becomes the item's rendered content. Attribute tags win if both are supplied on the same `ToggleGroup`."}
