Filed unassigned out of objectui#6347, whose docs half deletes the page's ## Selection Mode section. Deleting the section is the honest thing to do about the documentation; it says nothing about whether the capability should exist. That question is this card.
What the renderer does, read off packages/components/src/renderers/basic/button-group.tsx
It maps schema.buttons to Button elements and reads exactly five things: schema.className, schema.variant, schema.size, button.variant, button.size, button.className, button.label. Nothing else. Specifically:
- No selection behaviour at all — no
selectionMode read, no group-level value read, no state, no onValueChange. selectionMode appears nowhere in the file; the only value reads in packages/components/src/renderers/** belong to other component types. ButtonGroupButton.onClick is declared and never wired.navigation.ts:325 declares onClick?: () = a void function, mirrored at zod/navigation.zod.ts:147 as z.function().optional(). The renderer passes no onClick to Button, so a declared handler is inert.disabled is declared twice and read neither time.ButtonGroupButton.disabled?: boolean (navigation.ts:321) and BaseSchema.disabled?: boolean | string reach ButtonGroupSchema; the renderer forwards neither to Button. Every sibling that declares item-level disabled — tabs, select, dropdown-menu, menubar, context-menu, and toggle-group since objectui#4632 — forwards it. button-group is the outlier.
What the catalog authors, counted
All six examples/schema-catalog/src/schemas/components-basic-button-group/*.json fixtures author keys the shipped types do not declare. Counted per fixture:
| fixture | buttons[].value | buttons[].icon | value | selectionMode |
|---|
basic-button-group.json | 3 | 0 | 0 | 0 |
icon-toolbar.json | 3 | 3 | 0 | 0 |
multiple-selection.json | 3 | 3 | 1 | 1 |
outline-variant.json | 3 | 0 | 0 | 0 |
single-selection.json | 3 | 0 | 1 | 1 |
with-icons.json | 2 | 2 | 0 | 0 |
| total | 17 | 8 | 2 | 2 |
29 occurrences, six of six fixtures. None of the four keys is declared on ButtonGroupSchema / ButtonGroupButton (navigation.ts:305-351, zod/navigation.zod.ts:142-159), and none is read by any renderer.
Overlap with objectui#5931, declared rather than left for a reader to find: that card already records with-icons.json's buttons[].icon (two occurrences), alongside the same shape in breadcrumb and command. What is new here is the other six icon occurrences in icon-toolbar.json and multiple-selection.json, the 17 buttons[].value, and the schema-level pair. If #5931 is settled first, its ruling should extend to this component's other two fixtures.
Why nothing goes red
BaseSchema is .passthrough() and carries [key: string]: any, so every one of the 29 parses green and type-checks — admitted unexamined, not refused (the reading component-fixture-declared-keys.test.ts and undeclared-but-consumed-keys-6150.test.ts both record). catalog-gallery-render.test.tsx renders each fixture and only fails on an unregistered type. So the demos render as inert button rows and every gate stays green.
The catalog is the corpus AI authoring tools retrieve from, which is what makes this more than cosmetic: an author copying single-selection.json gets a schema that validates, publishes, and does nothing.
The decision, stated as a fork
- Implement it. Wire
onClick and disabled (mechanical, and the sibling convention above already fixes their spelling), then decide separately whether selectionMode / value / per-button value / icon become declared members with real readers. That is a capability addition and needs the four-axis judgement, not a dev's guess. - Retire the authored surface. Under ADR-0049 enforce-or-remove, drop the 29 undeclared keys from the fixtures and leave the component a presentational group.
onClick and disabled would then be declared-but-dead and face the same question one level in.
I did not choose. objectui#6347's PR corrects the documentation to the shipped surface and touches no fixture and no renderer.
Refs: objectui#6347 · objectui#5931 · objectui#4632 · objectui#6157.
Filed unassigned out of objectui#6347, whose docs half deletes the page's
## Selection Modesection. Deleting the section is the honest thing to do about the documentation; it says nothing about whether the capability should exist. That question is this card.What the renderer does, read off
packages/components/src/renderers/basic/button-group.tsxIt maps
schema.buttonstoButtonelements and reads exactly five things:schema.className,schema.variant,schema.size,button.variant,button.size,button.className,button.label. Nothing else. Specifically:selectionModeread, no group-levelvalueread, no state, noonValueChange.selectionModeappears nowhere in the file; the onlyvaluereads inpackages/components/src/renderers/**belong to other component types.ButtonGroupButton.onClickis declared and never wired.navigation.ts:325declaresonClick?: () =a void function, mirrored atzod/navigation.zod.ts:147asz.function().optional(). The renderer passes noonClicktoButton, so a declared handler is inert.disabledis declared twice and read neither time.ButtonGroupButton.disabled?: boolean(navigation.ts:321) andBaseSchema.disabled?: boolean | stringreachButtonGroupSchema; the renderer forwards neither toButton. Every sibling that declares item-leveldisabled—tabs,select,dropdown-menu,menubar,context-menu, andtoggle-groupsince objectui#4632 — forwards it.button-groupis the outlier.What the catalog authors, counted
All six
examples/schema-catalog/src/schemas/components-basic-button-group/*.jsonfixtures author keys the shipped types do not declare. Counted per fixture:buttons[].valuebuttons[].iconvalueselectionModebasic-button-group.jsonicon-toolbar.jsonmultiple-selection.jsonoutline-variant.jsonsingle-selection.jsonwith-icons.json29 occurrences, six of six fixtures. None of the four keys is declared on
ButtonGroupSchema/ButtonGroupButton(navigation.ts:305-351,zod/navigation.zod.ts:142-159), and none is read by any renderer.Overlap with objectui#5931, declared rather than left for a reader to find: that card already records
with-icons.json'sbuttons[].icon(two occurrences), alongside the same shape inbreadcrumbandcommand. What is new here is the other sixiconoccurrences inicon-toolbar.jsonandmultiple-selection.json, the 17buttons[].value, and the schema-level pair. If #5931 is settled first, its ruling should extend to this component's other two fixtures.Why nothing goes red
BaseSchemais.passthrough()and carries[key: string]: any, so every one of the 29 parses green and type-checks — admitted unexamined, not refused (the readingcomponent-fixture-declared-keys.test.tsandundeclared-but-consumed-keys-6150.test.tsboth record).catalog-gallery-render.test.tsxrenders each fixture and only fails on an unregistered type. So the demos render as inert button rows and every gate stays green.The catalog is the corpus AI authoring tools retrieve from, which is what makes this more than cosmetic: an author copying
single-selection.jsongets a schema that validates, publishes, and does nothing.The decision, stated as a fork
onClickanddisabled(mechanical, and the sibling convention above already fixes their spelling), then decide separately whetherselectionMode/value/ per-buttonvalue/iconbecome declared members with real readers. That is a capability addition and needs the four-axis judgement, not a dev's guess.onClickanddisabledwould then be declared-but-dead and face the same question one level in.I did not choose. objectui#6347's PR corrects the documentation to the shipped surface and touches no fixture and no renderer.
Refs: objectui#6347 · objectui#5931 · objectui#4632 · objectui#6157.