bestax-mcp 1.14.6 → 1.14.7
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 +76 -50
- package/data/components/Button.json +3 -3
- package/data/components/Buttons.json +4 -4
- package/data/components/ContextMenu.json +213 -0
- package/data/components/DateTimeInput.json +2 -2
- package/data/components/Dropdown.json +1 -1
- package/data/components/HoverCard.json +1 -1
- package/data/components/LinkButton.json +1 -1
- package/data/components/Popover.json +2 -1
- package/data/components/TimeInput.json +3 -3
- package/data/components/ToggleButton.json +501 -0
- package/data/components/Tooltip.json +20 -7
- package/data/skills/bestax-custom-component/SKILL.md +18 -0
- package/data/skills/bestax-custom-component/references/api.md +6 -3
- package/data/skills/bestax-custom-component/references/component-catalog.md +3 -1
- package/data/skills/bestax-layout-scaffold/SKILL.md +9 -0
- package/data/skills/bestax-migrate/references/bloomer/prop-map.md +3 -3
- package/data/skills/bestax-migrate/references/rbx/prop-map.md +3 -3
- package/data/skills/bestax-migrate/references/rbx/unmappables.md +23 -14
- package/data/skills/bestax-migrate/references/react-bulma-components/component-map.md +2 -2
- package/data/skills/bestax-migrate/references/react-bulma-components/unmappables.md +9 -3
- package/data/skills/bestax-optimize/references/modular-build.md +4 -2
- package/data/skills/bestax-theming/references/css-variables.md +18 -1
- package/data/skills/bestax-theming/references/themeable-components.md +1 -0
- package/data/skills.json +9 -9
- 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.
|
|
5
|
+
"version": "5.30.0"
|
|
6
6
|
},
|
|
7
7
|
"docsBase": "https://bestax.io/docs",
|
|
8
8
|
"categories": [
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"Tag",
|
|
41
41
|
"Tags",
|
|
42
42
|
"Title",
|
|
43
|
+
"ToggleButton",
|
|
43
44
|
"UnorderedList"
|
|
44
45
|
]
|
|
45
46
|
},
|
|
@@ -55,6 +56,7 @@
|
|
|
55
56
|
"Carousel",
|
|
56
57
|
"Collapse",
|
|
57
58
|
"Collapses",
|
|
59
|
+
"ContextMenu",
|
|
58
60
|
"Dialog",
|
|
59
61
|
"Dropdown",
|
|
60
62
|
"HoverCard",
|
|
@@ -381,6 +383,17 @@
|
|
|
381
383
|
"propCount": 6,
|
|
382
384
|
"exampleCount": 10
|
|
383
385
|
},
|
|
386
|
+
{
|
|
387
|
+
"name": "ContextMenu",
|
|
388
|
+
"kind": "component",
|
|
389
|
+
"category": "components",
|
|
390
|
+
"purpose": "The `ContextMenu` component opens a menu of actions where you right-click an element, such as a table row or a card, or long press it on a touch screen.",
|
|
391
|
+
"slug": "components/contextmenu",
|
|
392
|
+
"import": "import { ContextMenu } from '@allxsmith/bestax-bulma';",
|
|
393
|
+
"compound": true,
|
|
394
|
+
"propCount": 10,
|
|
395
|
+
"exampleCount": 9
|
|
396
|
+
},
|
|
384
397
|
{
|
|
385
398
|
"name": "Control",
|
|
386
399
|
"kind": "component",
|
|
@@ -1096,6 +1109,17 @@
|
|
|
1096
1109
|
"propCount": 17,
|
|
1097
1110
|
"exampleCount": 7
|
|
1098
1111
|
},
|
|
1112
|
+
{
|
|
1113
|
+
"name": "ToggleButton",
|
|
1114
|
+
"kind": "component",
|
|
1115
|
+
"category": "elements",
|
|
1116
|
+
"purpose": "The `ToggleButton` component renders a button that stays pressed until it's pressed again, and says whether it's on through `aria-pressed`.",
|
|
1117
|
+
"slug": "elements/togglebutton",
|
|
1118
|
+
"import": "import { ToggleButton } from '@allxsmith/bestax-bulma';",
|
|
1119
|
+
"compound": false,
|
|
1120
|
+
"propCount": 14,
|
|
1121
|
+
"exampleCount": 11
|
|
1122
|
+
},
|
|
1099
1123
|
{
|
|
1100
1124
|
"name": "Tooltip",
|
|
1101
1125
|
"kind": "component",
|
|
@@ -1104,8 +1128,8 @@
|
|
|
1104
1128
|
"slug": "components/tooltip",
|
|
1105
1129
|
"import": "import { Tooltip } from '@allxsmith/bestax-bulma';",
|
|
1106
1130
|
"compound": false,
|
|
1107
|
-
"propCount":
|
|
1108
|
-
"exampleCount":
|
|
1131
|
+
"propCount": 14,
|
|
1132
|
+
"exampleCount": 11
|
|
1109
1133
|
},
|
|
1110
1134
|
{
|
|
1111
1135
|
"name": "UnorderedList",
|
|
@@ -1236,52 +1260,52 @@
|
|
|
1236
1260
|
"--bulma-breadcrumb-item-padding-horizontal": ["Breadcrumb"],
|
|
1237
1261
|
"--bulma-breadcrumb-item-padding-vertical": ["Breadcrumb"],
|
|
1238
1262
|
"--bulma-breadcrumb-item-separator-color": ["Breadcrumb"],
|
|
1239
|
-
"--bulma-button-active-background-l-delta": ["Button"],
|
|
1240
|
-
"--bulma-button-active-border-color": ["Button"],
|
|
1241
|
-
"--bulma-button-active-border-l-delta": ["Button"],
|
|
1242
|
-
"--bulma-button-active-color": ["Button"],
|
|
1243
|
-
"--bulma-button-background-l": ["Button"],
|
|
1244
|
-
"--bulma-button-background-l-delta": ["Button"],
|
|
1245
|
-
"--bulma-button-border-color": ["Button"],
|
|
1246
|
-
"--bulma-button-border-l": ["Button"],
|
|
1247
|
-
"--bulma-button-border-l-delta": ["Button"],
|
|
1248
|
-
"--bulma-button-border-style": ["Button"],
|
|
1249
|
-
"--bulma-button-border-width": ["Button"],
|
|
1250
|
-
"--bulma-button-color-l": ["Button"],
|
|
1251
|
-
"--bulma-button-disabled-background-color": ["Button"],
|
|
1252
|
-
"--bulma-button-disabled-border-color": ["Button"],
|
|
1253
|
-
"--bulma-button-disabled-opacity": ["Button"],
|
|
1254
|
-
"--bulma-button-disabled-shadow": ["Button"],
|
|
1255
|
-
"--bulma-button-family": ["Button"],
|
|
1256
|
-
"--bulma-button-focus-border-color": ["Button"],
|
|
1257
|
-
"--bulma-button-focus-border-l-delta": ["Button"],
|
|
1258
|
-
"--bulma-button-focus-box-shadow-color": ["Button"],
|
|
1259
|
-
"--bulma-button-focus-box-shadow-size": ["Button"],
|
|
1260
|
-
"--bulma-button-ghost-background": ["Button"],
|
|
1261
|
-
"--bulma-button-ghost-border-color": ["Button"],
|
|
1262
|
-
"--bulma-button-ghost-color": ["Button"],
|
|
1263
|
-
"--bulma-button-ghost-decoration": ["Button"],
|
|
1264
|
-
"--bulma-button-ghost-hover-color": ["Button"],
|
|
1265
|
-
"--bulma-button-ghost-hover-decoration": ["Button"],
|
|
1266
|
-
"--bulma-button-h": ["Button"],
|
|
1267
|
-
"--bulma-button-hover-background-l-delta": ["Button"],
|
|
1268
|
-
"--bulma-button-hover-border-l-delta": ["Button"],
|
|
1269
|
-
"--bulma-button-l": ["Button"],
|
|
1270
|
-
"--bulma-button-outer-shadow-a": ["Button"],
|
|
1271
|
-
"--bulma-button-outer-shadow-h": ["Button"],
|
|
1272
|
-
"--bulma-button-outer-shadow-l": ["Button"],
|
|
1273
|
-
"--bulma-button-outer-shadow-s": ["Button"],
|
|
1274
|
-
"--bulma-button-padding-horizontal": ["Button"],
|
|
1275
|
-
"--bulma-button-padding-vertical": ["Button"],
|
|
1276
|
-
"--bulma-button-s": ["Button"],
|
|
1277
|
-
"--bulma-button-static-background-color": ["Button"],
|
|
1278
|
-
"--bulma-button-static-border-color": ["Button"],
|
|
1279
|
-
"--bulma-button-static-color": ["Button"],
|
|
1280
|
-
"--bulma-button-text-color": ["Button"],
|
|
1281
|
-
"--bulma-button-text-decoration": ["Button"],
|
|
1282
|
-
"--bulma-button-text-hover-background-color": ["Button"],
|
|
1283
|
-
"--bulma-button-text-hover-color": ["Button"],
|
|
1284
|
-
"--bulma-button-weight": ["Button"],
|
|
1263
|
+
"--bulma-button-active-background-l-delta": ["Button", "ToggleButton"],
|
|
1264
|
+
"--bulma-button-active-border-color": ["Button", "ToggleButton"],
|
|
1265
|
+
"--bulma-button-active-border-l-delta": ["Button", "ToggleButton"],
|
|
1266
|
+
"--bulma-button-active-color": ["Button", "ToggleButton"],
|
|
1267
|
+
"--bulma-button-background-l": ["Button", "ToggleButton"],
|
|
1268
|
+
"--bulma-button-background-l-delta": ["Button", "ToggleButton"],
|
|
1269
|
+
"--bulma-button-border-color": ["Button", "ToggleButton"],
|
|
1270
|
+
"--bulma-button-border-l": ["Button", "ToggleButton"],
|
|
1271
|
+
"--bulma-button-border-l-delta": ["Button", "ToggleButton"],
|
|
1272
|
+
"--bulma-button-border-style": ["Button", "ToggleButton"],
|
|
1273
|
+
"--bulma-button-border-width": ["Button", "ToggleButton"],
|
|
1274
|
+
"--bulma-button-color-l": ["Button", "ToggleButton"],
|
|
1275
|
+
"--bulma-button-disabled-background-color": ["Button", "ToggleButton"],
|
|
1276
|
+
"--bulma-button-disabled-border-color": ["Button", "ToggleButton"],
|
|
1277
|
+
"--bulma-button-disabled-opacity": ["Button", "ToggleButton"],
|
|
1278
|
+
"--bulma-button-disabled-shadow": ["Button", "ToggleButton"],
|
|
1279
|
+
"--bulma-button-family": ["Button", "ToggleButton"],
|
|
1280
|
+
"--bulma-button-focus-border-color": ["Button", "ToggleButton"],
|
|
1281
|
+
"--bulma-button-focus-border-l-delta": ["Button", "ToggleButton"],
|
|
1282
|
+
"--bulma-button-focus-box-shadow-color": ["Button", "ToggleButton"],
|
|
1283
|
+
"--bulma-button-focus-box-shadow-size": ["Button", "ToggleButton"],
|
|
1284
|
+
"--bulma-button-ghost-background": ["Button", "ToggleButton"],
|
|
1285
|
+
"--bulma-button-ghost-border-color": ["Button", "ToggleButton"],
|
|
1286
|
+
"--bulma-button-ghost-color": ["Button", "ToggleButton"],
|
|
1287
|
+
"--bulma-button-ghost-decoration": ["Button", "ToggleButton"],
|
|
1288
|
+
"--bulma-button-ghost-hover-color": ["Button", "ToggleButton"],
|
|
1289
|
+
"--bulma-button-ghost-hover-decoration": ["Button", "ToggleButton"],
|
|
1290
|
+
"--bulma-button-h": ["Button", "ToggleButton"],
|
|
1291
|
+
"--bulma-button-hover-background-l-delta": ["Button", "ToggleButton"],
|
|
1292
|
+
"--bulma-button-hover-border-l-delta": ["Button", "ToggleButton"],
|
|
1293
|
+
"--bulma-button-l": ["Button", "ToggleButton"],
|
|
1294
|
+
"--bulma-button-outer-shadow-a": ["Button", "ToggleButton"],
|
|
1295
|
+
"--bulma-button-outer-shadow-h": ["Button", "ToggleButton"],
|
|
1296
|
+
"--bulma-button-outer-shadow-l": ["Button", "ToggleButton"],
|
|
1297
|
+
"--bulma-button-outer-shadow-s": ["Button", "ToggleButton"],
|
|
1298
|
+
"--bulma-button-padding-horizontal": ["Button", "ToggleButton"],
|
|
1299
|
+
"--bulma-button-padding-vertical": ["Button", "ToggleButton"],
|
|
1300
|
+
"--bulma-button-s": ["Button", "ToggleButton"],
|
|
1301
|
+
"--bulma-button-static-background-color": ["Button", "ToggleButton"],
|
|
1302
|
+
"--bulma-button-static-border-color": ["Button", "ToggleButton"],
|
|
1303
|
+
"--bulma-button-static-color": ["Button", "ToggleButton"],
|
|
1304
|
+
"--bulma-button-text-color": ["Button", "ToggleButton"],
|
|
1305
|
+
"--bulma-button-text-decoration": ["Button", "ToggleButton"],
|
|
1306
|
+
"--bulma-button-text-hover-background-color": ["Button", "ToggleButton"],
|
|
1307
|
+
"--bulma-button-text-hover-color": ["Button", "ToggleButton"],
|
|
1308
|
+
"--bulma-button-weight": ["Button", "ToggleButton"],
|
|
1285
1309
|
"--bulma-card-background-color": ["Card"],
|
|
1286
1310
|
"--bulma-card-color": ["Card"],
|
|
1287
1311
|
"--bulma-card-content-background-color": ["Card"],
|
|
@@ -1373,6 +1397,8 @@
|
|
|
1373
1397
|
"--bulma-content-table-foot-cell-color": ["Content"],
|
|
1374
1398
|
"--bulma-content-table-head-cell-border-width": ["Content"],
|
|
1375
1399
|
"--bulma-content-table-head-cell-color": ["Content"],
|
|
1400
|
+
"--bulma-context-menu-max-height": ["ContextMenu"],
|
|
1401
|
+
"--bulma-context-menu-z-index": ["ContextMenu"],
|
|
1376
1402
|
"--bulma-control-border-width": ["Control"],
|
|
1377
1403
|
"--bulma-control-focus-shadow-l": ["Control"],
|
|
1378
1404
|
"--bulma-control-height": ["Control"],
|
|
@@ -1886,7 +1912,7 @@
|
|
|
1886
1912
|
"--bulma-loading-cancel-hover-color": ["Loading"],
|
|
1887
1913
|
"--bulma-loading-cancel-radius": ["Loading"],
|
|
1888
1914
|
"--bulma-loading-cancel-size": ["Loading"],
|
|
1889
|
-
"--bulma-loading-color": ["Button"],
|
|
1915
|
+
"--bulma-loading-color": ["Button", "ToggleButton"],
|
|
1890
1916
|
"--bulma-loading-content-gap": ["Loading"],
|
|
1891
1917
|
"--bulma-loading-icon-border-width": ["Loading"],
|
|
1892
1918
|
"--bulma-loading-icon-border-width-large": ["Loading"],
|
|
@@ -97,8 +97,8 @@
|
|
|
97
97
|
"code": "function example() {\n const buttonRef = React.useRef<HTMLButtonElement>(null);\n const [tag, setTag] = React.useState<string>();\n\n return (\n <>\n <Button color=\"primary\" ref={buttonRef}>\n Target\n </Button>\n <Button ml=\"2\" onClick={() => setTag(buttonRef.current?.tagName)}>\n Read the tag from its ref\n </Button>\n <p>Rendered element: {tag ?? '—'}</p>\n </>\n );\n}"
|
|
98
98
|
}
|
|
99
99
|
],
|
|
100
|
-
"accessibility": "- **Labeling:** Always provide descriptive content for buttons for screen readers.\n- **States:** The `isDisabled` and `disabled` props ensure correct `aria-disabled` and `disabled` attributes.\n- **Keyboard:** When rendered as `<a>`, disabled buttons are not focusable.\n- **Focus:** Use `isFocused` and `isActive` for visual feedback, but rely on browser focus for actual accessibility.\n\n:::note\nIf your button has only an icon, use `aria-label` to provide accessible text.\n:::",
|
|
101
|
-
"related": ["Buttons", "Icon", "useBulmaClasses"],
|
|
100
|
+
"accessibility": "- **Labeling:** Always provide descriptive content for buttons for screen readers.\n- **States:** The `isDisabled` and `disabled` props ensure correct `aria-disabled` and `disabled` attributes.\n- **Keyboard:** When rendered as `<a>`, disabled buttons are not focusable.\n- **Focus:** Use `isFocused` and `isActive` for visual feedback, but rely on browser focus for actual accessibility.\n- **Toggles:** `isActive` tells a screen reader nothing. A button that turns something on or off is a [`ToggleButton`](https://bestax.io/docs/api/elements/togglebutton), which sets `aria-pressed`.\n\n:::note\nIf your button has only an icon, use `aria-label` to provide accessible text.\n:::",
|
|
101
|
+
"related": ["Buttons", "Icon", "ToggleButton", "useBulmaClasses"],
|
|
102
102
|
"storybook": "https://bestax.io/storybook/?path=/story/elements-button--default",
|
|
103
103
|
"summary": "The `Button` component provides a flexible and highly customizable button for your Bulma React UI.",
|
|
104
104
|
"import": "import { Button } from '@allxsmith/bestax-bulma';",
|
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
"name": "isActive",
|
|
224
224
|
"type": "boolean",
|
|
225
225
|
"default": "false",
|
|
226
|
-
"description": "Applies active styling (visual only)
|
|
226
|
+
"description": "Applies active styling (visual only), with no `aria-pressed`. For a button that stays pressed, use `ToggleButton`.",
|
|
227
227
|
"required": false,
|
|
228
228
|
"inherited": false,
|
|
229
229
|
"deprecated": false
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"code": "<Buttons>\n <Buttons.Button color=\"primary\">Save</Buttons.Button>\n <Buttons.Button>Cancel</Buttons.Button>\n <Buttons.LinkButton>Learn more</Buttons.LinkButton>\n</Buttons>"
|
|
39
39
|
}
|
|
40
40
|
],
|
|
41
|
-
"accessibility": "- Grouping buttons in a `<div class=\"buttons\">` has no negative impact on accessibility.\n- Ensure each `Button` has a clear label (text or `aria-label`).\n-
|
|
42
|
-
"related": ["Button", "useBulmaClasses"],
|
|
41
|
+
"accessibility": "- Grouping buttons in a `<div class=\"buttons\">` has no negative impact on accessibility.\n- Ensure each `Button` has a clear label (text or `aria-label`).\n- For a set of toggles that each turn on and off on their own, use [`ToggleButton`](https://bestax.io/docs/api/elements/togglebutton) in `Buttons hasAddons`, and give the `Buttons` `role=\"group\"` and an `aria-label`. A set where only one can be on is a radio group, so use [`Radios`](https://bestax.io/docs/api/form/radios) for it.\n\n:::tip\nYou can use all Bulma helper props (spacing, color, alignment) with `Buttons` for even more control.\n:::",
|
|
42
|
+
"related": ["Button", "ToggleButton", "useBulmaClasses"],
|
|
43
43
|
"storybook": "https://bestax.io/storybook/?path=/story/elements-button--default",
|
|
44
44
|
"summary": "The `Buttons` component lets you group multiple `Button` elements together with Bulma's spacing, alignment, and add-on features.",
|
|
45
45
|
"import": "import { Buttons } from '@allxsmith/bestax-bulma';",
|
|
@@ -257,7 +257,7 @@
|
|
|
257
257
|
"name": "isActive",
|
|
258
258
|
"type": "boolean",
|
|
259
259
|
"default": "false",
|
|
260
|
-
"description": "Applies active styling (visual only)
|
|
260
|
+
"description": "Applies active styling (visual only), with no `aria-pressed`. For a button that stays pressed, use `ToggleButton`.",
|
|
261
261
|
"required": false,
|
|
262
262
|
"inherited": false,
|
|
263
263
|
"deprecated": false
|
|
@@ -433,7 +433,7 @@
|
|
|
433
433
|
"name": "isActive",
|
|
434
434
|
"type": "boolean",
|
|
435
435
|
"default": "false",
|
|
436
|
-
"description": "Applies active styling (visual only)
|
|
436
|
+
"description": "Applies active styling (visual only), with no `aria-pressed`. For a button that stays pressed, use `ToggleButton`.",
|
|
437
437
|
"required": false,
|
|
438
438
|
"inherited": true,
|
|
439
439
|
"deprecated": false
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ContextMenu",
|
|
3
|
+
"kind": "component",
|
|
4
|
+
"category": "components",
|
|
5
|
+
"slug": "components/contextmenu",
|
|
6
|
+
"docsUrl": "https://bestax.io/docs/api/components/contextmenu",
|
|
7
|
+
"examples": [
|
|
8
|
+
{
|
|
9
|
+
"title": "Basic ContextMenu",
|
|
10
|
+
"code": "<ContextMenu\n aria-label=\"Actions for report.pdf\"\n trigger={\n <Box tabIndex={0} p=\"6\" textAlign=\"centered\">\n report.pdf: right-click here, or long press on a touch screen\n </Box>\n }\n>\n <ContextMenu.Item as=\"button\">Rename</ContextMenu.Item>\n <ContextMenu.Item as=\"button\">Duplicate</ContextMenu.Item>\n <ContextMenu.Divider />\n <ContextMenu.Item as=\"button\" color=\"danger\">\n Delete\n </ContextMenu.Item>\n</ContextMenu>"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"title": "On Table Rows",
|
|
14
|
+
"code": "function example() {\n const [openFor, setOpenFor] = useState<string | null>(null);\n const [last, setLast] = useState('nothing yet');\n const files = ['report.pdf', 'budget.xlsx', 'notes.txt'];\n\n return (\n <>\n <Paragraph mb=\"3\">Last action: {last}</Paragraph>\n <Table isFullwidth>\n <Table.Tbody>\n {files.map(name => {\n const actions = (\n <>\n <ContextMenu.Item\n as=\"button\"\n onClick={() => setLast(`Rename ${name}`)}\n >\n Rename\n </ContextMenu.Item>\n <ContextMenu.Item\n as=\"button\"\n onClick={() => setLast(`Duplicate ${name}`)}\n >\n Duplicate\n </ContextMenu.Item>\n <ContextMenu.Divider />\n <ContextMenu.Item\n as=\"button\"\n color=\"danger\"\n onClick={() => setLast(`Delete ${name}`)}\n >\n Delete\n </ContextMenu.Item>\n </>\n );\n return (\n <ContextMenu\n key={name}\n aria-label={`Actions for ${name}`}\n onOpenChange={open =>\n setOpenFor(current =>\n open ? name : current === name ? null : current\n )\n }\n trigger={\n <Table.Tr isSelected={openFor === name}>\n <Table.Td>{name}</Table.Td>\n <Table.Td>\n <Dropdown label=\"Actions\" right>\n {actions}\n </Dropdown>\n </Table.Td>\n </Table.Tr>\n }\n >\n {actions}\n </ContextMenu>\n );\n })}\n </Table.Tbody>\n </Table>\n </>\n );\n}"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"title": "On Touch Screens",
|
|
18
|
+
"code": "<ContextMenu\n aria-label=\"Actions for IMG_0042.jpg\"\n trigger={\n <Box tabIndex={0} interaction=\"unselectable\" p=\"6\" textAlign=\"centered\">\n IMG_0042.jpg: long press, and no text gets selected\n </Box>\n }\n>\n <ContextMenu.Item as=\"button\">Copy link</ContextMenu.Item>\n <ContextMenu.Item as=\"button\">Download</ContextMenu.Item>\n</ContextMenu>"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"title": "Keeping It Open",
|
|
22
|
+
"code": "function example() {\n const [hidden, setHidden] = useState(false);\n const [extensions, setExtensions] = useState(true);\n\n return (\n <ContextMenu\n aria-label=\"View options\"\n closeOnClick={false}\n trigger={\n <Box tabIndex={0} p=\"6\" textAlign=\"centered\">\n Hidden files are {hidden ? 'shown' : 'hidden'}, extensions are{' '}\n {extensions ? 'shown' : 'hidden'}\n </Box>\n }\n >\n <ContextMenu.Item\n as=\"button\"\n role=\"menuitemcheckbox\"\n aria-checked={hidden}\n onClick={() => setHidden(value => !value)}\n >\n Show hidden files\n </ContextMenu.Item>\n <ContextMenu.Item\n as=\"button\"\n role=\"menuitemcheckbox\"\n aria-checked={extensions}\n onClick={() => setExtensions(value => !value)}\n >\n Show extensions\n </ContextMenu.Item>\n </ContextMenu>\n );\n}"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"title": "Disabled Items",
|
|
26
|
+
"code": "<ContextMenu\n aria-label=\"Clipboard\"\n trigger={\n <Box tabIndex={0} p=\"6\" textAlign=\"centered\">\n Right-click for the clipboard\n </Box>\n }\n>\n <ContextMenu.Item as=\"button\" disabled>\n Cut\n </ContextMenu.Item>\n <ContextMenu.Item as=\"button\" disabled>\n Copy\n </ContextMenu.Item>\n <ContextMenu.Item as=\"button\">Paste</ContextMenu.Item>\n</ContextMenu>"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"title": "Nested Regions",
|
|
30
|
+
"code": "<ContextMenu\n aria-label=\"Board\"\n trigger={\n <Box p=\"5\">\n <Paragraph mb=\"4\">Right-click between the cards for the board</Paragraph>\n <ContextMenu\n aria-label=\"Actions for Write the docs\"\n trigger={\n <Card tabIndex={0}>\n <Card.Content>Write the docs</Card.Content>\n </Card>\n }\n >\n <ContextMenu.Item as=\"button\">Move to Done</ContextMenu.Item>\n <ContextMenu.Item as=\"button\">Archive</ContextMenu.Item>\n </ContextMenu>\n </Box>\n }\n>\n <ContextMenu.Item as=\"button\">New card</ContextMenu.Item>\n <ContextMenu.Item as=\"button\">Rename board</ContextMenu.Item>\n</ContextMenu>"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"title": "Turning It Off",
|
|
34
|
+
"code": "function example() {\n const [disabled, setDisabled] = useState(false);\n\n return (\n <>\n <Switch\n mb=\"3\"\n checked={disabled}\n onChange={event => setDisabled(event.target.checked)}\n >\n Use the browser's menu\n </Switch>\n <ContextMenu\n aria-label=\"Actions for notes.txt\"\n disabled={disabled}\n trigger={\n <Box tabIndex={0} p=\"6\" textAlign=\"centered\">\n notes.txt\n </Box>\n }\n >\n <ContextMenu.Item as=\"button\">Rename</ContextMenu.Item>\n <ContextMenu.Item as=\"button\">Delete</ContextMenu.Item>\n </ContextMenu>\n </>\n );\n}"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"title": "Where the Menu Goes",
|
|
38
|
+
"code": "function RenameDialog({ active, onClose }) {\n const [overlays, setOverlays] = useState<HTMLElement | null>(null);\n\n return (\n <Modal active={active} onClose={onClose}>\n <ConfigProvider portalContainer={overlays ?? undefined}>\n <ContextMenu\n aria-label=\"Actions for report.pdf\"\n trigger={<Box tabIndex={0}>report.pdf</Box>}\n >\n <ContextMenu.Item as=\"button\">Rename</ContextMenu.Item>\n </ContextMenu>\n </ConfigProvider>\n <div ref={setOverlays} />\n </Modal>\n );\n}"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"title": "Compound (dot-notation) usage",
|
|
42
|
+
"code": "<ContextMenu\n aria-label=\"Actions for notes.txt\"\n trigger={\n <Box tabIndex={0} p=\"6\" textAlign=\"centered\">\n notes.txt\n </Box>\n }\n>\n <ContextMenu.Item as=\"button\">Open</ContextMenu.Item>\n <ContextMenu.Item as=\"button\">Rename</ContextMenu.Item>\n <ContextMenu.Divider />\n <ContextMenu.Item as=\"button\">Delete</ContextMenu.Item>\n</ContextMenu>"
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
"accessibility": "`ContextMenu` follows the [WAI-ARIA menu pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menubar/),\nwithout a menubar or submenus:\n\n- **Opening:** APG names \"a command, such as Shift + F10 in Windows, that opens a context specific\n menu\". That's the browser's `contextmenu` event, which <kbd>Shift</kbd>+<kbd>F10</kbd> and the\n context menu key fire on Windows and Linux, and VoiceOver's <kbd>VO</kbd>+<kbd>Shift</kbd>+<kbd>M</kbd>\n fires on macOS. `ContextMenu` adds no key handler of its own, so the menu never opens twice for\n one key.\n- **Focus on open** goes to the first enabled item, or to the menu itself when there's none.\n- <kbd>ArrowDown</kbd> and <kbd>ArrowUp</kbd> move to the next and previous item, wrapping, and\n <kbd>Home</kbd> and <kbd>End</kbd> go to the first and last.\n- **Typing** a letter moves to the next item whose text starts with what's been typed. Letters typed\n in quick succession add up to one search, and the same letter again cycles through the items that\n start with it. Each opening starts a new search.\n- <kbd>Enter</kbd> and <kbd>Space</kbd> activate the focused item the way a click does, so its\n `onClick` runs, and a key held down activates it once.\n- <kbd>Escape</kbd> closes the menu and returns focus to what had it before the menu opened. It\n stops there, so a `Popover` or a `Modal` around the menu stays open.\n- <kbd>Tab</kbd> and <kbd>Shift</kbd>+<kbd>Tab</kbd> close it and return focus too. The menu sits at\n the end of the page, so letting Tab go on from it would skip the rest of the page.\n- An item that runs closes the menu and returns focus, unless it moved focus somewhere else, such as\n into a `Modal` it opened or a rename field.\n\nRoles and names:\n\n- The menu is `role=\"menu\"`, named by the `aria-label` or `aria-labelledby` you pass. There's no\n button to borrow a name from, and a development build warns when a menu opens without one.\n- Items are `menuitem` by default, and `menuitemcheckbox` or `menuitemradio` with `aria-checked`\n through the item's `role`. A divider is an `<hr>`, which is a separator.\n- Disabled items, a `button` with `disabled` or an item with `aria-disabled=\"true\"`, are skipped by\n the arrow keys and by typing, as in `Dropdown`.\n- The trigger gets no ARIA, no role and no tab stop. `aria-haspopup` describes a popup that opens\n when an element is activated, and a right-click on a row isn't that. So nothing tells a screen\n reader user the menu is there, and on macOS only VoiceOver opens it from the keyboard: every action\n in it has to be reachable from a visible control as well, which\n [WCAG 2.1.1](https://www.w3.org/WAI/WCAG22/Understanding/keyboard.html) asks for.\n\nAnd around it:\n\n- The menu isn't modal. A press outside it closes it and does whatever it does, the rest of the page\n stays reachable, and nothing locks scrolling.\n- Nothing listens on the page while the menu is closed and no finger is held on its trigger, so a\n table with a menu on every row adds no listeners until one is used.\n- The menu doesn't animate.",
|
|
46
|
+
"related": [
|
|
47
|
+
"ConfigProvider",
|
|
48
|
+
"Dropdown",
|
|
49
|
+
"HoverCard",
|
|
50
|
+
"Popover",
|
|
51
|
+
"Portal",
|
|
52
|
+
"useBulmaClasses"
|
|
53
|
+
],
|
|
54
|
+
"storybook": "https://bestax.io/storybook/?path=/story/components-contextmenu--default",
|
|
55
|
+
"summary": "The `ContextMenu` component opens a menu of actions where you right-click an element, such as a table row or a card, or long press it on a touch screen. Shift+F10 and the context menu key open it too, where the browser fires `contextmenu` for them, which Windows and Linux do. The menu is Dropdown's markup, portaled into the `portalContainer` a `ConfigProvider` sets, or the end of the trigger's own document's `<body>`, so it never has server markup. It opens below and to the right of the point, flips above or to the left where there's no room, moves in where it fits neither way, and scrolls inside when it's taller than the viewport. It doesn't follow the trigger, since scrolling closes it. Inside a `Modal` or a shadow root, point `portalContainer` inside it, so screen readers that honor `aria-modal` reach the menu and the shadow root's styles apply. Opening moves focus to the first enabled item. The arrow keys, Home, End and typing move between items, and Enter and Space activate one. Escape, Tab, an item, a press outside, scrolling, resizing and the window losing focus close it, handing focus back to what had it unless an item moved it somewhere else. For a menu opened from a button use `Dropdown`.",
|
|
56
|
+
"import": "import { ContextMenu } from '@allxsmith/bestax-bulma';",
|
|
57
|
+
"sourceFile": "bulma-ui/src/components/ContextMenu.tsx",
|
|
58
|
+
"rootClass": "context-menu",
|
|
59
|
+
"parts": [
|
|
60
|
+
{
|
|
61
|
+
"path": "ContextMenu",
|
|
62
|
+
"summary": "The `ContextMenu` component opens a menu of actions where you right-click an element, such as a table row or a card, or long press it on a touch screen. Shift+F10 and the context menu key open it too, where the browser fires `contextmenu` for them, which Windows and Linux do. The menu is Dropdown's markup, portaled into the `portalContainer` a `ConfigProvider` sets, or the end of the trigger's own document's `<body>`, so it never has server markup. It opens below and to the right of the point, flips above or to the left where there's no room, moves in where it fits neither way, and scrolls inside when it's taller than the viewport. It doesn't follow the trigger, since scrolling closes it. Inside a `Modal` or a shadow root, point `portalContainer` inside it, so screen readers that honor `aria-modal` reach the menu and the shadow root's styles apply. Opening moves focus to the first enabled item. The arrow keys, Home, End and typing move between items, and Enter and Space activate one. Escape, Tab, an item, a press outside, scrolling, resizing and the window losing focus close it, handing focus back to what had it unless an item moved it somewhere else. For a menu opened from a button use `Dropdown`.",
|
|
63
|
+
"component": null,
|
|
64
|
+
"props": [
|
|
65
|
+
{
|
|
66
|
+
"name": "trigger",
|
|
67
|
+
"type": "React.ReactElement",
|
|
68
|
+
"default": null,
|
|
69
|
+
"description": "The element a right-click, Shift+F10, the context menu key or a long press opens the menu from: a table row, a card, an image. It's cloned, not wrapped, so a row stays a row, which means it has to be a single element that passes `className` and the `onContextMenu`, `onPointerDown`, `onPointerMove`, `onPointerUp`, `onPointerCancel` and `onTouchEnd` handlers to its DOM node. Its own handlers for those run first, and one that calls `preventDefault()` on `contextmenu` keeps the menu closed. A `ContextMenu` inside it opens instead of this one. It gets no ARIA and no tab stop, since it can be any element and a right-click isn't an activation. Keyboard users reach it through something focusable inside it, such as the row's own `Dropdown` button, or a `tabIndex={0}` you give it, and press Shift+F10 or the context menu key there. It gets `-webkit-touch-callout: none`, so iOS doesn't put its own callout for a link or an image over the menu. A long press still selects text the way it does anywhere, so give a region where it shouldn't `interaction=\"unselectable\"`.",
|
|
70
|
+
"required": false,
|
|
71
|
+
"inherited": false,
|
|
72
|
+
"deprecated": false
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"name": "children",
|
|
76
|
+
"type": "React.ReactNode",
|
|
77
|
+
"default": null,
|
|
78
|
+
"description": "The menu's items: `ContextMenu.Item` and `ContextMenu.Divider`, the same components as `Dropdown.Item` and `Dropdown.Divider`. Every action in it needs a visible way in as well, such as a `Dropdown` on the same row: nothing tells a screen reader user the menu is there, and on macOS only VoiceOver opens it from the keyboard.",
|
|
79
|
+
"required": false,
|
|
80
|
+
"inherited": false,
|
|
81
|
+
"deprecated": false
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"name": "onOpenChange",
|
|
85
|
+
"type": "(open: boolean) => void",
|
|
86
|
+
"default": null,
|
|
87
|
+
"description": "Called with `true` when the menu opens and `false` when it closes, whatever closed it, such as for highlighting the row whose menu is open. Nothing fires after ContextMenu unmounts. There's no `open` prop to go with it: a menu opened from code has no point to open at.",
|
|
88
|
+
"required": false,
|
|
89
|
+
"inherited": false,
|
|
90
|
+
"deprecated": false
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"name": "closeOnClick",
|
|
94
|
+
"type": "boolean",
|
|
95
|
+
"default": "true",
|
|
96
|
+
"description": "Close the menu when an item is clicked, or activated with Enter or Space. A click on a divider or between items leaves it open either way.",
|
|
97
|
+
"required": false,
|
|
98
|
+
"inherited": false,
|
|
99
|
+
"deprecated": false
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"name": "disabled",
|
|
103
|
+
"type": "boolean",
|
|
104
|
+
"default": "false",
|
|
105
|
+
"description": "Leave the trigger to the browser: a right-click shows the browser's own menu, a long press does what it does anywhere, and an open menu closes.",
|
|
106
|
+
"required": false,
|
|
107
|
+
"inherited": false,
|
|
108
|
+
"deprecated": false
|
|
109
|
+
}
|
|
110
|
+
],
|
|
111
|
+
"extraProps": [
|
|
112
|
+
{
|
|
113
|
+
"name": "aria-label",
|
|
114
|
+
"type": "string",
|
|
115
|
+
"default": null,
|
|
116
|
+
"description": "The menu's accessible name, such as \"Actions for report.pdf\". There's no button to borrow a name from, so pass this or `aria-labelledby`, and a development build warns when the menu opens with neither.",
|
|
117
|
+
"required": false,
|
|
118
|
+
"inherited": false,
|
|
119
|
+
"deprecated": false
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"name": "className",
|
|
123
|
+
"type": "string",
|
|
124
|
+
"default": null,
|
|
125
|
+
"description": "Additional classes for the menu (`role=\"menu\"`). The trigger keeps its own.",
|
|
126
|
+
"required": false,
|
|
127
|
+
"inherited": false,
|
|
128
|
+
"deprecated": false
|
|
129
|
+
}
|
|
130
|
+
],
|
|
131
|
+
"catchAll": "All standard <div> attributes and Bulma helper props",
|
|
132
|
+
"types": []
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"path": "ContextMenu.Item",
|
|
136
|
+
"summary": "Bulma Dropdown item.",
|
|
137
|
+
"component": "DropdownItem",
|
|
138
|
+
"props": [
|
|
139
|
+
{
|
|
140
|
+
"name": "as",
|
|
141
|
+
"type": "'a' | 'div' | 'button'",
|
|
142
|
+
"default": "'a'",
|
|
143
|
+
"description": "The element type to render. `'button'` renders `type=\"button\"` unless you pass `type=\"submit\"` or `type=\"reset\"`, so an item inside a form does not submit it.",
|
|
144
|
+
"required": false,
|
|
145
|
+
"inherited": false,
|
|
146
|
+
"deprecated": false
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"name": "active",
|
|
150
|
+
"type": "boolean",
|
|
151
|
+
"default": "false",
|
|
152
|
+
"description": "Whether the item is active.",
|
|
153
|
+
"required": false,
|
|
154
|
+
"inherited": false,
|
|
155
|
+
"deprecated": false
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"name": "className",
|
|
159
|
+
"type": "string",
|
|
160
|
+
"default": null,
|
|
161
|
+
"description": "Additional CSS classes.",
|
|
162
|
+
"required": false,
|
|
163
|
+
"inherited": false,
|
|
164
|
+
"deprecated": false
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"name": "disabled",
|
|
168
|
+
"type": "boolean",
|
|
169
|
+
"default": "false",
|
|
170
|
+
"description": "Marks the item as disabled; disabled items are skipped during keyboard navigation. Use with `as=\"button\"` for a native disabled control, or pair with `aria-disabled` on a link.",
|
|
171
|
+
"required": false,
|
|
172
|
+
"inherited": false,
|
|
173
|
+
"deprecated": false
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"name": "children",
|
|
177
|
+
"type": "React.ReactNode",
|
|
178
|
+
"default": null,
|
|
179
|
+
"description": "Item content.",
|
|
180
|
+
"required": false,
|
|
181
|
+
"inherited": false,
|
|
182
|
+
"deprecated": false
|
|
183
|
+
}
|
|
184
|
+
],
|
|
185
|
+
"extraProps": [],
|
|
186
|
+
"catchAll": "Remaining props of the element selected by as and Bulma helper props",
|
|
187
|
+
"types": []
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"path": "ContextMenu.Divider",
|
|
191
|
+
"summary": "Bulma Dropdown divider.",
|
|
192
|
+
"component": "DropdownDivider",
|
|
193
|
+
"props": [],
|
|
194
|
+
"extraProps": [],
|
|
195
|
+
"catchAll": null,
|
|
196
|
+
"types": []
|
|
197
|
+
}
|
|
198
|
+
],
|
|
199
|
+
"cssVars": [
|
|
200
|
+
{
|
|
201
|
+
"css": "--bulma-context-menu-z-index",
|
|
202
|
+
"sass": "$context-menu-z-index",
|
|
203
|
+
"default": "$extras-z-index-tooltip",
|
|
204
|
+
"scope": "element"
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"css": "--bulma-context-menu-max-height",
|
|
208
|
+
"sass": "$context-menu-max-height",
|
|
209
|
+
"default": "calc(100dvh - 1rem)",
|
|
210
|
+
"scope": "element"
|
|
211
|
+
}
|
|
212
|
+
]
|
|
213
|
+
}
|
|
@@ -170,7 +170,7 @@
|
|
|
170
170
|
"code": "<DateTimeInput label=\"Input only\" popover={false} defaultValue={new Date()} />"
|
|
171
171
|
}
|
|
172
172
|
],
|
|
173
|
-
"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.\n- Closing the popover with `Escape`, the ✓ button or `Enter` on a time wheel 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. Closing it commits nothing by itself: an empty field stays empty, and leaving afterwards commits only what you typed, so seconds the display leaves out are kept.\n- Calendar uses `role=\"grid\"`; cells expose `aria-selected`, `aria-disabled`, and `aria-current=\"date\"`.\n- Roving `tabindex` keeps a single day 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- Each time wheel uses `role=\"spinbutton\"` with `aria-valuemin`, `aria-valuemax`, `aria-valuenow`, and `aria-valuetext`. The values drawn above and below are click targets hidden from assistive technology, which reads the value from the spinbutton.\n- The footer's confirm button exposes an accessible label (`Done`); the Reset button reverts your edits to the value the popover opened with.\n- Tab order walks from the calendar to the footer (Reset / ✓), and from the time wheels to the footer while they are open.",
|
|
173
|
+
"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.\n- Closing the popover with `Escape`, the ✓ button or `Enter` on a time wheel 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. Closing it commits nothing by itself: an empty field stays empty, and leaving afterwards commits only what you typed, so seconds the display leaves out are kept.\n- Calendar uses `role=\"grid\"`; cells expose `aria-selected`, `aria-disabled`, and `aria-current=\"date\"`.\n- Roving `tabindex` keeps a single day 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- Each time wheel uses `role=\"spinbutton\"` with `aria-valuemin`, `aria-valuemax`, `aria-valuenow`, and `aria-valuetext`. The values drawn above and below are click targets hidden from assistive technology, which reads the value from the spinbutton.\n- In a 12-hour picker, AM/PM is one of those wheels, reading `AM` or `PM`. Its accessible name is `AM/PM` unless `labels.ampm` sets another.\n- The footer's confirm button exposes an accessible label (`Done`); the Reset button reverts your edits to the value the popover opened with.\n- Tab order walks from the calendar to the footer (Reset / ✓), and from the time wheels to the footer while they are open.",
|
|
174
174
|
"related": ["DateInput", "Input", "TimeInput"],
|
|
175
175
|
"storybook": "https://bestax.io/storybook/?path=/story/form-datetimeinput",
|
|
176
176
|
"summary": "The `DateTimeInput` combines a calendar and a time **wheel spinner** in a single popover — an iOS-style layout.",
|
|
@@ -718,7 +718,7 @@
|
|
|
718
718
|
"name": "labels",
|
|
719
719
|
"type": "PickerLabels",
|
|
720
720
|
"default": null,
|
|
721
|
-
"description": "Optional translatable string overrides.",
|
|
721
|
+
"description": "Optional translatable string overrides. In a 12-hour picker, `ampm` names the AM/PM column, `'AM/PM'` by default.",
|
|
722
722
|
"required": false,
|
|
723
723
|
"inherited": true,
|
|
724
724
|
"deprecated": false
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
}
|
|
44
44
|
],
|
|
45
45
|
"accessibility": "- The dropdown root is a `<div class=\"dropdown\">` with ARIA roles/attributes for menu and trigger.\n- The trigger button uses `aria-haspopup`, `aria-controls`, and `aria-expanded`.\n- Menu items are focusable and use `role=\"menuitem\"`. An item given `role=\"menuitemcheckbox\"` or `role=\"menuitemradio\"` stays in the arrow-key order.\n- The items are the only focusable things inside `role=\"menu\"`. A click between them, on a divider say, focuses the menu itself, so the arrow keys still reach the items from there.\n- `Dropdown.Item as=\"button\"` defaults to `type=\"button\"`, so a menu item inside a form doesn't\n submit it. Pass `type=\"submit\"` or `type=\"reset\"` and yours is used instead; any other value\n renders `type=\"button\"`.\n- Clicking outside closes the dropdown in most cases.\n\n`Dropdown` implements the [WAI-ARIA Menu Button pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/)\nout of the box:\n\n- On the trigger: <kbd>ArrowDown</kbd> or <kbd>Enter</kbd>/<kbd>Space</kbd> open the menu and\n focus the first item; <kbd>ArrowUp</kbd> opens the menu and focuses the last item;\n <kbd>Escape</kbd> closes an open menu.\n- Inside the menu: <kbd>ArrowDown</kbd>/<kbd>ArrowUp</kbd> move between items and wrap around;\n <kbd>Home</kbd>/<kbd>End</kbd> jump to the first/last item; <kbd>Escape</kbd> closes the menu\n and returns focus to the trigger; <kbd>Tab</kbd> closes the menu and lets focus continue\n naturally.\n- On an item: <kbd>Enter</kbd> or <kbd>Space</kbd> activates it the way a click does, so its\n `onClick` runs and the menu closes unless `closeOnClick` is `false`. That includes the\n default anchor without an `href` and `as=\"div\"`, which the browser would not activate on\n its own.\n- When running an item closes the menu, by click or by key, focus goes back to the trigger,\n as it does for <kbd>Escape</kbd>. An item whose `onClick` moves focus somewhere else keeps\n it there.\n- Disabled items (a `Dropdown.Item` rendered with a native `disabled` attribute or\n `aria-disabled=\"true\"`) and dividers are skipped during arrow-key navigation.\n\n:::note\nThere is no typeahead and no built-in outside-click handling inside the menu beyond the\nexisting click-outside-to-close behavior — add those yourself if your use case needs them.\n:::",
|
|
46
|
-
"related": ["Button", "Popover", "useBulmaClasses"],
|
|
46
|
+
"related": ["Button", "ContextMenu", "Popover", "useBulmaClasses"],
|
|
47
47
|
"storybook": "https://bestax.io/storybook/?path=/story/components-dropdown--default",
|
|
48
48
|
"summary": "The `Dropdown` component provides Bulma's versatile dropdown menu for your Bulma React UI.",
|
|
49
49
|
"import": "import { Dropdown, Button, Field, Control, Span } from '@allxsmith/bestax-bulma';",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"code": "function example() {\n const [open, setOpen] = useState(false);\n const [following, setFollowing] = useState(false);\n\n return (\n <>\n <Paragraph mb=\"3\">\n The card is {open ? 'open' : 'closed'}\n {following ? ', and you follow Ada' : ''}.\n </Paragraph>\n <HoverCard\n open={open}\n onOpenChange={setOpen}\n trigger={<Link href=\"#ada\">Ada Lovelace</Link>}\n >\n <Paragraph mb=\"3\">Analytical Engine team</Paragraph>\n <Button\n size=\"small\"\n color=\"primary\"\n onClick={() => {\n setFollowing(true);\n setOpen(false);\n }}\n >\n Follow\n </Button>\n </HoverCard>\n </>\n );\n}"
|
|
31
31
|
}
|
|
32
32
|
],
|
|
33
|
-
"accessibility": "`HoverCard` is built to\n[WCAG's Content on Hover or Focus](https://www.w3.org/WAI/WCAG22/Understanding/content-on-hover-or-focus.html)\ncriterion, condition by condition:\n\n- **Dismissible:** <kbd>Escape</kbd> closes the card wherever focus is, without moving the
|
|
33
|
+
"accessibility": "`HoverCard` is built to\n[WCAG's Content on Hover or Focus](https://www.w3.org/WAI/WCAG22/Understanding/content-on-hover-or-focus.html)\ncriterion, condition by condition:\n\n- **Dismissible:** <kbd>Escape</kbd> closes the card wherever focus is, without you moving the\n pointer or focus. In controlled use it asks to close through `onOpenChange`, so the card closes\n when you set `open` to `false`. The keypress belongs to whatever has focus. When that's the card,\n its trigger or nothing, the card takes it, so a `Popover` or `Modal` around it stays open. When\n it's something else, such as a field elsewhere on the page or a `Modal` opened from the card, the\n card still closes and the key goes on to it. With one card inside another, the inner one closes\n first. Focus that was in the card goes back to the trigger, and the card stays closed until the\n pointer or focus leaves and comes back, or, with `openOnTap`, until the next tap on the trigger.\n- **Hoverable:** the pointer can move from the trigger onto the card. `closeDelay` covers the gap\n between them, and the card takes pointer events.\n- **Persistent:** no timer closes a card that's hovered or focused. Focus inside the card holds it\n however it got there. Whether a click focuses what it lands on is up to the browser, though:\n Safari and Firefox on macOS don't focus a button on click, so there a clicked button doesn't keep\n the card open once the pointer moves away.\n\nAnd around it:\n\n- Keyboard focus on the trigger opens the card, as hover does. Focus that a press brings doesn't,\n and neither does a touch pointer, so tapping the trigger on a phone just does what the trigger\n does. Clicking the trigger never toggles the card.\n- By default, then, a phone or tablet never opens the card, so whatever it shows has to be\n reachable from the trigger as well. `openOnTap` opens it with a tap, for a trigger with no tap\n action of its own. While a tap holds it open, a tap outside the trigger and the card closes it.\n- The trigger gets `aria-expanded` and `aria-controls`, which say it's expanded and name the card\n only while the card is on the page. It gets no role, no tab stop and no `aria-haspopup`, so the trigger element itself has to\n take focus, such as a link or a button. A link inside a `<span>` doesn't do, since focus comes\n back to the trigger and its ARIA is on it. A development build warns when the trigger can't take\n focus.\n- The card is a plain element with an `id` and no role. It isn't a dialog, since focus doesn't move\n into it, and it isn't a tooltip, since it can hold links. In place, a screen reader meets it\n right after the trigger, Tab goes from the trigger into its links and buttons, and tabbing past\n them closes it.\n- With `appendToBody` the card sits in the Tab order where its container is. By default that's\n the end of `<body>`, so it comes last: Tab reaches it only after the rest of the page, and focus\n leaving the trigger on the way closes it. Keyboard users can open it, read it and close it, so\n whatever it links to should be reachable from the page as well.\n- Opening the card moves no focus, and nothing traps it. Links and buttons belong in a card; a form\n belongs in a `Popover`, which opens on purpose and holds focus.\n- The fade-in is turned off under `prefers-reduced-motion: reduce`.",
|
|
34
34
|
"related": ["Media", "Popover", "Portal", "Tooltip", "useBulmaClasses"],
|
|
35
35
|
"storybook": "https://bestax.io/storybook/?path=/story/components-hovercard--default",
|
|
36
36
|
"summary": "The `HoverCard` component shows a card previewing what's behind a link or a button while the pointer rests on it or keyboard focus is on it. Nothing moves focus when the card opens, and nothing traps it. In place, the card comes right after the trigger, so Tab goes from the trigger into its links and tabbing past them closes it. The pointer can move onto the card, Escape closes it from anywhere, and by default touch doesn't open it, so tapping the trigger just does what the trigger does. `openOnTap` opens it with a tap, for a trigger with no tap action of its own. For hints with nothing to click use `Tooltip`, and for content opened on purpose, such as a form, use `Popover`.",
|
|
@@ -154,7 +154,7 @@
|
|
|
154
154
|
"name": "isActive",
|
|
155
155
|
"type": "boolean",
|
|
156
156
|
"default": "false",
|
|
157
|
-
"description": "Applies active styling (visual only)
|
|
157
|
+
"description": "Applies active styling (visual only), with no `aria-pressed`. For a button that stays pressed, use `ToggleButton`.",
|
|
158
158
|
"required": false,
|
|
159
159
|
"inherited": true,
|
|
160
160
|
"deprecated": false
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
],
|
|
41
41
|
"accessibility": "`Popover` follows the [WAI-ARIA dialog pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/)\nfor a non-modal dialog:\n\n- The panel is a `role=\"dialog\"` without `aria-modal`. It is named by its `Popover.Header` through\n `aria-labelledby`, or by `ariaLabel`, which takes precedence. A development build warns when an\n open panel has neither.\n- The trigger gets `aria-haspopup=\"dialog\"`, `aria-expanded`, and `aria-controls` pointing at the\n panel while it is open.\n- Opening moves focus to the first control in the panel, or to the panel itself when it has none.\n Closing hands focus back to the trigger, as long as focus is still in the panel then, so a click\n that put it somewhere else keeps it there.\n- Tab and Shift+Tab wrap inside the open panel, which the pattern asks of non-modal dialogs too.\n Pointer focus, the screen reader's reading cursor and the rest of the page stay free: nothing\n outside is hidden or made inert, and the page still scrolls. `trapFocus={false}` lets Tab leave.\n- <kbd>Escape</kbd> closes the popover while focus is in the panel or on the trigger. A dialog\n nested inside the panel, such as a date picker's calendar or another popover, takes its own\n Escape first.\n- <kbd>Enter</kbd> and <kbd>Space</kbd> toggle a trigger the browser doesn't click on its own.\n- The open animation is turned off under `prefers-reduced-motion: reduce`.",
|
|
42
42
|
"related": [
|
|
43
|
+
"ContextMenu",
|
|
43
44
|
"Dropdown",
|
|
44
45
|
"HoverCard",
|
|
45
46
|
"Modal",
|
|
@@ -348,7 +349,7 @@
|
|
|
348
349
|
"name": "isActive",
|
|
349
350
|
"type": "boolean",
|
|
350
351
|
"default": "false",
|
|
351
|
-
"description": "Applies active styling (visual only)
|
|
352
|
+
"description": "Applies active styling (visual only), with no `aria-pressed`. For a button that stays pressed, use `ToggleButton`.",
|
|
352
353
|
"required": false,
|
|
353
354
|
"inherited": true,
|
|
354
355
|
"deprecated": false
|
|
@@ -178,7 +178,7 @@
|
|
|
178
178
|
"code": "function example() {\n return (\n <Field\n horizontal\n label=\"Time\"\n labelProps={{ htmlFor: 'time-field-control' }}\n >\n <Field.Body>\n <Field>\n <Control iconLeftName=\"clock\">\n <TimeInput id=\"time-field-control\" placeholder=\"HH:MM\" />\n </Control>\n </Field>\n </Field.Body>\n </Field>\n );\n}"
|
|
179
179
|
}
|
|
180
180
|
],
|
|
181
|
-
"accessibility": "- Trigger uses `role=\"combobox\"` with `aria-haspopup=\"dialog\"`, `aria-expanded`, and `aria-controls`.\n- Popover panel has `role=\"dialog\"` with an accessible name.\n- Each spinner column has `role=\"spinbutton\"` with `aria-valuemin`, `aria-valuemax`, `aria-valuenow`, and `aria-valuetext`. The values drawn above and below are click targets hidden from assistive technology, which reads the value from the spinbutton.\n- AM/PM toggle
|
|
181
|
+
"accessibility": "- Trigger uses `role=\"combobox\"` with `aria-haspopup=\"dialog\"`, `aria-expanded`, and `aria-controls`.\n- Popover panel has `role=\"dialog\"` with an accessible name.\n- Each spinner column has `role=\"spinbutton\"` with `aria-valuemin`, `aria-valuemax`, `aria-valuenow`, and `aria-valuetext`. The values drawn above and below are click targets hidden from assistive technology, which reads the value from the spinbutton.\n- In a 12-hour picker, AM/PM is one of those spinbutton columns rather than a toggle button. Its `aria-valuetext` reads `AM` or `PM`; `↑`, `PageUp` and `End` move it to PM, and `↓`, `PageDown` and `Home` move it to AM. It stops at either end instead of wrapping around. Its accessible name is `AM/PM` unless `labels.ampm` sets another.\n- Honors `prefers-reduced-motion`.",
|
|
182
182
|
"related": ["DateInput", "DateTimeInput", "Input"],
|
|
183
183
|
"storybook": "https://bestax.io/storybook/?path=/story/form-timeinput",
|
|
184
184
|
"summary": "The `TimeInput` component is a form input that opens a popover spinner for time-of-day selection.",
|
|
@@ -582,7 +582,7 @@
|
|
|
582
582
|
"name": "hourFormat",
|
|
583
583
|
"type": "'12' | '24'",
|
|
584
584
|
"default": "'24'",
|
|
585
|
-
"description": "Hour format. `'12'`
|
|
585
|
+
"description": "Hour format. `'12'` adds an AM/PM column to the wheels.",
|
|
586
586
|
"required": false,
|
|
587
587
|
"inherited": true,
|
|
588
588
|
"deprecated": false
|
|
@@ -654,7 +654,7 @@
|
|
|
654
654
|
"name": "labels",
|
|
655
655
|
"type": "PickerLabels",
|
|
656
656
|
"default": null,
|
|
657
|
-
"description": "Optional translatable string overrides.",
|
|
657
|
+
"description": "Optional translatable string overrides. In a 12-hour picker, `ampm` names the AM/PM column, `'AM/PM'` by default.",
|
|
658
658
|
"required": false,
|
|
659
659
|
"inherited": true,
|
|
660
660
|
"deprecated": false
|