Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
91c9b42
fix(bulma-ui): name custom form controls from a Field label
allxsmith Oct 7, 2026
04b3575
fix(bulma-ui): take no Field id for a Taginput at its tag limit
allxsmith Oct 8, 2026
2cb9366
fix(bulma-ui): drop Taginput's fallback name when a label is wired by…
allxsmith Oct 8, 2026
8fd3457
fix(bulma-ui): keep the label's id and name through an undefined call…
allxsmith Oct 8, 2026
3b4e2a1
Merge remote-tracking branch 'origin/main' into work-974-threads
allxsmith Oct 8, 2026
30c6933
fix(bulma-ui): name DateRangeInput's default icon in its Control-leve…
allxsmith Oct 8, 2026
958275b
Merge remote-tracking branch 'origin/main' into work-974-merge2
allxsmith Oct 8, 2026
1658ec1
fix(bulma-ui): keep Input, Select and TextArea labelled through an un…
allxsmith Oct 8, 2026
2f886e8
Merge remote-tracking branch 'origin/main' into work-974-merge3
allxsmith Oct 8, 2026
d38c64c
chore: regenerate after merging main
allxsmith Oct 8, 2026
d5d650d
Merge remote-tracking branch 'origin/main' into fix/939-field-label-n…
allxsmith Oct 8, 2026
a351898
chore: regenerate after merging main
allxsmith Oct 8, 2026
8da6804
test(bulma-ui): cover inline TimeInput and DateTimeInput in the Field…
allxsmith Oct 8, 2026
132976b
docs: say any content without the label's target leaves its for unmat…
allxsmith Oct 8, 2026
7e83a0f
Merge remote-tracking branch 'origin/main' into gate-fix-939-field-la…
allxsmith Oct 8, 2026
68098db
chore: regenerate after merging main
allxsmith Oct 8, 2026
c68fb50
fix(bulma-ui): let a caller's aria name win over a group's own label
allxsmith Oct 9, 2026
4c319bb
docs: drop the unmatched for from the hand-wired group examples
allxsmith Oct 9, 2026
3b940c7
chore: regenerate
allxsmith Oct 9, 2026
b60f19c
Merge remote-tracking branch 'origin/main' into gate-fix-939-field-la…
allxsmith Oct 9, 2026
ddb7c34
chore: regenerate after merging main
allxsmith Oct 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bestax-mcp/data/catalog.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"schemaVersion": 2,
"generatedFrom": {
"package": "@allxsmith/bestax-bulma",
"version": "5.27.0"
"version": "5.27.1"
},
"docsBase": "https://bestax.io/docs",
"categories": [
Expand Down
8 changes: 4 additions & 4 deletions bestax-mcp/data/components/Autocomplete.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@
},
{
"title": "Context-Aware Rendering",
"code": "function example() {\n return (\n <Field horizontal label=\"Fruit\">\n <Field.Body>\n <Field>\n <Autocomplete\n data={['Apple', 'Banana', 'Cherry']}\n placeholder=\"Search fruit...\"\n />\n </Field>\n </Field.Body>\n </Field>\n );\n}"
"code": "function example() {\n return (\n <Field horizontal label=\"Fruit\" labelProps={{ htmlFor: 'fruit-field' }}>\n <Field.Body>\n <Field>\n <Autocomplete\n id=\"fruit-field\"\n data={['Apple', 'Banana', 'Cherry']}\n placeholder=\"Search fruit...\"\n />\n </Field>\n </Field.Body>\n </Field>\n );\n}"
},
{
"title": "Context-Aware Rendering",
"code": "function example() {\n return (\n <Field horizontal label=\"Fruit\">\n <Field.Body>\n <Field>\n <Control iconLeftName=\"search\">\n <Autocomplete\n data={['Apple', 'Banana', 'Cherry']}\n placeholder=\"Search fruit...\"\n />\n </Control>\n </Field>\n </Field.Body>\n </Field>\n );\n}"
"code": "function example() {\n return (\n <Field\n horizontal\n label=\"Fruit\"\n labelProps={{ htmlFor: 'fruit-field-control' }}\n >\n <Field.Body>\n <Field>\n <Control iconLeftName=\"search\">\n <Autocomplete\n id=\"fruit-field-control\"\n data={['Apple', 'Banana', 'Cherry']}\n placeholder=\"Search fruit...\"\n />\n </Control>\n </Field>\n </Field.Body>\n </Field>\n );\n}"
}
],
"accessibility": "- The `label` prop is automatically associated with the inner text input (`htmlFor` plus a generated `id`, or your own `id` if you pass one), so clicking the label focuses the input and assistive technology announces it.\n- A user-supplied `id` is applied to the inner input (the labellable control), not the wrapper div.\n- Uses `role=\"combobox\"` with `aria-expanded`, which is true only while the list is on screen\n- Has `aria-haspopup=\"listbox\"` and `aria-autocomplete=\"list\"`, and, while the list is on screen, `aria-controls` pointing at it\n- Focus stays in the input, which points `aria-activedescendant` at the highlighted option as the arrow keys move it\n- The list is a `role=\"listbox\"` named by the `label` prop's label. Inside an outer `Field`, or with no `label`, it falls back to `aria-label=\"Suggestions\"`\n- Dropdown items use `role=\"option\"` with `aria-selected`\n- Disabled items have `aria-disabled`\n- The `clearable` clear button is a native button named \"Clear\": `Tab` from the input reaches it, and `Enter` or `Space` clears the input and puts focus back in it\n- Full keyboard navigation support",
"accessibility": "- The `label` prop is automatically associated with the inner text input (`htmlFor` plus a generated `id`, or your own `id` if you pass one), so clicking the label focuses the input and assistive technology announces it. Inside a labeled `Field`, that `Field`'s label names the input the same way.\n- A user-supplied `id` is applied to the inner input (the labellable control), not the wrapper div.\n- Uses `role=\"combobox\"` with `aria-expanded`, which is true only while the list is on screen\n- Has `aria-haspopup=\"listbox\"` and `aria-autocomplete=\"list\"`, and, while the list is on screen, `aria-controls` pointing at it\n- Focus stays in the input, which points `aria-activedescendant` at the highlighted option as the arrow keys move it\n- The list is a `role=\"listbox\"` named by the `label` prop's label. Inside an outer `Field`, or with no `label`, it falls back to `aria-label=\"Suggestions\"`\n- Dropdown items use `role=\"option\"` with `aria-selected`\n- Disabled items have `aria-disabled`\n- The `clearable` clear button is a native button named \"Clear\": `Tab` from the input reaches it, and `Enter` or `Space` clears the input and puts focus back in it\n- Full keyboard navigation support",
"related": ["Input", "Select", "Taginput"],
"storybook": "https://bestax.io/storybook/?path=/story/form-autocomplete",
"summary": "The `Autocomplete` component provides an input field with dropdown suggestions that filter based on user input.",
Expand All @@ -71,7 +71,7 @@
"name": "label",
"type": "React.ReactNode",
"default": null,
"description": "Field label. Automatically associated with the text input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Dropped inside an outer `Field` (label that `Field` yourself).",
"description": "Field label. Automatically associated with the text input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`).",
"required": false,
"inherited": false,
"deprecated": false
Expand Down
8 changes: 4 additions & 4 deletions bestax-mcp/data/components/Checkboxes.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@
},
{
"title": "Context-Aware Rendering",
"code": "function example() {\n return (\n <Field horizontal label=\"Chores\">\n <Field.Body>\n <Field>\n <Checkboxes>\n <Checkbox> Make the bed </Checkbox>\n <Checkbox> Brush teeth </Checkbox>\n <Checkbox> Do homework </Checkbox>\n </Checkboxes>\n </Field>\n </Field.Body>\n </Field>\n );\n}"
"code": "function example() {\n return (\n <Field\n horizontal\n label=\"Chores\"\n labelProps={{ id: 'chores-label', htmlFor: undefined }}\n >\n <Field.Body>\n <Field>\n <Checkboxes aria-labelledby=\"chores-label\">\n <Checkbox> Make the bed </Checkbox>\n <Checkbox> Brush teeth </Checkbox>\n <Checkbox> Do homework </Checkbox>\n </Checkboxes>\n </Field>\n </Field.Body>\n </Field>\n );\n}"
},
{
"title": "Context-Aware Rendering",
"code": "function example() {\n return (\n <Field horizontal label=\"Chores\">\n <Field.Body>\n <Field>\n <Control>\n <Checkboxes>\n <Checkbox> Make the bed </Checkbox>\n <Checkbox> Brush teeth </Checkbox>\n <Checkbox> Do homework </Checkbox>\n </Checkboxes>\n </Control>\n </Field>\n </Field.Body>\n </Field>\n );\n}"
"code": "function example() {\n return (\n <Field\n horizontal\n label=\"Chores\"\n labelProps={{ id: 'chores-label-control', htmlFor: undefined }}\n >\n <Field.Body>\n <Field>\n <Control>\n <Checkboxes aria-labelledby=\"chores-label-control\">\n <Checkbox> Make the bed </Checkbox>\n <Checkbox> Brush teeth </Checkbox>\n <Checkbox> Do homework </Checkbox>\n </Checkboxes>\n </Control>\n </Field>\n </Field.Body>\n </Field>\n );\n}"
},
{
"title": "Compound (dot-notation) usage",
"code": "<Checkboxes name=\"frameworks\" label=\"Frameworks\">\n <Checkboxes.Checkbox value=\"react\">React</Checkboxes.Checkbox>\n <Checkboxes.Checkbox value=\"vue\">Vue</Checkboxes.Checkbox>\n</Checkboxes>"
}
],
"accessibility": "- The group is rendered as a `<div class=\"checkboxes\" role=\"group\">` containing labeled checkboxes.\n- The `label` prop names the whole group: the rendered `<label>` gets an id (yours via `labelProps.id`, or a generated one) and the group points at it with `aria-labelledby`.\n- Each child should be a `Checkbox` for proper labeling and accessibility.",
"accessibility": "- The group is rendered as a `<div class=\"checkboxes\" role=\"group\">` containing labeled checkboxes.\n- The `label` prop names the whole group: the rendered `<label>` gets an id (yours via `labelProps.id`, or a generated one) and the group points at it with `aria-labelledby`.\n- Inside a labeled `Field`, that `Field`'s label names the group the same way.\n- An `aria-label` or `aria-labelledby` you give the group wins over either label, whether that label sits on the Checkboxes or on a `Field` around them.\n- Each child should be a `Checkbox` for proper labeling and accessibility.",
"related": ["Checkbox", "Field"],
"storybook": "https://bestax.io/storybook/?path=/story/form-checkboxes--default",
"summary": "The `Checkboxes` component wraps multiple `Checkbox` components in a Bulma-styled group.",
Expand All @@ -43,7 +43,7 @@
"name": "label",
"type": "React.ReactNode",
"default": null,
"description": "Field label naming the whole group. Automatically associated via `aria-labelledby` on the `role=\"group\"` wrapper — uses your `labelProps.id` when provided, otherwise a generated one. Dropped inside an outer `Field` (label that `Field` yourself).",
"description": "Field label naming the whole group. Automatically associated via `aria-labelledby` on the `role=\"group\"` wrapper — uses your `labelProps.id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose own label names the group instead through `aria-labelledby` when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`). An `aria-label` or `aria-labelledby` you set on the group wins over either label, which still renders but no longer names it. An `aria-labelledby` key counts even when undefined, since it is spread over the group's own.",
"required": false,
"inherited": false,
"deprecated": false
Expand Down
6 changes: 3 additions & 3 deletions bestax-mcp/data/components/DateInput.json
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,11 @@
},
{
"title": "Context-Aware Rendering",
"code": "function example() {\n return (\n <Field horizontal label=\"Date\">\n <Field.Body>\n <Field>\n <DateInput placeholder=\"YYYY-MM-DD\" />\n </Field>\n </Field.Body>\n </Field>\n );\n}"
"code": "function example() {\n return (\n <Field horizontal label=\"Date\" labelProps={{ htmlFor: 'date-field' }}>\n <Field.Body>\n <Field>\n <DateInput id=\"date-field\" placeholder=\"YYYY-MM-DD\" />\n </Field>\n </Field.Body>\n </Field>\n );\n}"
},
{
"title": "Context-Aware Rendering",
"code": "function example() {\n return (\n <Field horizontal label=\"Date\">\n <Field.Body>\n <Field>\n <Control iconLeftName=\"calendar-alt\">\n <DateInput placeholder=\"YYYY-MM-DD\" />\n </Control>\n </Field>\n </Field.Body>\n </Field>\n );\n}"
"code": "function example() {\n return (\n <Field\n horizontal\n label=\"Date\"\n labelProps={{ htmlFor: 'date-field-control' }}\n >\n <Field.Body>\n <Field>\n <Control iconLeftName=\"calendar-alt\">\n <DateInput id=\"date-field-control\" placeholder=\"YYYY-MM-DD\" />\n </Control>\n </Field>\n </Field.Body>\n </Field>\n );\n}"
}
],
"accessibility": "- Trigger uses `role=\"combobox\"` with `aria-haspopup=\"dialog\"`, `aria-expanded`, and `aria-controls`.\n- Popover panel has `role=\"dialog\"` with an accessible name. Opening it puts focus on the focused date, month or year.\n- Closing the popover with `Escape` or a pick returns focus to the input, whether the input or the launcher opened it. Under `openOnFocus` that returning focus leaves the popover closed; focusing or clicking the input again opens it. Dismissing without a pick commits nothing: an empty field stays empty, and leaving afterwards commits only what you typed.\n- Calendar uses `role=\"grid\"` with cells as `role=\"gridcell\"`.\n- Cells expose `aria-selected`, `aria-disabled`, and `aria-current=\"date\"` for today.\n- Roving `tabindex` keeps a single grid cell focusable at a time, and focus moves with it, inline as in the popover. When the focused date is disabled, that cell is the nearest enabled day of the month.\n- The month grid is a `role=\"grid\"` of `role=\"row\"`s, labelled by the year in its header. Each month cell carries the full month name as its accessible name, `aria-current=\"date\"` for this month and `aria-disabled` for a month with no selectable day.\n- The year list is a `role=\"listbox\"` named by the `chooseYear` label. As the selection surface its options take `aria-selected` from the value's year rather than from focus, which roves through the list. When the focused year is disabled, the nearest enabled year takes the tab stop, so `Tab` still reaches the list.\n- The launcher and popover are named \"Choose month\" or \"Choose year\" to match the granularity; override them, and the month grid's \"Previous year\" / \"Next year\" buttons, through `labels` (`chooseMonth`, `chooseYear`, `prevYear`, `nextYear`).\n- Honors `prefers-reduced-motion` (skip popover fade-in).",
Expand All @@ -191,7 +191,7 @@
"name": "label",
"type": "React.ReactNode",
"default": null,
"description": "Field label (component auto-wraps in a `Field` if not already inside). Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Not wired in `inline` mode (no visible input to label) and dropped inside an outer `Field`.",
"description": "Field label (component auto-wraps in a `Field` if not already inside). Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Not wired in `inline` mode (no visible input to label). Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`).",
"required": false,
"inherited": false,
"deprecated": false
Expand Down
4 changes: 2 additions & 2 deletions bestax-mcp/data/components/DateRangeInput.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"code": "<Field label=\"Leave\">\n <Control iconLeftName=\"calendar-alt\">\n <DateRangeInput />\n </Control>\n</Field>"
}
],
"accessibility": "- The root is a `role=\"group\"` named by `label` through `aria-labelledby`, since the label names two inputs rather than one.\n- Each input is a `role=\"combobox\"` with `aria-haspopup=\"dialog\"`, `aria-expanded` and `aria-controls`, and its own name: \"Start date\" or \"End date\", from the `labels` keys `rangeStart` and `rangeEnd`. The separator between them is hidden from assistive technology.\n- The popover is a `role=\"dialog\"` named \"Choose date range\" (`labels.chooseDateRange`). Opening it puts focus on the calendar's focused day, and closing it returns focus to the input you were last in, or to the start input.\n- The day grid is `aria-multiselectable`, and its days sit in a `role=\"row\"` per week. Every day of the range is `aria-selected`, both ends included. While the end is still being picked, only the start is: the preview is not a selection.\n- The start and end days are described as \"Start date\" and \"End date\", so moving onto either says which it is. While the end is still being picked, the day the range would end on is described as \"Choose as end date\" (`labels.rangePreviewEnd`).\n- A polite live region in the calendar states the range in words, such as \"Start date: June 10, 2024, End date: June 13, 2024\", and announces each pick. The grid points at it too, so moving into the grid reads the current range.\n- Everything else is the calendar `DateInput` uses: a roving `tabindex`, `aria-disabled` on disabled days and `aria-current=\"date\"` on today.",
"accessibility": "- The root is a `role=\"group\"` named by `label` through `aria-labelledby`, since the label names two inputs rather than one. Inside a labeled `Field`, that `Field`'s label names the group the same way. An `aria-label` or `aria-labelledby` you give the group wins over either label.\n- Each input is a `role=\"combobox\"` with `aria-haspopup=\"dialog\"`, `aria-expanded` and `aria-controls`, and its own name: \"Start date\" or \"End date\", from the `labels` keys `rangeStart` and `rangeEnd`. The separator between them is hidden from assistive technology.\n- The popover is a `role=\"dialog\"` named \"Choose date range\" (`labels.chooseDateRange`). Opening it puts focus on the calendar's focused day, and closing it returns focus to the input you were last in, or to the start input.\n- The day grid is `aria-multiselectable`, and its days sit in a `role=\"row\"` per week. Every day of the range is `aria-selected`, both ends included. While the end is still being picked, only the start is: the preview is not a selection.\n- The start and end days are described as \"Start date\" and \"End date\", so moving onto either says which it is. While the end is still being picked, the day the range would end on is described as \"Choose as end date\" (`labels.rangePreviewEnd`).\n- A polite live region in the calendar states the range in words, such as \"Start date: June 10, 2024, End date: June 13, 2024\", and announces each pick. The grid points at it too, so moving into the grid reads the current range.\n- Everything else is the calendar `DateInput` uses: a roving `tabindex`, `aria-disabled` on disabled days and `aria-current=\"date\"` on today.",
"related": ["DateInput", "DateTimeInput", "Field"],
"storybook": "https://bestax.io/storybook/?path=/story/form-daterangeinput",
"summary": "The `DateRangeInput` component is a form input for a start and end date, picked from one popover calendar or typed into two segmented inputs.",
Expand All @@ -63,7 +63,7 @@
"name": "label",
"type": "React.ReactNode",
"default": null,
"description": "Field label naming the whole range. Associated through `aria-labelledby` on the `role=\"group\"` root, since it names two inputs rather than one; uses your `labelProps.id` when provided, otherwise a generated one. Each input keeps its own name, \"Start date\" or \"End date\" (`labels.rangeStart` / `labels.rangeEnd`). Dropped inside an outer `Field`.",
"description": "Field label naming the whole range. Associated through `aria-labelledby` on the `role=\"group\"` root, since it names two inputs rather than one; uses your `labelProps.id` when provided, otherwise a generated one. Each input keeps its own name, \"Start date\" or \"End date\" (`labels.rangeStart` / `labels.rangeEnd`). Dropped inside an outer `Field`, whose own label names the group instead through `aria-labelledby` when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`). An `aria-label` or `aria-labelledby` you set on the group wins over either label, which still renders but no longer names it. An `aria-labelledby` key counts even when undefined, since it is spread over the group's own.",
"required": false,
"inherited": false,
"deprecated": false
Expand Down
Loading
Loading