bestax-mcp 1.14.1 → 1.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data/catalog.json +11 -11
- package/data/components/Autocomplete.json +4 -4
- package/data/components/Avatars.json +1 -1
- package/data/components/Cell.json +2 -2
- package/data/components/Checkboxes.json +4 -4
- package/data/components/ClientOnly.json +37 -6
- package/data/components/Columns.json +2 -2
- package/data/components/ConfigProvider.json +45 -5
- package/data/components/DateInput.json +3 -3
- package/data/components/DateRangeInput.json +2 -2
- package/data/components/DateTimeInput.json +3 -3
- package/data/components/Dialog.json +1 -1
- package/data/components/Field.json +4 -4
- package/data/components/File.json +4 -4
- package/data/components/Grid.json +1 -1
- package/data/components/Link.json +1 -1
- package/data/components/Notification.json +1 -1
- package/data/components/Numberinput.json +3 -3
- package/data/components/Portal.json +45 -5
- package/data/components/Radios.json +4 -4
- package/data/components/Rate.json +4 -4
- package/data/components/Slider.json +5 -5
- package/data/components/Taginput.json +4 -4
- package/data/components/Theme.json +411 -5
- package/data/components/TimeInput.json +3 -3
- package/data/components/Valid value constants.json +2 -1
- package/data/components/classNames.json +2 -1
- package/data/components/useBulmaClasses.json +2 -1
- package/data/components/useFocusTrap.json +3 -2
- package/data/components/usePrefixedClassNames.json +2 -1
- package/data/skills/bestax-form/SKILL.md +13 -6
- package/data/skills/bestax-form/references/api.md +10 -10
- package/data/skills.json +1 -1
- package/dist/data.d.ts +6 -1
- package/dist/data.d.ts.map +1 -1
- package/dist/format.d.ts +52 -5
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +240 -42
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +8 -8
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +12 -12
- package/package.json +2 -2
package/data/catalog.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"generatedFrom": {
|
|
4
4
|
"package": "@allxsmith/bestax-bulma",
|
|
5
|
-
"version": "5.27.
|
|
5
|
+
"version": "5.27.1"
|
|
6
6
|
},
|
|
7
7
|
"docsBase": "https://bestax.io/docs",
|
|
8
8
|
"categories": [
|
|
@@ -252,7 +252,7 @@
|
|
|
252
252
|
"name": "Cell",
|
|
253
253
|
"kind": "component",
|
|
254
254
|
"category": "grid",
|
|
255
|
-
"purpose": "The `Cell` component provides a single Bulma grid cell for use inside the [`Grid`](
|
|
255
|
+
"purpose": "The `Cell` component provides a single Bulma grid cell for use inside the [`Grid`](https://bestax.io/docs/api/grid) component.",
|
|
256
256
|
"slug": "grid/cell",
|
|
257
257
|
"import": "import { Cell } from '@allxsmith/bestax-bulma';",
|
|
258
258
|
"compound": false,
|
|
@@ -283,13 +283,13 @@
|
|
|
283
283
|
},
|
|
284
284
|
{
|
|
285
285
|
"name": "ClientOnly",
|
|
286
|
-
"kind": "
|
|
286
|
+
"kind": "component",
|
|
287
287
|
"category": "helpers",
|
|
288
288
|
"purpose": "`ClientOnly` renders its children only in the browser, after hydration, and a `fallback` until then, so content that depends on browser-only state doesn't…",
|
|
289
289
|
"slug": "helpers/clientonly",
|
|
290
290
|
"import": "import { ClientOnly, useIsHydrated } from '@allxsmith/bestax-bulma';",
|
|
291
291
|
"compound": false,
|
|
292
|
-
"propCount":
|
|
292
|
+
"propCount": 2,
|
|
293
293
|
"exampleCount": 3
|
|
294
294
|
},
|
|
295
295
|
{
|
|
@@ -340,7 +340,7 @@
|
|
|
340
340
|
"name": "Columns",
|
|
341
341
|
"kind": "component",
|
|
342
342
|
"category": "columns",
|
|
343
|
-
"purpose": "The `Columns` component provides Bulma's flexible, responsive grid container for aligning and distributing [`Column`](
|
|
343
|
+
"purpose": "The `Columns` component provides Bulma's flexible, responsive grid container for aligning and distributing [`Column`](https://bestax.io/docs/api/columns/column) components.",
|
|
344
344
|
"slug": "columns/columns",
|
|
345
345
|
"import": "import { Columns, Column } from '@allxsmith/bestax-bulma';",
|
|
346
346
|
"compound": true,
|
|
@@ -349,13 +349,13 @@
|
|
|
349
349
|
},
|
|
350
350
|
{
|
|
351
351
|
"name": "ConfigProvider",
|
|
352
|
-
"kind": "
|
|
352
|
+
"kind": "component",
|
|
353
353
|
"category": "helpers",
|
|
354
354
|
"purpose": "The `ConfigProvider` component provides a React context for configuring global settings across all Bulma UI components.",
|
|
355
355
|
"slug": "helpers/config",
|
|
356
356
|
"import": "import { ConfigProvider, useConfig } from '@allxsmith/bestax-bulma';",
|
|
357
357
|
"compound": false,
|
|
358
|
-
"propCount":
|
|
358
|
+
"propCount": 3,
|
|
359
359
|
"exampleCount": 0
|
|
360
360
|
},
|
|
361
361
|
{
|
|
@@ -789,13 +789,13 @@
|
|
|
789
789
|
},
|
|
790
790
|
{
|
|
791
791
|
"name": "Portal",
|
|
792
|
-
"kind": "
|
|
792
|
+
"kind": "component",
|
|
793
793
|
"category": "helpers",
|
|
794
794
|
"purpose": "`Portal` renders its children into another part of the page, `document.body` unless `container` says otherwise, so floating content escapes an ancestor's…",
|
|
795
795
|
"slug": "helpers/portal",
|
|
796
796
|
"import": "import { Portal } from '@allxsmith/bestax-bulma';",
|
|
797
797
|
"compound": false,
|
|
798
|
-
"propCount":
|
|
798
|
+
"propCount": 3,
|
|
799
799
|
"exampleCount": 3
|
|
800
800
|
},
|
|
801
801
|
{
|
|
@@ -1042,13 +1042,13 @@
|
|
|
1042
1042
|
},
|
|
1043
1043
|
{
|
|
1044
1044
|
"name": "Theme",
|
|
1045
|
-
"kind": "
|
|
1045
|
+
"kind": "component",
|
|
1046
1046
|
"category": "helpers",
|
|
1047
1047
|
"purpose": "The `Theme` component provides a powerful way to customize Bulma's appearance using CSS custom properties (CSS variables).",
|
|
1048
1048
|
"slug": "helpers/theme",
|
|
1049
1049
|
"import": "import { Theme } from '@allxsmith/bestax-bulma';",
|
|
1050
1050
|
"compound": false,
|
|
1051
|
-
"propCount":
|
|
1051
|
+
"propCount": 43,
|
|
1052
1052
|
"exampleCount": 12
|
|
1053
1053
|
},
|
|
1054
1054
|
{
|
|
@@ -47,14 +47,14 @@
|
|
|
47
47
|
},
|
|
48
48
|
{
|
|
49
49
|
"title": "Context-Aware Rendering",
|
|
50
|
-
"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}"
|
|
50
|
+
"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}"
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
53
|
"title": "Context-Aware Rendering",
|
|
54
|
-
"code": "function example() {\n return (\n <Field
|
|
54
|
+
"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}"
|
|
55
55
|
}
|
|
56
56
|
],
|
|
57
|
-
"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",
|
|
57
|
+
"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",
|
|
58
58
|
"related": ["Input", "Select", "Taginput"],
|
|
59
59
|
"storybook": "https://bestax.io/storybook/?path=/story/form-autocomplete",
|
|
60
60
|
"summary": "The `Autocomplete` component provides an input field with dropdown suggestions that filter based on user input.",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"name": "label",
|
|
72
72
|
"type": "React.ReactNode",
|
|
73
73
|
"default": null,
|
|
74
|
-
"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
|
|
74
|
+
"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`).",
|
|
75
75
|
"required": false,
|
|
76
76
|
"inherited": false,
|
|
77
77
|
"deprecated": false
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"code": "<Avatars>\n <Avatars.Avatar name=\"Ada Lovelace\" />\n <Avatars.Avatar name=\"Grace Hopper\" />\n <Avatars.Avatar name=\"Katherine Johnson\" />\n</Avatars>"
|
|
39
39
|
}
|
|
40
40
|
],
|
|
41
|
-
"accessibility": "- `Avatars` is a plain container — each child `Avatar` carries its own accessible name (see\n [Avatar's accessibility notes](
|
|
41
|
+
"accessibility": "- `Avatars` is a plain container — each child `Avatar` carries its own accessible name (see\n [Avatar's accessibility notes](https://bestax.io/docs/api/components/avatar#accessibility)).\n- The `+N` surplus avatar gets an accessible name of `\"{N} more\"` (via its `alt`), so assistive\n tech announces how many members are hidden. Localize it with `surplusLabel`, e.g.\n ``surplusLabel={count => `${count} weitere`}``.\n- A focused clickable avatar is lifted above its overlapping neighbours so its focus outline\n is never partially covered.\n- When the group represents a labelled set (e.g. \"Project members\"), give the container a\n `role=\"group\"` and an `aria-label` describing it.",
|
|
42
42
|
"related": ["Avatar", "Badge", "Tags", "useBulmaClasses"],
|
|
43
43
|
"storybook": "https://bestax.io/storybook/?path=/story/components-avatars--default",
|
|
44
44
|
"summary": "The `Avatars` component renders an overlapping/stacked group of `Avatar`s, the \"members\" list pattern.",
|
|
@@ -33,14 +33,14 @@
|
|
|
33
33
|
"accessibility": null,
|
|
34
34
|
"related": [],
|
|
35
35
|
"storybook": null,
|
|
36
|
-
"summary": "The `Cell` component provides a single Bulma grid cell for use inside the [`Grid`](
|
|
36
|
+
"summary": "The `Cell` component provides a single Bulma grid cell for use inside the [`Grid`](https://bestax.io/docs/api/grid) component.",
|
|
37
37
|
"import": "import { Cell } from '@allxsmith/bestax-bulma';",
|
|
38
38
|
"sourceFile": "bulma-ui/src/grid/Cell.tsx",
|
|
39
39
|
"rootClass": "cell",
|
|
40
40
|
"parts": [
|
|
41
41
|
{
|
|
42
42
|
"path": "Cell",
|
|
43
|
-
"summary": "The `Cell` component provides a single Bulma grid cell for use inside the [`Grid`](
|
|
43
|
+
"summary": "The `Cell` component provides a single Bulma grid cell for use inside the [`Grid`](https://bestax.io/docs/api/grid) component.",
|
|
44
44
|
"component": null,
|
|
45
45
|
"props": [
|
|
46
46
|
{
|
|
@@ -15,18 +15,18 @@
|
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
17
|
"title": "Context-Aware Rendering",
|
|
18
|
-
"code": "function example() {\n return (\n <Field
|
|
18
|
+
"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}"
|
|
19
19
|
},
|
|
20
20
|
{
|
|
21
21
|
"title": "Context-Aware Rendering",
|
|
22
|
-
"code": "function example() {\n return (\n <Field
|
|
22
|
+
"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}"
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
"title": "Compound (dot-notation) usage",
|
|
26
26
|
"code": "<Checkboxes name=\"frameworks\" label=\"Frameworks\">\n <Checkboxes.Checkbox value=\"react\">React</Checkboxes.Checkbox>\n <Checkboxes.Checkbox value=\"vue\">Vue</Checkboxes.Checkbox>\n</Checkboxes>"
|
|
27
27
|
}
|
|
28
28
|
],
|
|
29
|
-
"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.",
|
|
29
|
+
"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.",
|
|
30
30
|
"related": ["Checkbox", "Field"],
|
|
31
31
|
"storybook": "https://bestax.io/storybook/?path=/story/form-checkboxes--default",
|
|
32
32
|
"summary": "The `Checkboxes` component wraps multiple `Checkbox` components in a Bulma-styled group.",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"name": "label",
|
|
44
44
|
"type": "React.ReactNode",
|
|
45
45
|
"default": null,
|
|
46
|
-
"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
|
|
46
|
+
"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.",
|
|
47
47
|
"required": false,
|
|
48
48
|
"inherited": false,
|
|
49
49
|
"deprecated": false
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ClientOnly",
|
|
3
|
-
"kind": "
|
|
3
|
+
"kind": "component",
|
|
4
4
|
"category": "helpers",
|
|
5
5
|
"slug": "helpers/clientonly",
|
|
6
6
|
"docsUrl": "https://bestax.io/docs/api/helpers/clientonly",
|
|
@@ -18,12 +18,43 @@
|
|
|
18
18
|
"code": "<ClientOnly fallback={<Skeleton variant=\"lines\" lines={3} />}>\n {() => <RecentlyViewed items={readHistory(localStorage)} />}\n</ClientOnly>"
|
|
19
19
|
}
|
|
20
20
|
],
|
|
21
|
-
"accessibility": "- Content that arrives after hydration is not announced by screen readers on its own. Keep what a reader needs on first load out of `ClientOnly`, and use it for enhancements.\n- Match the fallback's size to the content, so the page doesn't shift under someone who has started reading or scrolling.\n- Assistive technology meets the fallback until it is replaced. An empty [`Skeleton`](
|
|
21
|
+
"accessibility": "- Content that arrives after hydration is not announced by screen readers on its own. Keep what a reader needs on first load out of `ClientOnly`, and use it for enhancements.\n- Match the fallback's size to the content, so the page doesn't shift under someone who has started reading or scrolling.\n- Assistive technology meets the fallback until it is replaced. An empty [`Skeleton`](https://bestax.io/docs/api/elements/skeleton) gives it nothing to read; a text fallback such as \"Loading…\" is read out.",
|
|
22
22
|
"related": ["Modal", "Reveal", "Skeleton"],
|
|
23
23
|
"storybook": "https://bestax.io/storybook/?path=/story/helpers-clientonly--default",
|
|
24
|
-
"summary": "
|
|
24
|
+
"summary": "Renders its children only in the browser, after hydration, and a `fallback` until then, so content that depends on browser-only state doesn't cause a hydration mismatch. The server render and the hydrating client render both show `fallback`, which keeps them identical; the children replace it in the commit that follows. In an app without server rendering the children show on the first render.",
|
|
25
25
|
"import": "import { ClientOnly, useIsHydrated } from '@allxsmith/bestax-bulma';",
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
26
|
+
"sourceFile": "bulma-ui/src/helpers/ClientOnly.tsx",
|
|
27
|
+
"rootClass": null,
|
|
28
|
+
"parts": [
|
|
29
|
+
{
|
|
30
|
+
"path": "ClientOnly",
|
|
31
|
+
"summary": "Renders its children only in the browser, after hydration, and a `fallback` until then, so content that depends on browser-only state doesn't cause a hydration mismatch. The server render and the hydrating client render both show `fallback`, which keeps them identical; the children replace it in the commit that follows. In an app without server rendering the children show on the first render.",
|
|
32
|
+
"component": null,
|
|
33
|
+
"props": [
|
|
34
|
+
{
|
|
35
|
+
"name": "children",
|
|
36
|
+
"type": "React.ReactNode | (() => React.ReactNode)",
|
|
37
|
+
"default": null,
|
|
38
|
+
"description": "Content to render once the page has hydrated. A function is called only then, so an inline expression that reads `window`, `document` or `localStorage` never runs on the server.",
|
|
39
|
+
"required": false,
|
|
40
|
+
"inherited": false,
|
|
41
|
+
"deprecated": false
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "fallback",
|
|
45
|
+
"type": "React.ReactNode",
|
|
46
|
+
"default": "null",
|
|
47
|
+
"description": "Rendered on the server and during hydration instead of `children`, such as a placeholder the same size as the content so the layout doesn't shift when it arrives.",
|
|
48
|
+
"required": false,
|
|
49
|
+
"inherited": false,
|
|
50
|
+
"deprecated": false
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"extraProps": [],
|
|
54
|
+
"catchAll": null,
|
|
55
|
+
"types": []
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
"cssVars": [],
|
|
59
|
+
"doc": "# ClientOnly\n\n## Overview\n\n`ClientOnly` renders its children only in the browser, after hydration, and a `fallback` until then, so content that depends on browser-only state doesn't cause a hydration mismatch.\n\nThe server render and the hydrating client render both show `fallback`, which keeps them identical; the children replace it in the commit that follows. Reach for it when the markup itself would differ between server and browser: the reader's time zone or locale, a value from `localStorage`, the viewport size, a widget that needs `window` to render at all. In an app without server rendering the children show on the first render, so wrapping something in `ClientOnly` costs nothing there.\n\nThe hook underneath, `useIsHydrated`, is exported too, for components that need the answer rather than a wrapper.\n\n---\n\n## Import\n\n```tsx\nimport { ClientOnly, useIsHydrated } from '@allxsmith/bestax-bulma';\n```\n\n---\n\n## Hooks\n\n### useIsHydrated\n\nReturns `false` during server rendering and during the hydrating client render, then `true` from the commit that follows. A component that mounts after hydration (after a route change, or in an app with no server rendering) gets `true` on its first render, so it pays for no extra render.\n\n```tsx\nfunction Greeting() {\n const hydrated = useIsHydrated();\n // localStorage only exists in the browser, so the server render and the\n // hydrating render both show the generic greeting.\n const name = hydrated ? localStorage.getItem('name') : null;\n return <Title size=\"4\">{name ? `Welcome back, ${name}` : 'Welcome'}</Title>;\n}\n```\n\n---\n\n## Usage\n\n### Browser-only content\n\nPass the content as a function and it is called only after hydration, so an expression that reads `window`, `document` or `Intl` state never runs on the server. Plain children work too, but JSX children are evaluated by the component that renders `ClientOnly`, on the server included; a function is what keeps a browser-only expression off the server.\n\n```tsx live\n<ClientOnly fallback={<Skeleton variant=\"lines\" lines={1} />}>\n {() => (\n <Notification color=\"info\">\n Times are shown in{' '}\n <strong>{Intl.DateTimeFormat().resolvedOptions().timeZone}</strong>.\n </Notification>\n )}\n</ClientOnly>\n```\n\n### A component that needs the browser\n\nA component's own render is deferred along with it, so a component child works without the function form.\n\n```tsx\n<ClientOnly fallback={<Skeleton variant=\"block\" />}>\n <MapWidget center={office} />\n</ClientOnly>\n```\n\n### A fallback that holds the layout\n\nWithout a `fallback` nothing renders until hydration, and the content pushes the page down when it arrives. A placeholder of the same size, such as a [`Skeleton`](https://bestax.io/docs/api/elements/skeleton), avoids the jump.\n\n```tsx\n<ClientOnly fallback={<Skeleton variant=\"lines\" lines={3} />}>\n {() => <RecentlyViewed items={readHistory(localStorage)} />}\n</ClientOnly>\n```\n\n---\n\n## Accessibility\n\n- Content that arrives after hydration is not announced by screen readers on its own. Keep what a reader needs on first load out of `ClientOnly`, and use it for enhancements.\n- Match the fallback's size to the content, so the page doesn't shift under someone who has started reading or scrolling.\n- Assistive technology meets the fallback until it is replaced. An empty [`Skeleton`](https://bestax.io/docs/api/elements/skeleton) gives it nothing to read; a text fallback such as \"Loading…\" is read out.\n\n---\n\n## Related Components\n\n- [`Modal`](https://bestax.io/docs/api/components/modal): Its `portal` prop follows the same rule, rendering inline until the page has hydrated.\n- [`Skeleton`](https://bestax.io/docs/api/elements/skeleton): A placeholder to pass as `fallback`.\n- [`Reveal`](https://bestax.io/docs/api/components/reveal): Renders its final state on the server and animates only in the browser.\n\n---\n\n## Additional Resources\n\n- [Storybook: ClientOnly Stories](https://bestax.io/storybook/?path=/story/helpers-clientonly--default)\n- [React: hydration mismatches](https://react.dev/reference/react-dom/client/hydrateRoot#handling-different-client-and-server-content)\n\n---\n\n## Props\n\n| Prop | Type | Default | Description |\n| ---------- | -------------------------------- | ------- | -------------------------------------------------------------------------------------------------------- |\n| `children` | `ReactNode` \\| `() => ReactNode` | — | Content to render once hydrated. A function is called only then, never on the server. |\n| `fallback` | `ReactNode` | `null` | Rendered on the server and during hydration instead, such as a placeholder the same size as the content. |"
|
|
29
60
|
}
|
|
@@ -73,14 +73,14 @@
|
|
|
73
73
|
"accessibility": null,
|
|
74
74
|
"related": [],
|
|
75
75
|
"storybook": null,
|
|
76
|
-
"summary": "The `Columns` component provides Bulma's flexible, responsive grid container for aligning and distributing [`Column`](
|
|
76
|
+
"summary": "The `Columns` component provides Bulma's flexible, responsive grid container for aligning and distributing [`Column`](https://bestax.io/docs/api/columns/column) components.",
|
|
77
77
|
"import": "import { Columns, Column } from '@allxsmith/bestax-bulma';",
|
|
78
78
|
"sourceFile": "bulma-ui/src/columns/Columns.tsx",
|
|
79
79
|
"rootClass": "columns",
|
|
80
80
|
"parts": [
|
|
81
81
|
{
|
|
82
82
|
"path": "Columns",
|
|
83
|
-
"summary": "The `Columns` component provides Bulma's flexible, responsive grid container for aligning and distributing [`Column`](
|
|
83
|
+
"summary": "The `Columns` component provides Bulma's flexible, responsive grid container for aligning and distributing [`Column`](https://bestax.io/docs/api/columns/column) components.",
|
|
84
84
|
"component": null,
|
|
85
85
|
"props": [
|
|
86
86
|
{
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ConfigProvider",
|
|
3
|
-
"kind": "
|
|
3
|
+
"kind": "component",
|
|
4
4
|
"category": "helpers",
|
|
5
5
|
"slug": "helpers/config",
|
|
6
6
|
"docsUrl": "https://bestax.io/docs/api/helpers/config",
|
|
@@ -8,9 +8,49 @@
|
|
|
8
8
|
"accessibility": null,
|
|
9
9
|
"related": [],
|
|
10
10
|
"storybook": null,
|
|
11
|
-
"summary": "
|
|
11
|
+
"summary": "ConfigProvider injects configuration into all child components via React context.",
|
|
12
12
|
"import": "import { ConfigProvider, useConfig } from '@allxsmith/bestax-bulma';",
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
13
|
+
"sourceFile": "bulma-ui/src/helpers/Config.tsx",
|
|
14
|
+
"rootClass": null,
|
|
15
|
+
"parts": [
|
|
16
|
+
{
|
|
17
|
+
"path": "ConfigProvider",
|
|
18
|
+
"summary": "ConfigProvider injects configuration into all child components via React context.",
|
|
19
|
+
"component": null,
|
|
20
|
+
"props": [
|
|
21
|
+
{
|
|
22
|
+
"name": "children",
|
|
23
|
+
"type": "ReactNode",
|
|
24
|
+
"default": null,
|
|
25
|
+
"description": "Child components to receive configuration.",
|
|
26
|
+
"required": false,
|
|
27
|
+
"inherited": false,
|
|
28
|
+
"deprecated": false
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"name": "classPrefix",
|
|
32
|
+
"type": "string",
|
|
33
|
+
"default": null,
|
|
34
|
+
"description": "Prefix applied to all Bulma class names.",
|
|
35
|
+
"required": false,
|
|
36
|
+
"inherited": false,
|
|
37
|
+
"deprecated": false
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "iconLibrary",
|
|
41
|
+
"type": "'fa' | 'mdi' | 'ion' | 'material-icons' | 'material-symbols'",
|
|
42
|
+
"default": null,
|
|
43
|
+
"description": "Default icon library for Icon components.",
|
|
44
|
+
"required": false,
|
|
45
|
+
"inherited": false,
|
|
46
|
+
"deprecated": false
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
"extraProps": [],
|
|
50
|
+
"catchAll": null,
|
|
51
|
+
"types": []
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
"cssVars": [],
|
|
55
|
+
"doc": "# ConfigProvider\n\n## Overview\n\nThe `ConfigProvider` component provides a React context for configuring global settings across all Bulma UI components. Currently, it supports setting a `classPrefix` that will be automatically applied to **all Bulma CSS classes**, including both main component classes (like `button`, `box`, `title`) and helper/modifier classes (like `is-primary`, `has-text-centered`, `m-4`), allowing you to namespace Bulma classes to avoid conflicts with other CSS frameworks or customize the class naming convention.\n\n---\n\n## Import\n\n```tsx\nimport { ConfigProvider, useConfig } from '@allxsmith/bestax-bulma';\n```\n\n---\n\n## Hooks\n\n### useConfig\n\nReturns the current configuration context values.\n\n```tsx\nconst { classPrefix } = useConfig();\n```\n\n### useClassPrefix\n\nConvenience hook that returns just the classPrefix string (or empty string if not set).\n\n```tsx\nconst classPrefix = useClassPrefix();\n```\n\n---\n\n## Usage Examples\n\n### Basic Usage with Class Prefix\n\nUse `ConfigProvider` to add a prefix to all Bulma CSS classes within its scope:\n\n```tsx\nimport {\n ConfigProvider,\n Box,\n Title,\n Button,\n Notification,\n} from '@allxsmith/bestax-bulma';\n\nfunction App() {\n return (\n <div>\n <Title size=\"3\">Prefixed Bulma Components</Title>\n <p>\n This demonstrates using ConfigProvider with{' '}\n <code>classPrefix=\"bestax-\"</code> to add the \"bestax-\" prefix to all\n component CSS classes. This is useful when integrating Bulma with other\n CSS frameworks or when you need to namespace Bulma classes to avoid\n conflicts.\n </p>\n\n <Notification color=\"info\" mt=\"4\">\n <strong>Tip:</strong> Open your browser's developer tools and inspect\n the DOM elements below. You'll see that all Bulma CSS classes have the\n \"bestax-\" prefix applied.\n </Notification>\n\n <ConfigProvider classPrefix=\"bestax-\">\n <Box mt=\"4\" p=\"4\">\n {/* \n This Box will have classes:\n - bestax-box (main class)\n - bestax-mt-4 (helper class)\n - bestax-p-4 (helper class)\n */}\n <Title size=\"4\">Prefixed Components</Title>\n {/* \n This Title will have classes:\n - bestax-title (main class)\n - bestax-is-4 (modifier class)\n */}\n <p>\n All components inside this ConfigProvider will have their CSS\n classes prefixed with \"bestax-\". This allows you to use Bulma\n alongside other CSS frameworks without class name conflicts.\n </p>\n <Button color=\"primary\" mt=\"3\" isRounded>\n {/* \n This Button will have classes:\n - bestax-button (main class)\n - bestax-is-primary (modifier class)\n - bestax-is-rounded (modifier class)\n - bestax-mt-3 (helper class)\n */}\n Bulma-Prefixed Button\n </Button>\n </Box>\n </ConfigProvider>\n\n <Box mt=\"4\" p=\"4\">\n <Title size=\"4\">Standard Components (No Prefix)</Title>\n <p>\n Components outside the ConfigProvider use standard Bulma classes\n without any prefix.\n </p>\n <Button color=\"info\">Standard Button</Button>\n </Box>\n </div>\n );\n}\n```\n\n### Nested ConfigProviders\n\nConfigProviders can be nested, with inner providers overriding outer settings:\n\n```tsx\nfunction NestedExample() {\n return (\n <ConfigProvider classPrefix=\"outer-\">\n <Box p=\"4\">\n <Title>Outer Prefix (outer-)</Title>\n\n <ConfigProvider classPrefix=\"inner-\">\n <Box p=\"4\" mt=\"3\">\n <Title>Inner Prefix (inner-)</Title>\n <Button color=\"primary\">Inner Button</Button>\n </Box>\n </ConfigProvider>\n\n <Button color=\"info\" mt=\"3\">\n Outer Button\n </Button>\n </Box>\n </ConfigProvider>\n );\n}\n```\n\n### Using Configuration in Custom Components\n\nAccess the configuration in your own components using the `useConfig` hook:\n\n```tsx\nimport { useConfig } from '@allxsmith/bestax-bulma';\n\nfunction CustomComponent() {\n const { classPrefix } = useConfig();\n const className = classPrefix\n ? `${classPrefix}custom-component`\n : 'custom-component';\n\n return (\n <div className={className}>\n My custom component with prefix: {classPrefix || 'none'}\n </div>\n );\n}\n```\n\n---\n\n## Use Cases\n\n### Framework Integration\n\nWhen integrating Bulma with other CSS frameworks like Bootstrap or Tailwind CSS:\n\n```tsx\n<ConfigProvider classPrefix=\"bestax-\">\n <App />\n</ConfigProvider>\n```\n\nThis ensures all Bulma classes are prefixed with `bestax-`, preventing conflicts with other framework classes.\n\n### Multi-tenant Applications\n\nFor applications that need to support different styling themes or brands:\n\n```tsx\n<ConfigProvider classPrefix={`${tenantName}-`}>\n <TenantApp />\n</ConfigProvider>\n```\n\n### Component Library Wrapping\n\nWhen wrapping Bulma UI components in your own component library:\n\n```tsx\n<ConfigProvider classPrefix=\"mylib-\">\n <MyComponentLibrary />\n</ConfigProvider>\n```\n\n---\n\n## Notes\n\n- The `classPrefix` is applied to **all Bulma classes**:\n - Main component classes (e.g., `button` → `bestax-button`, `box` → `bestax-box`)\n - Helper/modifier classes (e.g., `is-primary` → `bestax-is-primary`, `has-text-centered` → `bestax-has-text-centered`)\n - Spacing classes (e.g., `m-4` → `bestax-m-4`, `p-2` → `bestax-p-2`)\n - All other Bulma utility classes\n- Changes to the `classPrefix` will affect all child components immediately\n- If no `classPrefix` is provided, components use standard Bulma class names\n- The ConfigProvider must wrap all components that should inherit the configuration\n\n---\n\n## TypeScript Support\n\nFull TypeScript support is included:\n\n```tsx\ninterface ConfigContextProps {\n classPrefix?: string;\n iconLibrary?: 'fa' | 'mdi' | 'ion' | 'material-icons' | 'material-symbols';\n}\n\ninterface ConfigProviderProps {\n children: ReactNode;\n classPrefix?: string;\n iconLibrary?: 'fa' | 'mdi' | 'ion' | 'material-icons' | 'material-symbols';\n}\n```\n\n---\n\n## Props\n\n| Prop | Type | Description |\n| ------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------- |\n| `children` | `ReactNode` | The child components that will inherit the configuration settings. |\n| `classPrefix` | `string` | Optional prefix to add to all Bulma CSS classes. Useful for namespacing when integrating with other frameworks. |\n| `iconLibrary` | `'fa' \\| 'mdi' \\| 'ion' \\| 'material-icons' \\| 'material-symbols'` | Default icon library for all child components. |"
|
|
16
56
|
}
|
|
@@ -167,11 +167,11 @@
|
|
|
167
167
|
},
|
|
168
168
|
{
|
|
169
169
|
"title": "Context-Aware Rendering",
|
|
170
|
-
"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}"
|
|
170
|
+
"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}"
|
|
171
171
|
},
|
|
172
172
|
{
|
|
173
173
|
"title": "Context-Aware Rendering",
|
|
174
|
-
"code": "function example() {\n return (\n <Field
|
|
174
|
+
"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}"
|
|
175
175
|
}
|
|
176
176
|
],
|
|
177
177
|
"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).",
|
|
@@ -191,7 +191,7 @@
|
|
|
191
191
|
"name": "label",
|
|
192
192
|
"type": "React.ReactNode",
|
|
193
193
|
"default": null,
|
|
194
|
-
"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)
|
|
194
|
+
"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`).",
|
|
195
195
|
"required": false,
|
|
196
196
|
"inherited": false,
|
|
197
197
|
"deprecated": false
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"code": "<Field label=\"Leave\">\n <Control iconLeftName=\"calendar-alt\">\n <DateRangeInput />\n </Control>\n</Field>"
|
|
47
47
|
}
|
|
48
48
|
],
|
|
49
|
-
"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.",
|
|
49
|
+
"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.",
|
|
50
50
|
"related": ["DateInput", "DateTimeInput", "Field"],
|
|
51
51
|
"storybook": "https://bestax.io/storybook/?path=/story/form-daterangeinput",
|
|
52
52
|
"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.",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"name": "label",
|
|
64
64
|
"type": "React.ReactNode",
|
|
65
65
|
"default": null,
|
|
66
|
-
"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
|
|
66
|
+
"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.",
|
|
67
67
|
"required": false,
|
|
68
68
|
"inherited": false,
|
|
69
69
|
"deprecated": false
|
|
@@ -143,11 +143,11 @@
|
|
|
143
143
|
},
|
|
144
144
|
{
|
|
145
145
|
"title": "Context-Aware Rendering",
|
|
146
|
-
"code": "function example() {\n return (\n <Field horizontal label=\"When\">\n <Field.Body>\n <Field>\n <DateTimeInput placeholder=\"YYYY-MM-DD HH:MM\" />\n </Field>\n </Field.Body>\n </Field>\n );\n}"
|
|
146
|
+
"code": "function example() {\n return (\n <Field horizontal label=\"When\" labelProps={{ htmlFor: 'when-field' }}>\n <Field.Body>\n <Field>\n <DateTimeInput id=\"when-field\" placeholder=\"YYYY-MM-DD HH:MM\" />\n </Field>\n </Field.Body>\n </Field>\n );\n}"
|
|
147
147
|
},
|
|
148
148
|
{
|
|
149
149
|
"title": "Context-Aware Rendering",
|
|
150
|
-
"code": "function example() {\n return (\n <Field
|
|
150
|
+
"code": "function example() {\n return (\n <Field\n horizontal\n label=\"When\"\n labelProps={{ htmlFor: 'when-field-control' }}\n >\n <Field.Body>\n <Field>\n <Control iconLeftName=\"calendar-alt\">\n <DateTimeInput\n id=\"when-field-control\"\n placeholder=\"YYYY-MM-DD HH:MM\"\n />\n </Control>\n </Field>\n </Field.Body>\n </Field>\n );\n}"
|
|
151
151
|
},
|
|
152
152
|
{
|
|
153
153
|
"title": "Manual Keyboard Entry",
|
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
"name": "label",
|
|
188
188
|
"type": "React.ReactNode",
|
|
189
189
|
"default": null,
|
|
190
|
-
"description": "Field label. 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)
|
|
190
|
+
"description": "Field label. 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`).",
|
|
191
191
|
"required": false,
|
|
192
192
|
"inherited": false,
|
|
193
193
|
"deprecated": false
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"code": "function example() {\n const [showDialog, setShowDialog] = useState(false);\n return (\n <Block>\n <Button onClick={() => setShowDialog(true)}>Show Portaled Dialog</Button>\n <Dialog\n isOpen={showDialog}\n title=\"Rendered in document.body\"\n message=\"This dialog is portaled, so it escapes any ancestor with overflow: hidden.\"\n onConfirm={() => setShowDialog(false)}\n showCancel={false}\n portal\n />\n </Block>\n );\n}"
|
|
31
31
|
}
|
|
32
32
|
],
|
|
33
|
-
"accessibility": "- Uses `role=\"alertdialog\"` for proper screen reader announcement\n- Has `aria-modal=\"true\"` to indicate modal behavior — note this does not make background content inert; no `inert` attribute is applied, so background content stays reachable by pointer\n- `title` is wired up as `aria-labelledby` and `message` as `aria-describedby`\n- Focus moves to the confirm (or cancel, with `focusCancel`) button when opened\n- Escape key closes the dialog (when `canCancel` is true) — handled by the underlying [`Modal`](
|
|
33
|
+
"accessibility": "- Uses `role=\"alertdialog\"` for proper screen reader announcement\n- Has `aria-modal=\"true\"` to indicate modal behavior — note this does not make background content inert; no `inert` attribute is applied, so background content stays reachable by pointer\n- `title` is wired up as `aria-labelledby` and `message` as `aria-describedby`\n- Focus moves to the confirm (or cancel, with `focusCancel`) button when opened\n- Escape key closes the dialog (when `canCancel` is true) — handled by the underlying [`Modal`](https://bestax.io/docs/api/components/modal), which routes it to the topmost open modal only\n- Tab and Shift+Tab cycle within the dialog while it is open — also from the underlying [`Modal`](https://bestax.io/docs/api/components/modal)\n- Body scroll is prevented when dialog is open, through the ref-counted lock shared with `Modal`, `Sidebar` and `Loading`\n- Confirm/cancel buttons are keyboard accessible",
|
|
34
34
|
"related": ["Modal", "Toast"],
|
|
35
35
|
"storybook": "https://bestax.io/storybook/?path=/story/components-dialog",
|
|
36
36
|
"summary": "The `Dialog` component provides ready-made confirm and alert dialogs, so a destructive action stays one `await dialog.confirm()` call away.",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
},
|
|
20
20
|
{
|
|
21
21
|
"title": "With File",
|
|
22
|
-
"code": "<Field label=\"Upload Resume\">\n <File
|
|
22
|
+
"code": "<Field label=\"Upload Resume\">\n <File buttonLabel=\"Choose a file...\" />\n</Field>"
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
"title": "With Input (Default)",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"code": "<Field horizontal>\n <Field.Label>Name</Field.Label>\n <Field.Body>\n <Field.Control>\n <Input placeholder=\"Jane Doe\" />\n </Field.Control>\n </Field.Body>\n</Field>"
|
|
87
87
|
}
|
|
88
88
|
],
|
|
89
|
-
"accessibility": "- The `label` prop
|
|
89
|
+
"accessibility": "- The `label` prop names the one control the Field holds. A composed `InputBase`, `SelectBase`, or `TextAreaBase`, or a bestax input that renders a single input of its own (`Input`, `Select`, `TextArea`, `Numberinput`, `Slider`, `DateInput`, `TimeInput`, `DateTimeInput`, `Autocomplete`, `Taginput`, `File`), adopts a generated id the label's `for` points at, so clicking the label focuses the control and assistive technology announces it.\n- A group (`Radios`, `Checkboxes`, `Rate`, `DateRangeInput`) can't take a `for`, so the label gets an id (yours from `labelProps.id`, otherwise a generated one) and the group points `aria-labelledby` at it. An `aria-label` or `aria-labelledby` you set on the group wins over the Field's label, as it does over a group's own `label`.\n- An `id` you set on the control wins too: it keeps that id, and the label then names it only if you point `labelProps={{ htmlFor }}` at it. Pass `labelProps={{ htmlFor: undefined }}` to opt out of the association entirely.\n- Association is skipped for `grouped`/`hasAddons` fields (they hold several controls), and a `Field` nested inside a labeled one starts its own scope. A horizontal Field wraps its children in a `Field.Body` of its own and keeps the association, but the pattern with an inner `Field` in that body needs it wired by hand.\n- Two controls in one plain labeled Field would both adopt its id. Give each an `id` of its own and label it individually.\n- A labeled Field whose content takes no `for`, a group included, renders its `for` unmatched. `Checkbox`, `Radio` and `Switch` take nothing from the label at all: each is named by its own children, so put the text there rather than in the Field's `label`. Where you point content at the label by hand, as with a group in an inner `Field`, pass `labelProps={{ id, htmlFor: undefined }}` so the label keeps its id and drops the `for`.\n- Grouped/horizontal layouts use Bulma’s grid for layout.\n- Always use the `label` prop or a custom label for clarity.",
|
|
90
90
|
"related": [
|
|
91
91
|
"Checkbox",
|
|
92
92
|
"Checkboxes",
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
"name": "label",
|
|
150
150
|
"type": "React.ReactNode",
|
|
151
151
|
"default": null,
|
|
152
|
-
"description": "Field label, rendered above the widget. Automatically
|
|
152
|
+
"description": "Field label, rendered above the widget. Automatically names the one control the Field holds: a composed `InputBase`, `SelectBase` or `TextAreaBase`, or a bestax input that renders a single input of its own (`Input`, `Select`, `TextArea`, `Numberinput`, `Slider`, `DateInput`, `TimeInput`, `DateTimeInput`, `Autocomplete`, `Taginput`, `File`), adopts a generated id that the label's `htmlFor` points at, and a group (`Radios`, `Checkboxes`, `Rate`, `DateRangeInput`) points `aria-labelledby` at the label's own id unless you gave the group an `aria-label` or `aria-labelledby`. Nothing else takes the label: `Checkbox`, `Radio` and `Switch` are named by their own children. Only the single inputs take the `htmlFor`, so with a group or any other content it matches nothing. Pass `labelProps={{ htmlFor }}` to wire your own `id`, or `labelProps={{ htmlFor: undefined }}` to opt out. Skipped for `grouped`/`hasAddons` fields (multiple controls), and a nested `Field` starts its own scope, so a horizontal Field whose body holds an inner `Field` names the control there only when you wire it. Two controls in one plain labeled Field would both adopt the id, so give each an `id` of its own.",
|
|
153
153
|
"required": false,
|
|
154
154
|
"inherited": false,
|
|
155
155
|
"deprecated": false
|
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
"name": "labelProps",
|
|
168
168
|
"type": "React.LabelHTMLAttributes<HTMLLabelElement> & { [key: string]: unknown; }",
|
|
169
169
|
"default": null,
|
|
170
|
-
"description": "Props for the label element. An explicit `htmlFor` key — even set to `undefined` — takes over the association.",
|
|
170
|
+
"description": "Props for the label element. An explicit `htmlFor` key — even set to `undefined` — takes over the association. An `id` here is the one a group control's `aria-labelledby` points at; otherwise the label gets a generated one while the association is on. To point a group in an inner `Field` at this label by hand, pass that `id` with `htmlFor: undefined`, or the label keeps a generated `htmlFor` that nothing takes.",
|
|
171
171
|
"required": false,
|
|
172
172
|
"inherited": false,
|
|
173
173
|
"deprecated": false
|
|
@@ -67,14 +67,14 @@
|
|
|
67
67
|
},
|
|
68
68
|
{
|
|
69
69
|
"title": "Context-Aware Rendering",
|
|
70
|
-
"code": "function example() {\n return (\n <Field
|
|
70
|
+
"code": "function example() {\n return (\n <Field\n horizontal\n label=\"Document\"\n labelProps={{ htmlFor: 'document-field' }}\n >\n <Field.Body>\n <Field>\n <File\n id=\"document-field\"\n buttonLabel=\"Choose a file…\"\n iconLeft={<Icon name=\"upload\" aria-hidden=\"true\" />}\n />\n </Field>\n </Field.Body>\n </Field>\n );\n}"
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
73
|
"title": "Context-Aware Rendering",
|
|
74
|
-
"code": "function example() {\n return (\n <Field
|
|
74
|
+
"code": "function example() {\n return (\n <Field\n horizontal\n label=\"Document\"\n labelProps={{ htmlFor: 'document-field-control' }}\n >\n <Field.Body>\n <Field>\n <Control iconLeftName=\"paperclip\">\n <File\n id=\"document-field-control\"\n buttonLabel=\"Choose a file…\"\n iconLeft={<Icon name=\"upload\" aria-hidden=\"true\" />}\n />\n </Control>\n </Field>\n </Field.Body>\n </Field>\n );\n}"
|
|
75
75
|
}
|
|
76
76
|
],
|
|
77
|
-
"accessibility": "- The root is a `<div class=\"file\">` with a nested `<label>` and `<input type=\"file\">`.\n- The label is always clickable.\n- The focus ring shows for keyboard focus only, drawn inside the CTA in Bulma's focus color, width and style (`--bulma-focus-h`, `--bulma-focus-s`, `--bulma-focus-l`, `--bulma-focus-width`, `--bulma-focus-style`). On a colored `File` it takes the CTA's text color instead, so it shows against the fill. It comes from the bestax extras (`extras.css`, or `bestax.css`, which includes them); with Bulma's CSS alone the input shows no focus ring.\n- When `File` renders its own `Field` (that is, outside an existing one), the Field-level `label` prop is automatically associated with the file input via `htmlFor`, so the input then has two labels (the Field label plus the wrapping CTA label); assistive technology reads both. An explicit `labelProps.htmlFor` overrides the association and no id is generated.\n- The name area sits inside the CTA's label, so with `hasName` its text joins the input's accessible name (\"Choose a file… resume.pdf\"). Browsers can also expose a picked file on the input itself, so a screen reader may read the name twice. It stays in the label because text you pass in `fileName`, such as a file uploaded earlier, reaches assistive technology only from there.\n- Add `aria-label` to the `<input>` for accessibility if your label is not plain text.",
|
|
77
|
+
"accessibility": "- The root is a `<div class=\"file\">` with a nested `<label>` and `<input type=\"file\">`.\n- The label is always clickable.\n- The focus ring shows for keyboard focus only, drawn inside the CTA in Bulma's focus color, width and style (`--bulma-focus-h`, `--bulma-focus-s`, `--bulma-focus-l`, `--bulma-focus-width`, `--bulma-focus-style`). On a colored `File` it takes the CTA's text color instead, so it shows against the fill. It comes from the bestax extras (`extras.css`, or `bestax.css`, which includes them); with Bulma's CSS alone the input shows no focus ring.\n- When `File` renders its own `Field` (that is, outside an existing one), the Field-level `label` prop is automatically associated with the file input via `htmlFor`, so the input then has two labels (the Field label plus the wrapping CTA label); assistive technology reads both. An explicit `labelProps.htmlFor` overrides the association and no id is generated. Inside a labeled `Field`, that `Field`'s label is associated with the file input the same way, so the input again has two labels.\n- The name area sits inside the CTA's label, so with `hasName` its text joins the input's accessible name (\"Choose a file… resume.pdf\"). Browsers can also expose a picked file on the input itself, so a screen reader may read the name twice. It stays in the label because text you pass in `fileName`, such as a file uploaded earlier, reaches assistive technology only from there.\n- Add `aria-label` to the `<input>` for accessibility if your label is not plain text.",
|
|
78
78
|
"related": ["Field", "Icon", "useBulmaClasses"],
|
|
79
79
|
"storybook": "https://bestax.io/storybook/?path=/story/form-file--default",
|
|
80
80
|
"summary": "The `File` component provides a Bulma-styled file input, supporting color, size, boxed/fullwidth/align styles, icons, \"has name\", and filename display.",
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"name": "label",
|
|
92
92
|
"type": "React.ReactNode",
|
|
93
93
|
"default": null,
|
|
94
|
-
"description": "Field label. Automatically associated with the file input via `htmlFor` — uses your `id` when provided, otherwise a generated one. The input then has two labels (this one plus the wrapping `file-label`); assistive tech reads both. Dropped inside an outer `Field
|
|
94
|
+
"description": "Field label. Automatically associated with the file input via `htmlFor` — uses your `id` when provided, otherwise a generated one. The input then has two labels (this one plus the wrapping `file-label`); assistive tech reads both. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`).",
|
|
95
95
|
"required": false,
|
|
96
96
|
"inherited": false,
|
|
97
97
|
"deprecated": false
|
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
},
|
|
224
224
|
{
|
|
225
225
|
"path": "Grid.Cell",
|
|
226
|
-
"summary": "The `Cell` component provides a single Bulma grid cell for use inside the [`Grid`](
|
|
226
|
+
"summary": "The `Cell` component provides a single Bulma grid cell for use inside the [`Grid`](https://bestax.io/docs/api/grid) component.",
|
|
227
227
|
"component": "Cell",
|
|
228
228
|
"props": [
|
|
229
229
|
{
|