bestax-mcp 1.18.34 → 1.18.35
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/bulma-classes.json +6 -1
- package/data/catalog.json +127 -7
- package/data/components/Button.json +1 -1
- package/data/components/Card.json +1 -1
- package/data/components/Carousel.json +4 -4
- package/data/components/ColorInput.json +2 -2
- package/data/components/DateInput.json +3 -3
- package/data/components/DateRangeInput.json +3 -3
- package/data/components/DateTimeInput.json +3 -3
- package/data/components/Figure.json +1 -1
- package/data/components/LocaleProvider.json +1 -1
- package/data/components/Message.json +1 -1
- package/data/components/Modal.json +1 -1
- package/data/components/Navbar.json +2 -2
- package/data/components/Pagination.json +1 -1
- package/data/components/Popover.json +2 -2
- package/data/components/SegmentedControl.json +1 -1
- package/data/components/Sidebar.json +1 -1
- package/data/components/Slider.json +1 -1
- package/data/components/TimeInput.json +3 -3
- package/data/components/Tooltip.json +1 -1
- package/data/components/TreeSelect.json +1 -1
- package/data/skills/bestax-custom-component/references/component-catalog.md +8 -2
- package/data/skills/bestax-form/references/api.md +7 -2
- package/data/skills/bestax-layout-scaffold/references/layout-components.md +16 -11
- package/data/skills/bestax-migrate/references/bulma-classes/component-map.md +3 -1
- package/data/skills/bestax-migrate/references/bulma-classes/prop-map.md +2 -1
- package/data/skills/bestax-optimize/SKILL.md +2 -0
- package/data/skills/bestax-optimize/references/modular-build.md +11 -8
- package/data/skills/bestax-theming/references/css-variables.md +6 -3
- package/data/skills.json +7 -7
- package/package.json +2 -2
package/data/bulma-classes.json
CHANGED
|
@@ -2649,7 +2649,12 @@
|
|
|
2649
2649
|
"bgColor": "bgColor",
|
|
2650
2650
|
"part": false,
|
|
2651
2651
|
"why": null,
|
|
2652
|
-
"modifiers": {
|
|
2652
|
+
"modifiers": {
|
|
2653
|
+
"is-active": {
|
|
2654
|
+
"writes": [{ "prop": "active" }],
|
|
2655
|
+
"needsAttr": { "name": "aria-current", "value": "page" }
|
|
2656
|
+
}
|
|
2657
|
+
},
|
|
2653
2658
|
"omits": {},
|
|
2654
2659
|
"wrapsChildren": null,
|
|
2655
2660
|
"folds": null,
|
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.66.1"
|
|
6
6
|
},
|
|
7
7
|
"docsBase": "https://bestax.io/docs",
|
|
8
8
|
"categories": [
|
|
@@ -301,7 +301,7 @@
|
|
|
301
301
|
"category": "components",
|
|
302
302
|
"purpose": "The `Card` component renders a Bulma-styled card with optional header, image, content, and footer.",
|
|
303
303
|
"slug": "components/card",
|
|
304
|
-
"import": "import { Card } from '@allxsmith/bestax-bulma';",
|
|
304
|
+
"import": "import { Card, CardHeader, CardHeaderTitle, CardHeaderIcon, CardImage, CardContent, CardFooter, CardFooterItem } from '@allxsmith/bestax-bulma';",
|
|
305
305
|
"compound": true,
|
|
306
306
|
"propCount": 51,
|
|
307
307
|
"exampleCount": 14
|
|
@@ -719,7 +719,7 @@
|
|
|
719
719
|
"category": "elements",
|
|
720
720
|
"purpose": "The `Figure` component renders a styled `<figure>` element with Bulma helper class integration.",
|
|
721
721
|
"slug": "elements/figure",
|
|
722
|
-
"import": "import { Figure } from '@allxsmith/bestax-bulma';",
|
|
722
|
+
"import": "import { Figure, FigureCaption } from '@allxsmith/bestax-bulma';",
|
|
723
723
|
"compound": true,
|
|
724
724
|
"propCount": 8,
|
|
725
725
|
"exampleCount": 7
|
|
@@ -983,7 +983,7 @@
|
|
|
983
983
|
"category": "components",
|
|
984
984
|
"purpose": "The `Message` component provides Bulma's flexible notice/message box for your Bulma React UI.",
|
|
985
985
|
"slug": "components/message",
|
|
986
|
-
"import": "import { Message } from '@allxsmith/bestax-bulma';",
|
|
986
|
+
"import": "import { Message, MessageHeader, MessageBody } from '@allxsmith/bestax-bulma';",
|
|
987
987
|
"compound": true,
|
|
988
988
|
"propCount": 12,
|
|
989
989
|
"exampleCount": 8
|
|
@@ -994,7 +994,7 @@
|
|
|
994
994
|
"category": "components",
|
|
995
995
|
"purpose": "The `Modal` component provides an empty, accessible overlay for arbitrary content — for a ready-made confirm or alert, reach for `Dialog` instead.",
|
|
996
996
|
"slug": "components/modal",
|
|
997
|
-
"import": "import { Modal } from '@allxsmith/bestax-bulma';",
|
|
997
|
+
"import": "import { Modal, ModalBackground, ModalContent, ModalClose, ModalCard, ModalCardHead, ModalCardTitle, ModalCardBody, ModalCardFoot } from '@allxsmith/bestax-bulma';",
|
|
998
998
|
"compound": true,
|
|
999
999
|
"propCount": 23,
|
|
1000
1000
|
"exampleCount": 10
|
|
@@ -1247,7 +1247,7 @@
|
|
|
1247
1247
|
"category": "components",
|
|
1248
1248
|
"purpose": "The `SegmentedControl` component renders a row of buttons where only one can be on, and tells a screen reader it's a radio group.",
|
|
1249
1249
|
"slug": "components/segmentedcontrol",
|
|
1250
|
-
"import": "import { SegmentedControl } from '@allxsmith/bestax-bulma';",
|
|
1250
|
+
"import": "import { SegmentedControl, SegmentedControlSegment } from '@allxsmith/bestax-bulma';",
|
|
1251
1251
|
"compound": true,
|
|
1252
1252
|
"propCount": 16,
|
|
1253
1253
|
"exampleCount": 11
|
|
@@ -1269,7 +1269,7 @@
|
|
|
1269
1269
|
"category": "components",
|
|
1270
1270
|
"purpose": "The `Sidebar` component provides a slide-out navigation panel that appears from the left or right side of the screen.",
|
|
1271
1271
|
"slug": "components/sidebar",
|
|
1272
|
-
"import": "import { Sidebar } from '@allxsmith/bestax-bulma';",
|
|
1272
|
+
"import": "import { Sidebar, SidebarHeader, SidebarTitle, SidebarClose, SidebarBody, SidebarFooter } from '@allxsmith/bestax-bulma';",
|
|
1273
1273
|
"compound": true,
|
|
1274
1274
|
"propCount": 22,
|
|
1275
1275
|
"exampleCount": 8
|
|
@@ -3336,6 +3336,41 @@
|
|
|
3336
3336
|
"path": "AppFrame.Nav",
|
|
3337
3337
|
"purpose": "The navigation of an AppFrame: a column beside the page from the breakpoint up, and a drawer below it."
|
|
3338
3338
|
},
|
|
3339
|
+
"CardContent": {
|
|
3340
|
+
"component": "Card",
|
|
3341
|
+
"path": "Card.Content",
|
|
3342
|
+
"purpose": "Card content compound component. Wraps children in a `.card-content` element."
|
|
3343
|
+
},
|
|
3344
|
+
"CardFooter": {
|
|
3345
|
+
"component": "Card",
|
|
3346
|
+
"path": "Card.Footer",
|
|
3347
|
+
"purpose": "Card footer compound component. Wraps children in a `.card-footer` element."
|
|
3348
|
+
},
|
|
3349
|
+
"CardFooterItem": {
|
|
3350
|
+
"component": "Card",
|
|
3351
|
+
"path": "Card.FooterItem",
|
|
3352
|
+
"purpose": "Card footer item compound component. Wraps children in a `.card-footer-item` span."
|
|
3353
|
+
},
|
|
3354
|
+
"CardHeader": {
|
|
3355
|
+
"component": "Card",
|
|
3356
|
+
"path": "Card.Header",
|
|
3357
|
+
"purpose": "Card header compound component. Wraps children in a `.card-header` element."
|
|
3358
|
+
},
|
|
3359
|
+
"CardHeaderIcon": {
|
|
3360
|
+
"component": "Card",
|
|
3361
|
+
"path": "Card.Header.Icon",
|
|
3362
|
+
"purpose": "Card header icon compound component. Renders a `.card-header-icon` button."
|
|
3363
|
+
},
|
|
3364
|
+
"CardHeaderTitle": {
|
|
3365
|
+
"component": "Card",
|
|
3366
|
+
"path": "Card.Header.Title",
|
|
3367
|
+
"purpose": "Card header title compound component. Renders a `.card-header-title` element."
|
|
3368
|
+
},
|
|
3369
|
+
"CardImage": {
|
|
3370
|
+
"component": "Card",
|
|
3371
|
+
"path": "Card.Image",
|
|
3372
|
+
"purpose": "Card image compound component. Wraps children in a `.card-image` element."
|
|
3373
|
+
},
|
|
3339
3374
|
"CarouselItem": {
|
|
3340
3375
|
"component": "Carousel",
|
|
3341
3376
|
"path": "CarouselItem",
|
|
@@ -3512,6 +3547,11 @@
|
|
|
3512
3547
|
"path": "Field.Label",
|
|
3513
3548
|
"purpose": "FieldLabel component for rendering a Bulma field label."
|
|
3514
3549
|
},
|
|
3550
|
+
"FigureCaption": {
|
|
3551
|
+
"component": "Figure",
|
|
3552
|
+
"path": "Figure.Caption",
|
|
3553
|
+
"purpose": "FigureCaption component for rendering a styled figcaption element."
|
|
3554
|
+
},
|
|
3515
3555
|
"HeroBody": {
|
|
3516
3556
|
"component": "Hero",
|
|
3517
3557
|
"path": "Hero.Body",
|
|
@@ -3593,6 +3633,56 @@
|
|
|
3593
3633
|
"path": "Menu.Section",
|
|
3594
3634
|
"purpose": "A section of the menu that opens and closes: its heading is a button drawn like `Menu.Label`, and its `Menu.List` of links shows while it's open."
|
|
3595
3635
|
},
|
|
3636
|
+
"MessageBody": {
|
|
3637
|
+
"component": "Message",
|
|
3638
|
+
"path": "Message.Body",
|
|
3639
|
+
"purpose": "Message body compound component. Renders a `.message-body` element."
|
|
3640
|
+
},
|
|
3641
|
+
"MessageHeader": {
|
|
3642
|
+
"component": "Message",
|
|
3643
|
+
"path": "Message.Header",
|
|
3644
|
+
"purpose": "Message header compound component. Renders a `.message-header` element."
|
|
3645
|
+
},
|
|
3646
|
+
"ModalBackground": {
|
|
3647
|
+
"component": "Modal",
|
|
3648
|
+
"path": "Modal.Background",
|
|
3649
|
+
"purpose": "Modal.Background - Renders the modal background overlay."
|
|
3650
|
+
},
|
|
3651
|
+
"ModalCard": {
|
|
3652
|
+
"component": "Modal",
|
|
3653
|
+
"path": "Modal.Card",
|
|
3654
|
+
"purpose": "Modal.Card - Renders modal card wrapper with compound components."
|
|
3655
|
+
},
|
|
3656
|
+
"ModalCardBody": {
|
|
3657
|
+
"component": "Modal",
|
|
3658
|
+
"path": "Modal.Card.Body",
|
|
3659
|
+
"purpose": "Modal.Card.Body - Renders modal card body section."
|
|
3660
|
+
},
|
|
3661
|
+
"ModalCardFoot": {
|
|
3662
|
+
"component": "Modal",
|
|
3663
|
+
"path": "Modal.Card.Foot",
|
|
3664
|
+
"purpose": "Modal.Card.Foot - Renders modal card footer section."
|
|
3665
|
+
},
|
|
3666
|
+
"ModalCardHead": {
|
|
3667
|
+
"component": "Modal",
|
|
3668
|
+
"path": "Modal.Card.Head",
|
|
3669
|
+
"purpose": "Modal.Card.Head - Renders modal card header section."
|
|
3670
|
+
},
|
|
3671
|
+
"ModalCardTitle": {
|
|
3672
|
+
"component": "Modal",
|
|
3673
|
+
"path": "Modal.Card.Title",
|
|
3674
|
+
"purpose": "Modal.Card.Title - Renders modal card title."
|
|
3675
|
+
},
|
|
3676
|
+
"ModalClose": {
|
|
3677
|
+
"component": "Modal",
|
|
3678
|
+
"path": "Modal.Close",
|
|
3679
|
+
"purpose": "Modal.Close - Renders modal close button with two variant styles."
|
|
3680
|
+
},
|
|
3681
|
+
"ModalContent": {
|
|
3682
|
+
"component": "Modal",
|
|
3683
|
+
"path": "Modal.Content",
|
|
3684
|
+
"purpose": "Modal.Content - Renders modal content wrapper for custom content."
|
|
3685
|
+
},
|
|
3596
3686
|
"NavbarBrand": {
|
|
3597
3687
|
"component": "Navbar",
|
|
3598
3688
|
"path": "Navbar.Brand",
|
|
@@ -3735,12 +3825,42 @@
|
|
|
3735
3825
|
"path": "Popover.Header",
|
|
3736
3826
|
"purpose": "The popover's title, which names the panel for assistive technology."
|
|
3737
3827
|
},
|
|
3828
|
+
"SegmentedControlSegment": {
|
|
3829
|
+
"component": "SegmentedControl",
|
|
3830
|
+
"path": "SegmentedControl.Segment",
|
|
3831
|
+
"purpose": "One option in the row: a `<button role=\"radio\">` that's checked while the group's value is its `value`, filled with the group's `color` and marked…"
|
|
3832
|
+
},
|
|
3738
3833
|
"SelectBase": {
|
|
3739
3834
|
"component": "Select",
|
|
3740
3835
|
"path": "SelectBase",
|
|
3741
3836
|
"purpose": "Bulma Select component with full Bulma helper class support.",
|
|
3742
3837
|
"standalone": "base"
|
|
3743
3838
|
},
|
|
3839
|
+
"SidebarBody": {
|
|
3840
|
+
"component": "Sidebar",
|
|
3841
|
+
"path": "Sidebar.Body",
|
|
3842
|
+
"purpose": "Main content area of the sidebar."
|
|
3843
|
+
},
|
|
3844
|
+
"SidebarClose": {
|
|
3845
|
+
"component": "Sidebar",
|
|
3846
|
+
"path": "Sidebar.Close",
|
|
3847
|
+
"purpose": "Close button for the sidebar."
|
|
3848
|
+
},
|
|
3849
|
+
"SidebarFooter": {
|
|
3850
|
+
"component": "Sidebar",
|
|
3851
|
+
"path": "Sidebar.Footer",
|
|
3852
|
+
"purpose": "Footer area of the sidebar."
|
|
3853
|
+
},
|
|
3854
|
+
"SidebarHeader": {
|
|
3855
|
+
"component": "Sidebar",
|
|
3856
|
+
"path": "Sidebar.Header",
|
|
3857
|
+
"purpose": "Container for the sidebar header."
|
|
3858
|
+
},
|
|
3859
|
+
"SidebarTitle": {
|
|
3860
|
+
"component": "Sidebar",
|
|
3861
|
+
"path": "Sidebar.Title",
|
|
3862
|
+
"purpose": "Title text inside the header."
|
|
3863
|
+
},
|
|
3744
3864
|
"SplitterPane": {
|
|
3745
3865
|
"component": "Splitter",
|
|
3746
3866
|
"path": "Splitter.Pane",
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"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}"
|
|
102
102
|
}
|
|
103
103
|
],
|
|
104
|
-
"accessibility": "- **Labeling:** Always provide descriptive content for buttons for screen readers.\n- **Icons beside text:** Leave the `Icon` unnamed, so the text alone names the button. The icons in [With an Icon](https://bestax.io/docs/api/elements/button#with-an-icon) write out `aria-hidden=\"true\"`, and `Icon` would render it for them anyway, since they have no `ariaLabel`, `aria-label` or `aria-labelledby` to name them and no `role` or `tabIndex` of their own. A named icon joins the button's name instead, so `ariaLabel=\"Download\"` on the icon of a Download button makes a screen reader announce \"Download Download\".\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- **Focus ring:** Bulma shows a focused button with its border and a shadow. A ghost button has neither, and forced colors (Windows' contrast themes) drops the shadow and sets the border's color, so bestax's styles give a focused ghost button, and every focused button in forced colors, an outline. `isFocused` draws it too.\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\nA button that shows only an icon is an [`IconButton`](https://bestax.io/docs/api/elements/iconbutton), whose types require an\n`aria-label` or an `aria-labelledby`, and whose `isRounded` makes a circle. On a plain `Button` holding only\nan icon, name it with `aria-label` yourself.\n:::",
|
|
104
|
+
"accessibility": "- **Labeling:** Always provide descriptive content for buttons for screen readers.\n- **Icons beside text:** Leave the `Icon` unnamed, so the text alone names the button. The icons in [With an Icon](https://bestax.io/docs/api/elements/button#with-an-icon) write out `aria-hidden=\"true\"`, and `Icon` would render it for them anyway, since they have no `ariaLabel`, `aria-label` or `aria-labelledby` to name them and no `role` or `tabIndex` of their own. A named icon joins the button's name instead, so `ariaLabel=\"Download\"` on the icon of a Download button makes a screen reader announce \"Download Download\".\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- **Focus ring:** Bulma shows a focused button with its border and a shadow. A ghost button has neither, and forced colors (Windows' contrast themes) drops the shadow and sets the border's color, so bestax's styles give a focused ghost button, and every focused button in forced colors, an outline. `isFocused` draws it too.\n- **Forced colors:** In Windows' contrast themes a colored button keeps a 1px border, so it still has an edge when the theme replaces its fill, while an outlined button and a `text` one are left as they are.\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\nA button that shows only an icon is an [`IconButton`](https://bestax.io/docs/api/elements/iconbutton), whose types require an\n`aria-label` or an `aria-labelledby`, and whose `isRounded` makes a circle. On a plain `Button` holding only\nan icon, name it with `aria-label` yourself.\n:::",
|
|
105
105
|
"related": [
|
|
106
106
|
"Buttons",
|
|
107
107
|
"CopyButton",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"related": ["Icon", "Image", "useBulmaClasses"],
|
|
67
67
|
"storybook": "https://bestax.io/storybook/?path=/story/components-card--default",
|
|
68
68
|
"summary": "The `Card` component renders a Bulma-styled card with optional header, image, content, and footer.",
|
|
69
|
-
"import": "import { Card } from '@allxsmith/bestax-bulma';",
|
|
69
|
+
"import": "import { Card, CardHeader, CardHeaderTitle, CardHeaderIcon, CardImage, CardContent, CardFooter, CardFooterItem } from '@allxsmith/bestax-bulma';",
|
|
70
70
|
"sourceFile": "bulma-ui/src/components/Card.tsx",
|
|
71
71
|
"rootClass": "card",
|
|
72
72
|
"parts": [
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"code": "<Carousel repeat={false}>\n <CarouselItem>\n <Hero color=\"danger\" size=\"medium\">\n <Hero.Body textAlign=\"centered\">\n <Paragraph textColor=\"white\">First (no previous)</Paragraph>\n </Hero.Body>\n </Hero>\n </CarouselItem>\n <CarouselItem>\n <Hero color=\"warning\" size=\"medium\">\n <Hero.Body textAlign=\"centered\">\n <Paragraph>Middle slide</Paragraph>\n </Hero.Body>\n </Hero>\n </CarouselItem>\n <CarouselItem>\n <Hero color=\"success\" size=\"medium\">\n <Hero.Body textAlign=\"centered\">\n <Paragraph textColor=\"white\">Last (no next)</Paragraph>\n </Hero.Body>\n </Hero>\n </CarouselItem>\n</Carousel>"
|
|
71
71
|
}
|
|
72
72
|
],
|
|
73
|
-
"accessibility": "- Uses `role=\"region\"` with `aria-roledescription=\"carousel\"`\n- Each item is a `group` with `aria-roledescription=\"slide\"`, named for its place, such as \"2 of 6\". An item's own `aria-label` or `aria-labelledby` takes the place of that name\n- Items out of view are `aria-hidden` and `inert`, so screen readers skip them and nothing in them takes focus. With several in view, every item in view is exposed. The copies a loop adds at each end of the track follow the same rule, so where the view runs past the last item, the copies on screen are the ones exposed\n- The track is a polite live region, so what comes into view is announced, except while autoplay is moving it (`aria-live=\"off\"`)\n- Autoplay waits while the pointer is over the carousel (with `pauseOnHover`) and while focus is inside one of its items, so an item being read or used never moves out of view\n- When something else takes the item holding focus out of view (a swipe, a change of width that changes the count, a new controlled `value`, or the item's removal), focus moves to the first item in view rather than dropping to the page\n- Navigation arrows have `aria-label` for screen readers\n- Indicators use `role=\"tablist\"` and `role=\"tab\"` semantics, one for each position a step can land on\n- The Left and Right arrow keys move the carousel while focus is on its arrows or indicators. Inside an item they're left to the item's content, such as a field or a slider\n- Previous/Next buttons are properly disabled at boundaries when not repeating",
|
|
73
|
+
"accessibility": "- Uses `role=\"region\"` with `aria-roledescription=\"carousel\"`\n- Each item is a `group` with `aria-roledescription=\"slide\"`, named for its place, such as \"2 of 6\". An item's own `aria-label` or `aria-labelledby` takes the place of that name\n- Items out of view are `aria-hidden` and `inert`, so screen readers skip them and nothing in them takes focus. With several in view, every item in view is exposed. The copies a loop adds at each end of the track follow the same rule, so where the view runs past the last item, the copies on screen are the ones exposed\n- The track is a polite live region, so what comes into view is announced, except while autoplay is moving it (`aria-live=\"off\"`)\n- Autoplay waits while the pointer is over the carousel (with `pauseOnHover`) and while focus is inside one of its items, so an item being read or used never moves out of view\n- When something else takes the item holding focus out of view (a swipe, a change of width that changes the count, a new controlled `value`, or the item's removal), focus moves to the first item in view rather than dropping to the page\n- Navigation arrows have `aria-label` for screen readers\n- Indicators use `role=\"tablist\"` and `role=\"tab\"` semantics, one for each position a step can land on\n- The Left and Right arrow keys move the carousel while focus is on its arrows or indicators. Inside an item they're left to the item's content, such as a field or a slider\n- Previous/Next buttons are properly disabled at boundaries when not repeating\n- On a right-to-left page the slides run from right to left. The previous arrow sits on the right, at the start of the line, and the next arrow on the left, and the built-in chevrons flip to match. An `iconPrev` or `iconNext` is drawn as you give it. <kbd>ArrowLeft</kbd> and a swipe to the right go to the next slide, the way the track moves.",
|
|
74
74
|
"related": ["Modal", "Tabs"],
|
|
75
75
|
"storybook": "https://bestax.io/storybook/?path=/story/components-carousel",
|
|
76
76
|
"summary": "The `Carousel` component provides an image/content slider with navigation arrows and indicators.",
|
|
@@ -132,7 +132,7 @@
|
|
|
132
132
|
"name": "hasDrag",
|
|
133
133
|
"type": "boolean",
|
|
134
134
|
"default": "true",
|
|
135
|
-
"description": "Enable drag/swipe navigation. Default: true. A swipe moves one step, however far it travels.",
|
|
135
|
+
"description": "Enable drag/swipe navigation. Default: true. A swipe moves one step, however far it travels. A swipe toward the start of the line goes on, so on a right-to-left page a swipe right brings the next slide in.",
|
|
136
136
|
"required": false,
|
|
137
137
|
"inherited": false,
|
|
138
138
|
"deprecated": false
|
|
@@ -267,7 +267,7 @@
|
|
|
267
267
|
"name": "iconPrev",
|
|
268
268
|
"type": "string",
|
|
269
269
|
"default": null,
|
|
270
|
-
"description": "Icon name for the previous arrow button.",
|
|
270
|
+
"description": "Icon name for the previous arrow button. On a right-to-left page that button sits on the right and the built-in chevron flips to point there, but an icon you name is drawn as given, so pick one that points the way the page reads.",
|
|
271
271
|
"required": false,
|
|
272
272
|
"inherited": false,
|
|
273
273
|
"deprecated": false
|
|
@@ -276,7 +276,7 @@
|
|
|
276
276
|
"name": "iconNext",
|
|
277
277
|
"type": "string",
|
|
278
278
|
"default": null,
|
|
279
|
-
"description": "Icon name for the next arrow button.",
|
|
279
|
+
"description": "Icon name for the next arrow button. On a right-to-left page it sits on the left, and an icon you name is drawn as given, as with `iconPrev`.",
|
|
280
280
|
"required": false,
|
|
281
281
|
"inherited": false,
|
|
282
282
|
"deprecated": false
|
|
@@ -283,7 +283,7 @@
|
|
|
283
283
|
"name": "position",
|
|
284
284
|
"type": "'bottom-left' | 'bottom-right' | 'top-left' | 'top-right' | 'auto'",
|
|
285
285
|
"default": "'bottom-left'",
|
|
286
|
-
"description": "
|
|
286
|
+
"description": "Where the panel opens against the field. Left out, it opens below and lines up with the field's start edge, which is its right edge when the picker reads right to left. A corner you pass stays physical, so `bottom-left` lines up the left edges either way.",
|
|
287
287
|
"required": false,
|
|
288
288
|
"inherited": true,
|
|
289
289
|
"deprecated": false
|
|
@@ -529,7 +529,7 @@
|
|
|
529
529
|
"name": "position",
|
|
530
530
|
"type": "'bottom-left' | 'bottom-right' | 'top-left' | 'top-right' | 'auto'",
|
|
531
531
|
"default": "'bottom-left'",
|
|
532
|
-
"description": "
|
|
532
|
+
"description": "Where the panel opens against the field. Left out, it opens below and lines up with the field's start edge, which is its right edge when the picker reads right to left. A corner you pass stays physical, so `bottom-left` lines up the left edges either way.",
|
|
533
533
|
"required": false,
|
|
534
534
|
"inherited": false,
|
|
535
535
|
"deprecated": false
|
|
@@ -178,7 +178,7 @@
|
|
|
178
178
|
"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}"
|
|
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. 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).",
|
|
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. 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).\n- On a right-to-left page the launcher sits at the end of the line and the calendar icon at the start, and the previous-month chevron points right. The month names follow the page.",
|
|
182
182
|
"related": ["DateTimeInput", "Input", "TimeInput"],
|
|
183
183
|
"storybook": "https://bestax.io/storybook/?path=/story/form-dateinput",
|
|
184
184
|
"summary": "The `DateInput` component is a form input that opens a popover calendar for date selection.",
|
|
@@ -546,7 +546,7 @@
|
|
|
546
546
|
"name": "position",
|
|
547
547
|
"type": "'bottom-left' | 'bottom-right' | 'top-left' | 'top-right' | 'auto'",
|
|
548
548
|
"default": "'bottom-left'",
|
|
549
|
-
"description": "
|
|
549
|
+
"description": "Where the popover opens against the field. Left out, it opens below and lines up with the field's start edge, which is its right edge when the picker reads right to left. A corner you pass stays physical, so `bottom-left` lines up the left edges either way.",
|
|
550
550
|
"required": false,
|
|
551
551
|
"inherited": true,
|
|
552
552
|
"deprecated": false
|
|
@@ -908,7 +908,7 @@
|
|
|
908
908
|
"name": "position",
|
|
909
909
|
"type": "'bottom-left' | 'bottom-right' | 'top-left' | 'top-right' | 'auto'",
|
|
910
910
|
"default": "'bottom-left'",
|
|
911
|
-
"description": "
|
|
911
|
+
"description": "Where the popover opens against the field. Left out, it opens below and lines up with the field's start edge, which is its right edge when the picker reads right to left. A corner you pass stays physical, so `bottom-left` lines up the left edges either way.",
|
|
912
912
|
"required": false,
|
|
913
913
|
"inherited": false,
|
|
914
914
|
"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. Inside a labeled `Field`, that `Field`'s label names the group the same way, whether the `Field` holds `DateRangeInput` or a `DateRangeInputBase` you composed in a `Control` yourself, `inline` or not. 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.",
|
|
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, whether the `Field` holds `DateRangeInput` or a `DateRangeInputBase` you composed in a `Control` yourself, `inline` or not. 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.\n- On a right-to-left page the launcher sits at the end of the line and the calendar icon at the start, and the previous-month chevron points right.",
|
|
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.",
|
|
@@ -405,7 +405,7 @@
|
|
|
405
405
|
"name": "position",
|
|
406
406
|
"type": "'bottom-left' | 'bottom-right' | 'top-left' | 'top-right' | 'auto'",
|
|
407
407
|
"default": "'bottom-left'",
|
|
408
|
-
"description": "
|
|
408
|
+
"description": "Where the popover opens against the field. Left out, it opens below and lines up with the field's start edge, which is its right edge when the picker reads right to left. A corner you pass stays physical, so `bottom-left` lines up the left edges either way.",
|
|
409
409
|
"required": false,
|
|
410
410
|
"inherited": true,
|
|
411
411
|
"deprecated": false
|
|
@@ -794,7 +794,7 @@
|
|
|
794
794
|
"name": "position",
|
|
795
795
|
"type": "'bottom-left' | 'bottom-right' | 'top-left' | 'top-right' | 'auto'",
|
|
796
796
|
"default": "'bottom-left'",
|
|
797
|
-
"description": "
|
|
797
|
+
"description": "Where the popover opens against the field. Left out, it opens below and lines up with the field's start edge, which is its right edge when the picker reads right to left. A corner you pass stays physical, so `bottom-left` lines up the left edges either way.",
|
|
798
798
|
"required": false,
|
|
799
799
|
"inherited": false,
|
|
800
800
|
"deprecated": false
|
|
@@ -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- 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.",
|
|
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.\n- On a right-to-left page the launcher sits at the end of the line and the calendar icon at the start. The time wheels keep `dir=\"ltr\"`.",
|
|
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.",
|
|
@@ -529,7 +529,7 @@
|
|
|
529
529
|
"name": "position",
|
|
530
530
|
"type": "'bottom-left' | 'bottom-right' | 'top-left' | 'top-right' | 'auto'",
|
|
531
531
|
"default": "'bottom-left'",
|
|
532
|
-
"description": "
|
|
532
|
+
"description": "Where the popover opens against the field. Left out, it opens below and lines up with the field's start edge, which is its right edge when the picker reads right to left. A corner you pass stays physical, so `bottom-left` lines up the left edges either way.",
|
|
533
533
|
"required": false,
|
|
534
534
|
"inherited": true,
|
|
535
535
|
"deprecated": false
|
|
@@ -954,7 +954,7 @@
|
|
|
954
954
|
"name": "position",
|
|
955
955
|
"type": "'bottom-left' | 'bottom-right' | 'top-left' | 'top-right' | 'auto'",
|
|
956
956
|
"default": "'bottom-left'",
|
|
957
|
-
"description": "
|
|
957
|
+
"description": "Where the popover opens against the field. Left out, it opens below and lines up with the field's start edge, which is its right edge when the picker reads right to left. A corner you pass stays physical, so `bottom-left` lines up the left edges either way.",
|
|
958
958
|
"required": false,
|
|
959
959
|
"inherited": false,
|
|
960
960
|
"deprecated": false
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"related": ["Code", "Image", "Pre", "useBulmaClasses"],
|
|
39
39
|
"storybook": "https://bestax.io/storybook/?path=/story/elements-figure--default",
|
|
40
40
|
"summary": "The `Figure` component renders a styled `<figure>` element with Bulma helper class integration.",
|
|
41
|
-
"import": "import { Figure } from '@allxsmith/bestax-bulma';",
|
|
41
|
+
"import": "import { Figure, FigureCaption } from '@allxsmith/bestax-bulma';",
|
|
42
42
|
"sourceFile": "bulma-ui/src/elements/Figure.tsx",
|
|
43
43
|
"rootClass": null,
|
|
44
44
|
"parts": [
|
|
@@ -113,5 +113,5 @@
|
|
|
113
113
|
}
|
|
114
114
|
],
|
|
115
115
|
"cssVars": [],
|
|
116
|
-
"doc": "# LocaleProvider\n\n## Overview\n\n`LocaleProvider` sets the language and writing direction for the part of the app inside it, on a wrapper `<div>` and on what the library portals out of it.\n\nIt takes a `locale` and a `dir`, and each works alone. A `locale` such as `\"ar-EG\"` becomes the wrapper's `lang`, and its script decides the direction, so `dir=\"rtl\"` comes with it. A `dir` sets the direction whatever the locale, for a right-to-left layout with no particular language, or a locale whose script reads one way on a page laid out the other. A nested provider keeps whatever it leaves unset.\n\nThe direction lives on the wrapper as a `dir` attribute, so CSS follows it, and so do the components that read the direction they're laid out in, as they follow `<html dir>`. A page whose `<html>` already has `dir=\"rtl\"` needs no provider for that. What the provider adds is the rest:\n\n- a section of the page in another language or direction than the page around it;\n- the content the library portals to the end of `document.body`, such as a `Popover` panel, a `Modal` with `portal`, a `Toast` or a `Portal`'s children, which leaves the section it came from and gets the provider's `dir` and `lang` back;\n- the date and time pickers inside, which take its `locale` and start the week on that locale's first day;\n- the numbers the library writes, such as page numbers, badge counts and a slider's output, and the filtering in `Combobox`, `Autocomplete`, `Taginput` and `Command`, which follow the `locale` too.\n\nWithout a provider none of this changes: a picker uses the runtime's own locale and starts the week on Sunday, numbers are written as they always have been, and filtering ignores case only.\n\n---\n\n## Import\n\n```tsx\nimport { LocaleProvider, useLocale } from '@allxsmith/bestax-bulma';\n```\n\n---\n\n## Hooks\n\n### useLocale\n\nReturns the `locale` and `dir` the nearest provider sets, both `undefined` outside one. The locale is in its canonical form, so `\"en-us\"` comes back as `\"en-US\"`. Use it for your own `Intl` calls, so they match the components around them, or for `dir` and `lang` on content you portal yourself.\n\n```tsx\nfunction Price({ amount }: { amount: number }) {\n const { locale } = useLocale();\n return (\n <span>\n {new Intl.NumberFormat(locale, {\n style: 'currency',\n currency: 'EUR',\n }).format(amount)}\n </span>\n );\n}\n```\n\nFor numbers, [`NumberFormatter`](https://bestax.io/docs/api/elements/numberformatter) and its `useNumberFormat` hook do this for you, and build one formatter for each set of options rather than one on every render.\n\nIt isn't the direction of the page: with no provider, or one that sets no direction, `<html dir>` still decides. To act on the direction an element is laid out in, read `getComputedStyle(element).direction`.\n\n---\n\n## Usage\n\n### A Right-to-Left Section\n\nA `locale` alone sets the direction of its script. Arabic reads right to left, so the wrapper gets `dir=\"rtl\"` and `lang=\"ar-EG\"`, and the steps lay out from the right.\n\n```tsx live\n<LocaleProvider locale=\"ar-EG\">\n <Steps\n value={1}\n items={[{ label: 'السلة' }, { label: 'الشحن' }, { label: 'الدفع' }]}\n />\n</LocaleProvider>\n```\n\nThe wrapper is a plain `<div>` with no class of its own. It takes the helper props and any other attributes, and forwards its `ref`.\n\n### Direction Only\n\n`dir` sets the direction and leaves the language alone. It also wins over a `locale`'s own direction.\n\n```tsx live\n<LocaleProvider dir=\"rtl\">\n <Buttons>\n <Button color=\"primary\">First</Button>\n <Button>Second</Button>\n </Buttons>\n</LocaleProvider>\n```\n\n### Nested Providers\n\nAn inner provider keeps whatever it leaves unset. One that sets only a `locale` takes that locale's direction, so a French quote inside a Hebrew section reads left to right, and one that sets only a `dir` keeps the outer locale.\n\n```tsx live\n<LocaleProvider locale=\"he\">\n <Content>\n <p>הציטוט האהוב עליי:</p>\n <LocaleProvider locale=\"fr\">\n <blockquote>La simplicité est la sophistication suprême.</blockquote>\n </LocaleProvider>\n </Content>\n</LocaleProvider>\n```\n\n### Date Pickers\n\nThe date and time pickers take the provider's `locale` unless they have their own, for their day and month names and any `Intl` format. Inside a provider, the week starts on the first day of the locale the picker uses: Monday for `\"de\"`, Saturday for `\"ar-EG\"`, Sunday for `\"en-US\"`. A picker's own `firstDayOfWeek` still wins, and a picker with its own `dayNames` keeps Sunday unless it sets `firstDayOfWeek` too, since it shows those names exactly as given.\n\n```tsx live\n<LocaleProvider locale=\"de\">\n <DateInput inline label=\"Liefertermin\" />\n</LocaleProvider>\n```\n\nOutside a provider a picker keeps Sunday, even with a `locale` of its own, so pages that never asked for a different first day don't get one. The first day comes from a copy of [CLDR](https://cldr.unicode.org/)'s week data that the library carries, rather than from each browser's, because browsers disagree about a few regions, China among them, and a calendar rendered on the server has to come out the same in the browser. A `-u-fw-` extension in the tag, such as `\"en-US-u-fw-mon\"`, picks the day outright.\n\n### Numbers and Matching\n\nWith a `locale`, the numbers the library writes itself are written the way that locale writes them, with its digits and separators: `Pagination`'s page numbers, `Steps` markers, a `Badge` count, the `Avatars` surplus, a `RingProgress` in sections, `Rate`'s score, the `Slider` output, `Taginput`'s counter and the count of files `File` shows. Where an accessible name repeats a number on screen, as a page link's does, it's written the same way, so the name still holds the text. A label function you pass, such as `getPageLabel` or `formatOutput`, takes over as before.\n\n```tsx live\n<LocaleProvider locale=\"ar-EG\">\n <Pagination total={12} current={5} />\n</LocaleProvider>\n```\n\nNumbers of your own follow it through [`NumberFormatter`](https://bestax.io/docs/api/elements/numberformatter), and through its `useNumberFormat` hook for text outside JSX, such as an `aria-label`. Outside a provider, those write in the runtime's locale, while the library's own numbers stay as they always were.\n\nTyping in `Combobox`, `Autocomplete`, `Taginput` and `Command` filters the list the way the language compares letters: case and accents are ignored where it treats them as the same letter, so \"cafe\" finds \"Café\", while in Swedish \"a\" doesn't find \"å\", a letter of its own there. Vowel marks the language leaves out of comparisons, such as Arabic harakat and Hebrew niqqud, don't count on either side, so a name typed without them finds one written with them, and the other way round.\n\n```tsx live\n<LocaleProvider locale=\"fr\">\n <Combobox\n label=\"Boisson\"\n data={['Café', 'Thé', 'Chocolat chaud']}\n placeholder=\"Tapez « the »\"\n />\n</LocaleProvider>\n```\n\nThe pickers' digits stay as they are: their typed text is a token format of ASCII digits, and a calendar in another set of digits would sit under it. Numbers inside the library's English labels that aren't on screen, such as a carousel slide's \"1 of 3\", stay as they are too, since they get translated together with their words.\n\n### Portaled Content\n\nWhat the library portals renders outside the provider's wrapper, at the end of `document.body` or in the `portalContainer` a [`ConfigProvider`](https://bestax.io/docs/api/helpers/config) sets. Inside a provider, that content keeps the provider's `dir` and `lang`. That covers a `Portal`'s children, a `Popover`, `HoverCard` or `ContextMenu` panel, a `Combobox` menu or picker popover with `appendToBody`, a `Modal` or `Dialog` with `portal`, a `Sidebar`, and toasts and notifications.\n\nA container inside the provider's own wrapper takes the content as it is, and the content follows the provider through the page. Any other, `document.body` included, gets it inside one `<div>` carrying the values, with `display: contents`, so it adds no box and changes no layout. It is still an element, though, so content that must be its container's direct child, such as a `<tr>` portaled into a `<tbody>`, belongs in a container inside the provider. Which of the two is settled when the content mounts: switching the locale while a dialog or a toast is open updates that `<div>` in place, so what's open keeps its typed text, focus and timers.\n\n```tsx live\n<LocaleProvider locale=\"fa\">\n <Popover trigger={<Button>جزئیات</Button>} appendToBody ariaLabel=\"جزئیات\">\n <Popover.Body>\n این پنل بیرون از بخش رندر میشود و همچنان راستبهچپ است.\n </Popover.Body>\n </Popover>\n</LocaleProvider>\n```\n\nA date or time picker with a `locale` of its own is read the way a nested provider is: its popover, portaled or not, and an inline calendar take its `lang`, and the direction of its locale unless it has a `dir` of its own. So a French picker in an Arabic section shows a French calendar laid out left to right.\n\nFor content you portal yourself without `Portal`, put the values from `useLocale()` on it.\n\n### Server Rendering\n\nThe wrapper's `dir` and `lang` come from its props, so the server and the browser write the same ones, and portaled content only renders after hydration.\n\nSet a `locale` when an `inline` picker renders on the server. With none, `Intl` names its days in the runtime's own language, which is the server's on the server and the reader's in the browser, and the two renders don't match when those differ. With a locale they match, as long as the server's `Intl` data and the browser's spell the names alike. They don't always: Node and Safari write the short name for Saturday differently in Arabic. Where that matters, pass the picker its own `dayNames`, and with them the `firstDayOfWeek` they start on. The calendar shows `dayNames` exactly as given, from the first column, so a picker that brings its own keeps the week on Sunday, as it did before the provider, unless `firstDayOfWeek` says otherwise.\n\n```tsx live\n<LocaleProvider locale=\"ar-EG\">\n <DateInput\n inline\n label=\"تاريخ التسليم\"\n firstDayOfWeek={6}\n dayNames={[\n 'السبت',\n 'الأحد',\n 'الاثنين',\n 'الثلاثاء',\n 'الأربعاء',\n 'الخميس',\n 'الجمعة',\n ]}\n />\n</LocaleProvider>\n```\n\nFor an app that's in one language throughout, also set `lang` and `dir` on `<html>` in your page shell. That reaches what sits outside any provider, and the provider still carries them onto portaled content.\n\nIn the Next.js App Router, render it straight from the root layout, which stays a Server Component. `LocaleProvider` holds React context, so it's a client component, and bestax-bulma marks it one, so the layout can render it without a `'use client'` wrapper of its own. The `locale` and `children` here are values a Server Component can pass. It also takes the wrapper `<div>`'s attributes, and an event handler among them can't cross from a Server Component, so set one from a client component:\n\n```tsx title=\"app/layout.tsx\"\nimport type { ReactNode } from 'react';\nimport { LocaleProvider } from '@allxsmith/bestax-bulma';\n\nexport default function RootLayout({ children }: { children: ReactNode }) {\n return (\n <html lang=\"ar-EG\" dir=\"rtl\">\n <body>\n <LocaleProvider locale=\"ar-EG\">{children}</LocaleProvider>\n </body>\n </html>\n );\n}\n```\n\n### A Locale Intl Doesn't Accept\n\nA tag `Intl` refuses, such as `\"en_US\"` with an underscore, is ignored: the provider writes no `lang`, keeps an outer provider's locale, and warns once in development. A `NumberFormatter`'s or `useNumberFormat`'s own `locale` is checked the same way: a tag `Intl` refuses is ignored with a warning, and the number is written in the provider's locale. A picker's own `locale` isn't checked this way, and `Intl` throws on such a tag when the picker formats with it, as it always has.\n\n---\n\n## Accessibility\n\n- `lang` tells a screen reader which voice and pronunciation to use, and a translation tool what it's reading. The provider puts it on its wrapper and on portaled content, so a dialog or a notification announced from the end of the page comes in the same language.\n- `dir` decides the reading order of the content inside, and which side text starts on. Set the one the content is written in: a left-to-right quote in a right-to-left page needs its own provider or `dir`.\n- The provider changes no focus order and adds no role. The element it wraps portaled content in has `display: contents`, so it adds no box and no landmark.\n\n---\n\n## Related Components\n\n- [`ConfigProvider`](https://bestax.io/docs/api/helpers/config): The class prefix, icon library and portal container. A nested one replaces the outer one's settings, which is why the locale lives here instead.\n- [`Portal`](https://bestax.io/docs/api/helpers/portal): Inside a `LocaleProvider`, its children keep the provider's `dir` and `lang`.\n- [`DateInput`](https://bestax.io/docs/api/form/datetime/dateinput): Takes the provider's locale and first day of the week.\n- [`NumberFormatter`](https://bestax.io/docs/api/elements/numberformatter): Writes a number in the provider's locale, and `useNumberFormat` does the same for text outside JSX.\n- [`Theme`](https://bestax.io/docs/api/helpers/theme): Its scoped wrapper is the same idea for CSS variables.\n\n---\n\n## Additional Resources\n\n- [Storybook: LocaleProvider Stories](https://bestax.io/storybook/?path=/story/helpers-localeprovider--default)\n- [W3C: Structural markup and right-to-left text in HTML](https://www.w3.org/International/questions/qa-html-dir)\n- [MDN: the `lang` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang)\n- [MDN: `Intl.Locale.prototype.getWeekInfo()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getWeekInfo)\n\n---\n\n## Props\n\n| Prop | Type | Default | Description |\n| ---------- | ------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| `locale` | `string` | — | A BCP 47 language tag, such as `\"de\"` or `\"ar-EG\"`: the wrapper's `lang`, the pickers' default `locale`, and, with no `dir`, the direction of its script. Unset, a nested provider keeps the outer one's. A tag `Intl` refuses is ignored. |\n| `dir` | `'ltr'` \\| `'rtl'` | — | The direction, whatever the locale. Unset, it follows this provider's `locale`, else an outer provider's direction, else the page's. |\n| `children` | `ReactNode` | — | The part of the app it covers. |\n\nThe helper props, the other attributes of a `<div>` and the `ref` land on the wrapper."
|
|
116
|
+
"doc": "# LocaleProvider\n\n## Overview\n\n`LocaleProvider` sets the language and writing direction for the part of the app inside it, on a wrapper `<div>` and on what the library portals out of it.\n\nIt takes a `locale` and a `dir`, and each works alone. A `locale` such as `\"ar-EG\"` becomes the wrapper's `lang`, and its script decides the direction, so `dir=\"rtl\"` comes with it. A `dir` sets the direction whatever the locale, for a right-to-left layout with no particular language, or a locale whose script reads one way on a page laid out the other. A nested provider keeps whatever it leaves unset.\n\nThe direction lives on the wrapper as a `dir` attribute, so CSS follows it, and so do the components that read the direction they're laid out in, as they follow `<html dir>`. A page whose `<html>` already has `dir=\"rtl\"` needs no provider for that. What the provider adds is the rest:\n\n- a section of the page in another language or direction than the page around it;\n- the content the library portals to the end of `document.body`, such as a `Popover` panel, a `Modal` with `portal`, a `Toast` or a `Portal`'s children, which leaves the section it came from and gets the provider's `dir` and `lang` back;\n- the date and time pickers inside, which take its `locale` and start the week on that locale's first day;\n- the numbers the library writes, such as page numbers, badge counts and a slider's output, and the filtering in `Combobox`, `Autocomplete`, `Taginput` and `Command`, which follow the `locale` too.\n\nWithout a provider none of this changes: a picker uses the runtime's own locale and starts the week on Sunday, numbers are written as they always have been, and filtering ignores case only.\n\n---\n\n## Import\n\n```tsx\nimport { LocaleProvider, useLocale } from '@allxsmith/bestax-bulma';\n```\n\n---\n\n## Hooks\n\n### useLocale\n\nReturns the `locale` and `dir` the nearest provider sets, both `undefined` outside one. The locale is in its canonical form, so `\"en-us\"` comes back as `\"en-US\"`. Use it for your own `Intl` calls, so they match the components around them, or for `dir` and `lang` on content you portal yourself.\n\n```tsx\nfunction Price({ amount }: { amount: number }) {\n const { locale } = useLocale();\n return (\n <span>\n {new Intl.NumberFormat(locale, {\n style: 'currency',\n currency: 'EUR',\n }).format(amount)}\n </span>\n );\n}\n```\n\nFor numbers, [`NumberFormatter`](https://bestax.io/docs/api/elements/numberformatter) and its `useNumberFormat` hook do this for you, and build one formatter for each set of options rather than one on every render.\n\nIt isn't the direction of the page: with no provider, or one that sets no direction, `<html dir>` still decides. To act on the direction an element is laid out in, read `getComputedStyle(element).direction`.\n\n---\n\n## Usage\n\n### A Right-to-Left Section\n\nA `locale` alone sets the direction of its script. Arabic reads right to left, so the wrapper gets `dir=\"rtl\"` and `lang=\"ar-EG\"`, and the steps lay out from the right.\n\n```tsx live\n<LocaleProvider locale=\"ar-EG\">\n <Steps\n value={1}\n items={[{ label: 'السلة' }, { label: 'الشحن' }, { label: 'الدفع' }]}\n />\n</LocaleProvider>\n```\n\nThe wrapper is a plain `<div>` with no class of its own. It takes the helper props and any other attributes, and forwards its `ref`.\n\n### Direction Only\n\n`dir` sets the direction and leaves the language alone. It also wins over a `locale`'s own direction.\n\n```tsx live\n<LocaleProvider dir=\"rtl\">\n <Buttons>\n <Button color=\"primary\">First</Button>\n <Button>Second</Button>\n </Buttons>\n</LocaleProvider>\n```\n\n### Nested Providers\n\nAn inner provider keeps whatever it leaves unset. One that sets only a `locale` takes that locale's direction, so a French quote inside a Hebrew section reads left to right, and one that sets only a `dir` keeps the outer locale.\n\n```tsx live\n<LocaleProvider locale=\"he\">\n <Content>\n <p>הציטוט האהוב עליי:</p>\n <LocaleProvider locale=\"fr\">\n <blockquote>La simplicité est la sophistication suprême.</blockquote>\n </LocaleProvider>\n </Content>\n</LocaleProvider>\n```\n\n### Date Pickers\n\nThe date and time pickers take the provider's `locale` unless they have their own, for their day and month names and any `Intl` format. Inside a provider, the week starts on the first day of the locale the picker uses: Monday for `\"de\"`, Saturday for `\"ar-EG\"`, Sunday for `\"en-US\"`. A picker's own `firstDayOfWeek` still wins, and a picker with its own `dayNames` keeps Sunday unless it sets `firstDayOfWeek` too, since it shows those names exactly as given.\n\n```tsx live\n<LocaleProvider locale=\"de\">\n <DateInput inline label=\"Liefertermin\" />\n</LocaleProvider>\n```\n\nOutside a provider a picker keeps Sunday, even with a `locale` of its own, so pages that never asked for a different first day don't get one. The first day comes from a copy of [CLDR](https://cldr.unicode.org/)'s week data that the library carries, rather than from each browser's, because browsers disagree about a few regions, China among them, and a calendar rendered on the server has to come out the same in the browser. A `-u-fw-` extension in the tag, such as `\"en-US-u-fw-mon\"`, picks the day outright.\n\n### Numbers and Matching\n\nWith a `locale`, the numbers the library writes itself are written the way that locale writes them, with its digits and separators: `Pagination`'s page numbers, `Steps` markers, a `Badge` count, the `Avatars` surplus, a `RingProgress` in sections, `Rate`'s score, the `Slider` output, `Taginput`'s counter and the count of files `File` shows. Where an accessible name repeats a number on screen, as a page link's does, it's written the same way, so the name still holds the text. A label function you pass, such as `getPageLabel` or `formatOutput`, takes over as before.\n\n```tsx live\n<LocaleProvider locale=\"ar-EG\">\n <Pagination total={12} current={5} />\n</LocaleProvider>\n```\n\nNumbers of your own follow it through [`NumberFormatter`](https://bestax.io/docs/api/elements/numberformatter), and through its `useNumberFormat` hook for text outside JSX, such as an `aria-label`. Outside a provider, those write in the runtime's locale, while the library's own numbers stay as they always were.\n\nTyping in `Combobox`, `Autocomplete`, `Taginput` and `Command` filters the list the way the language compares letters: case and accents are ignored where it treats them as the same letter, so \"cafe\" finds \"Café\", while in Swedish \"a\" doesn't find \"å\", a letter of its own there. Vowel marks the language leaves out of comparisons, such as Arabic harakat and Hebrew niqqud, don't count on either side, so a name typed without them finds one written with them, and the other way round.\n\n```tsx live\n<LocaleProvider locale=\"fr\">\n <Combobox\n label=\"Boisson\"\n data={['Café', 'Thé', 'Chocolat chaud']}\n placeholder=\"Tapez « the »\"\n />\n</LocaleProvider>\n```\n\nThe pickers' digits stay as they are: their typed text is a token format of ASCII digits, and a calendar in another set of digits would sit under it. Numbers inside the library's English labels that aren't on screen, such as a carousel slide's \"1 of 3\", stay as they are too, since they get translated together with their words.\n\n### Portaled Content\n\nWhat the library portals renders outside the provider's wrapper, at the end of `document.body` or in the `portalContainer` a [`ConfigProvider`](https://bestax.io/docs/api/helpers/config) sets. Inside a provider, that content keeps the provider's `dir` and `lang`. That covers a `Portal`'s children, a `Popover`, `HoverCard` or `ContextMenu` panel, a `Combobox` menu or picker popover with `appendToBody`, a `Modal` or `Dialog` with `portal`, a `Sidebar`, and toasts and notifications.\n\nA container inside the provider's own wrapper takes the content as it is, and the content follows the provider through the page. Any other, `document.body` included, gets it inside one `<div>` carrying the values, with `display: contents`, so it adds no box and changes no layout. It is still an element, though, so content that must be its container's direct child, such as a `<tr>` portaled into a `<tbody>`, belongs in a container inside the provider. Which of the two is settled when the content mounts: switching the locale while a dialog or a toast is open updates that `<div>` in place, so what's open keeps its typed text, focus and timers.\n\n```tsx live\n<LocaleProvider locale=\"fa\">\n <Popover trigger={<Button>جزئیات</Button>} appendToBody ariaLabel=\"جزئیات\">\n <Popover.Body>\n این پنل بیرون از بخش رندر میشود و همچنان راستبهچپ است.\n </Popover.Body>\n </Popover>\n</LocaleProvider>\n```\n\nA date or time picker with a `locale` of its own is read the way a nested provider is: its popover, portaled or not, and an inline calendar take its `lang`, and the direction of its locale unless it has a `dir` of its own. So a French picker in an Arabic section shows a French calendar laid out left to right. The `Control` the picker renders takes that direction too, so its icon stays at the start of the field and the launcher at the end. In a `Control` of your own, give the `Control` the picker's `dir`.\n\nFor content you portal yourself without `Portal`, put the values from `useLocale()` on it.\n\n### Server Rendering\n\nThe wrapper's `dir` and `lang` come from its props, so the server and the browser write the same ones, and portaled content only renders after hydration.\n\nSet a `locale` when an `inline` picker renders on the server. With none, `Intl` names its days in the runtime's own language, which is the server's on the server and the reader's in the browser, and the two renders don't match when those differ. With a locale they match, as long as the server's `Intl` data and the browser's spell the names alike. They don't always: Node and Safari write the short name for Saturday differently in Arabic. Where that matters, pass the picker its own `dayNames`, and with them the `firstDayOfWeek` they start on. The calendar shows `dayNames` exactly as given, from the first column, so a picker that brings its own keeps the week on Sunday, as it did before the provider, unless `firstDayOfWeek` says otherwise.\n\n```tsx live\n<LocaleProvider locale=\"ar-EG\">\n <DateInput\n inline\n label=\"تاريخ التسليم\"\n firstDayOfWeek={6}\n dayNames={[\n 'السبت',\n 'الأحد',\n 'الاثنين',\n 'الثلاثاء',\n 'الأربعاء',\n 'الخميس',\n 'الجمعة',\n ]}\n />\n</LocaleProvider>\n```\n\nFor an app that's in one language throughout, also set `lang` and `dir` on `<html>` in your page shell. That reaches what sits outside any provider, and the provider still carries them onto portaled content.\n\nIn the Next.js App Router, render it straight from the root layout, which stays a Server Component. `LocaleProvider` holds React context, so it's a client component, and bestax-bulma marks it one, so the layout can render it without a `'use client'` wrapper of its own. The `locale` and `children` here are values a Server Component can pass. It also takes the wrapper `<div>`'s attributes, and an event handler among them can't cross from a Server Component, so set one from a client component:\n\n```tsx title=\"app/layout.tsx\"\nimport type { ReactNode } from 'react';\nimport { LocaleProvider } from '@allxsmith/bestax-bulma';\n\nexport default function RootLayout({ children }: { children: ReactNode }) {\n return (\n <html lang=\"ar-EG\" dir=\"rtl\">\n <body>\n <LocaleProvider locale=\"ar-EG\">{children}</LocaleProvider>\n </body>\n </html>\n );\n}\n```\n\n### A Locale Intl Doesn't Accept\n\nA tag `Intl` refuses, such as `\"en_US\"` with an underscore, is ignored: the provider writes no `lang`, keeps an outer provider's locale, and warns once in development. A `NumberFormatter`'s or `useNumberFormat`'s own `locale` is checked the same way: a tag `Intl` refuses is ignored with a warning, and the number is written in the provider's locale. A picker's own `locale` isn't checked this way, and `Intl` throws on such a tag when the picker formats with it, as it always has.\n\n---\n\n## Accessibility\n\n- `lang` tells a screen reader which voice and pronunciation to use, and a translation tool what it's reading. The provider puts it on its wrapper and on portaled content, so a dialog or a notification announced from the end of the page comes in the same language.\n- `dir` decides the reading order of the content inside, and which side text starts on. Set the one the content is written in: a left-to-right quote in a right-to-left page needs its own provider or `dir`.\n- The provider changes no focus order and adds no role. The element it wraps portaled content in has `display: contents`, so it adds no box and no landmark.\n\n---\n\n## Related Components\n\n- [`ConfigProvider`](https://bestax.io/docs/api/helpers/config): The class prefix, icon library and portal container. A nested one replaces the outer one's settings, which is why the locale lives here instead.\n- [`Portal`](https://bestax.io/docs/api/helpers/portal): Inside a `LocaleProvider`, its children keep the provider's `dir` and `lang`.\n- [`DateInput`](https://bestax.io/docs/api/form/datetime/dateinput): Takes the provider's locale and first day of the week.\n- [`NumberFormatter`](https://bestax.io/docs/api/elements/numberformatter): Writes a number in the provider's locale, and `useNumberFormat` does the same for text outside JSX.\n- [`Theme`](https://bestax.io/docs/api/helpers/theme): Its scoped wrapper is the same idea for CSS variables.\n\n---\n\n## Additional Resources\n\n- [Storybook: LocaleProvider Stories](https://bestax.io/storybook/?path=/story/helpers-localeprovider--default)\n- [W3C: Structural markup and right-to-left text in HTML](https://www.w3.org/International/questions/qa-html-dir)\n- [MDN: the `lang` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang)\n- [MDN: `Intl.Locale.prototype.getWeekInfo()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getWeekInfo)\n\n---\n\n## Props\n\n| Prop | Type | Default | Description |\n| ---------- | ------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| `locale` | `string` | — | A BCP 47 language tag, such as `\"de\"` or `\"ar-EG\"`: the wrapper's `lang`, the pickers' default `locale`, and, with no `dir`, the direction of its script. Unset, a nested provider keeps the outer one's. A tag `Intl` refuses is ignored. |\n| `dir` | `'ltr'` \\| `'rtl'` | — | The direction, whatever the locale. Unset, it follows this provider's `locale`, else an outer provider's direction, else the page's. |\n| `children` | `ReactNode` | — | The part of the app it covers. |\n\nThe helper props, the other attributes of a `<div>` and the `ref` land on the wrapper."
|
|
117
117
|
}
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"related": ["Notification", "useBulmaClasses"],
|
|
43
43
|
"storybook": "https://bestax.io/storybook/?path=/story/components-message--primary",
|
|
44
44
|
"summary": "The `Message` component provides Bulma's flexible notice/message box for your Bulma React UI.",
|
|
45
|
-
"import": "import { Message } from '@allxsmith/bestax-bulma';",
|
|
45
|
+
"import": "import { Message, MessageHeader, MessageBody } from '@allxsmith/bestax-bulma';",
|
|
46
46
|
"sourceFile": "bulma-ui/src/components/Message.tsx",
|
|
47
47
|
"rootClass": "message",
|
|
48
48
|
"parts": [
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
],
|
|
58
58
|
"storybook": "https://bestax.io/storybook/?path=/story/components-modal--modal-card",
|
|
59
59
|
"summary": "The `Modal` component provides an empty, accessible overlay for arbitrary content — for a ready-made confirm or alert, reach for `Dialog` instead.",
|
|
60
|
-
"import": "import { Modal } from '@allxsmith/bestax-bulma';",
|
|
60
|
+
"import": "import { Modal, ModalBackground, ModalContent, ModalClose, ModalCard, ModalCardHead, ModalCardTitle, ModalCardBody, ModalCardFoot } from '@allxsmith/bestax-bulma';",
|
|
61
61
|
"sourceFile": "bulma-ui/src/components/Modal.tsx",
|
|
62
62
|
"rootClass": "modal",
|
|
63
63
|
"parts": [
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"code": "<Navbar>\n <Navbar.Brand>\n <Navbar.Item href=\"#\">\n <img src=\"/img/logo.svg\" alt=\"Logo\" width=\"28\" height=\"28\" />\n </Navbar.Item>\n <Navbar.Burger aria-label=\"menu\" />\n </Navbar.Brand>\n <Navbar.Menu active>\n <Navbar.Start>\n <Navbar.Item href=\"#\">Home</Navbar.Item>\n <Navbar.Item href=\"#\">Docs</Navbar.Item>\n </Navbar.Start>\n <Navbar.End>\n <Navbar.Item href=\"#\">Log in</Navbar.Item>\n </Navbar.End>\n </Navbar.Menu>\n</Navbar>"
|
|
83
83
|
}
|
|
84
84
|
],
|
|
85
|
-
"accessibility": "- The root `Navbar` renders as `<nav role=\"navigation\" aria-label=\"main navigation\">`.\n The default accessible name is `main navigation`. A screen reader announces it with\n the role, and since the name holds the role word, \"navigation\" is heard twice.\n Pass a name without the role word (`aria-label=\"Site\"`), and a different name\n on each Navbar when a page has more than one. A passed `aria-label` replaces\n the default.\n- Use semantic links (`<a>`) and buttons, and provide clear `aria-label` and `aria-expanded` for the burger toggle.\n- `Navbar.Link` inside a `Navbar.Dropdown` automatically gets `aria-haspopup=\"true\"` and\n `aria-expanded` synced to the dropdown's open state — no manual wiring required.\n <kbd>Enter</kbd>/<kbd>Space</kbd> toggle the dropdown open/closed, and <kbd>Escape</kbd>\n closes it and keeps focus on the link. When the trigger isn't interactive on its own — no\n `href`, not `as=\"button\"`, and not a custom component — it also gets `role=\"button\"` and\n `tabIndex={0}` so it's reachable and operable by keyboard, and a mouse/touch click on it\n toggles the dropdown too (a caller-supplied `onClick` still runs, and can\n `preventDefault()` to opt out).\n- A custom component passed to `as` keeps its own semantics, because a router link takes `to`\n rather than `href` and so can't be recognised from the props it's given. If yours renders\n something non-interactive instead, pass `role=\"button\"` and it takes the fallback above —\n `tabIndex` and click included. The keyboard path is wired either way.\n- `hoverable` dropdowns keep working with a mouse (hover-to-open); the keyboard path above\n opens and closes them independently of hover.\n\n:::note\nThere's no arrow-key roving between navbar items and no outside-click handling for\n`Navbar.Dropdown` — Bulma navbar dropdowns are hover/click surfaces, so this is intentionally\nkept simple.\n:::",
|
|
85
|
+
"accessibility": "- The root `Navbar` renders as `<nav role=\"navigation\" aria-label=\"main navigation\">`.\n The default accessible name is `main navigation`. A screen reader announces it with\n the role, and since the name holds the role word, \"navigation\" is heard twice.\n Pass a name without the role word (`aria-label=\"Site\"`), and a different name\n on each Navbar when a page has more than one. A passed `aria-label` replaces\n the default.\n- `Navbar.Item active` sets `aria-current=\"page\"` on the element `as` renders, the link by\n default, so the current item isn't only a color. An `aria-current` you pass wins: a navbar of\n sections on one page can say `\"location\"`, and `aria-current={false}` turns it off.\n- Use semantic links (`<a>`) and buttons, and provide clear `aria-label` and `aria-expanded` for the burger toggle.\n- `Navbar.Link` inside a `Navbar.Dropdown` automatically gets `aria-haspopup=\"true\"` and\n `aria-expanded` synced to the dropdown's open state — no manual wiring required.\n <kbd>Enter</kbd>/<kbd>Space</kbd> toggle the dropdown open/closed, and <kbd>Escape</kbd>\n closes it and keeps focus on the link. When the trigger isn't interactive on its own — no\n `href`, not `as=\"button\"`, and not a custom component — it also gets `role=\"button\"` and\n `tabIndex={0}` so it's reachable and operable by keyboard, and a mouse/touch click on it\n toggles the dropdown too (a caller-supplied `onClick` still runs, and can\n `preventDefault()` to opt out).\n- A custom component passed to `as` keeps its own semantics, because a router link takes `to`\n rather than `href` and so can't be recognised from the props it's given. If yours renders\n something non-interactive instead, pass `role=\"button\"` and it takes the fallback above —\n `tabIndex` and click included. The keyboard path is wired either way.\n- `hoverable` dropdowns keep working with a mouse (hover-to-open); the keyboard path above\n opens and closes them independently of hover.\n\n:::note\nThere's no arrow-key roving between navbar items and no outside-click handling for\n`Navbar.Dropdown` — Bulma navbar dropdowns are hover/click surfaces, so this is intentionally\nkept simple.\n:::",
|
|
86
86
|
"related": ["Button", "Icon", "useBulmaClasses"],
|
|
87
87
|
"storybook": "https://bestax.io/storybook/?path=/story/components-navbar--default",
|
|
88
88
|
"summary": "The `Navbar` component implements Bulma's powerful, responsive navigation bar for your Bulma React UI.",
|
|
@@ -276,7 +276,7 @@
|
|
|
276
276
|
"name": "active",
|
|
277
277
|
"type": "boolean",
|
|
278
278
|
"default": "false",
|
|
279
|
-
"description": "
|
|
279
|
+
"description": "Marks the item as the current one. It adds Bulma's `is-active` class, and `aria-current=\"page\"` on the element `as` renders, so assistive tech can tell which item is current too. An `aria-current` you pass wins, even `undefined`: use it to say something else (`\"location\"` for a section of one page, say), or `aria-current={false}` to turn it off. An `active` item that isn't navigation takes `aria-current={false}`: an `as=\"button\"` control, say, or a `has-dropdown` container like the `<Navbar.Item as=\"div\" className=\"has-dropdown\" active>` older bestax-migrate versions wrote. That one can be a `Navbar.Dropdown` instead.",
|
|
280
280
|
"required": false,
|
|
281
281
|
"inherited": false,
|
|
282
282
|
"deprecated": false
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"code": "<Pagination>\n <Pagination.Previous>Previous</Pagination.Previous>\n <Pagination.Next>Next page</Pagination.Next>\n <Pagination.List>\n <Pagination.Link active>1</Pagination.Link>\n <Pagination.Link>2</Pagination.Link>\n <Pagination.Ellipsis />\n <Pagination.Link>10</Pagination.Link>\n </Pagination.List>\n</Pagination>"
|
|
43
43
|
}
|
|
44
44
|
],
|
|
45
|
-
"accessibility": "- The root `Pagination` renders as a semantic `<nav role=\"navigation\" aria-label=\"pagination\">`.\n- Use `aria-label` on page links for better screen reader support.\n- Disabled and active states are handled with ARIA attributes and classes.\n- Rendered from `total`, each page's link is named for its page (\"Page 3\"; pass `getPageLabel` for your own words), and the current page's link carries `aria-current=\"page\"`. Without `getPageHref` the links have no `href`, so they carry `role=\"button\"` and choose a page with Enter or Space.\n- **Forced colors:** Bulma marks the current page with colors alone, which forced colors (Windows' contrast themes) replaces, so bestax's styles draw it in the system's highlight colors there instead. A link with Bulma's `is-current` or `is-selected` class gets them, so a [DataTable](https://bestax.io/docs/api/components/datatable)'s pager does too.\n\n:::note\nPagination links are rendered as `<a>` elements for accessibility and keyboard navigation.\n:::",
|
|
45
|
+
"accessibility": "- The root `Pagination` renders as a semantic `<nav role=\"navigation\" aria-label=\"pagination\">`.\n- Use `aria-label` on page links for better screen reader support.\n- Disabled and active states are handled with ARIA attributes and classes.\n- Rendered from `total`, each page's link is named for its page (\"Page 3\"; pass `getPageLabel` for your own words), and the current page's link carries `aria-current=\"page\"`. Without `getPageHref` the links have no `href`, so they carry `role=\"button\"` and choose a page with Enter or Space.\n- **Focus ring:** the previous, next and page links show a focus ring for keyboard focus only, in Bulma's focus color, width, style and offset (`--bulma-focus-h`, `--bulma-focus-s`, `--bulma-focus-l`, `--bulma-focus-width`, `--bulma-focus-style`, `--bulma-focus-offset`). The current page is filled with the link color, which matches the focus color by default, so its ring takes the link's text color instead, inside the fill. It comes from the bestax extras (`extras.css`, or `bestax.css`, which includes them); with Bulma's CSS alone a focused link shows only its hover shade.\n- **Forced colors:** Bulma marks the current page with colors alone, which forced colors (Windows' contrast themes) replaces, so bestax's styles draw it in the system's highlight colors there instead. A link with Bulma's `is-current` or `is-selected` class gets them, so a [DataTable](https://bestax.io/docs/api/components/datatable)'s pager does too.\n\n:::note\nPagination links are rendered as `<a>` elements for accessibility and keyboard navigation.\n:::",
|
|
46
46
|
"related": ["Button", "useBulmaClasses"],
|
|
47
47
|
"storybook": "https://bestax.io/storybook/?path=/story/components-pagination--basic",
|
|
48
48
|
"summary": "The `Pagination` component provides a flexible, composable Bulma pagination navigation for your Bulma React UI.",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"code": "<Popover trigger={<Button>Rename</Button>}>\n <Popover.Header>Rename file</Popover.Header>\n <Popover.Body>\n <Input aria-label=\"File name\" defaultValue=\"report.pdf\" />\n </Popover.Body>\n <Popover.Footer>\n <Popover.Close>Cancel</Popover.Close>\n <Popover.Close color=\"primary\">Save</Popover.Close>\n </Popover.Footer>\n</Popover>"
|
|
39
39
|
}
|
|
40
40
|
],
|
|
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
|
|
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`.\n- On a right-to-left page a popover with no `position` lines its right edge up with the trigger's, so a trigger at the start of the line doesn't push the panel off the screen. A `position` you pass stays physical: `bottom-left` lines up the left edges on either page.",
|
|
42
42
|
"related": [
|
|
43
43
|
"ContextMenu",
|
|
44
44
|
"Dropdown",
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
"name": "position",
|
|
110
110
|
"type": "'bottom-left' | 'bottom-right' | 'top-left' | 'top-right' | 'auto'",
|
|
111
111
|
"default": "'bottom-left'",
|
|
112
|
-
"description": "Where the panel opens against the trigger.",
|
|
112
|
+
"description": "Where the panel opens against the trigger. Left out, it opens below and lines up with the trigger's start edge, which is its right edge on a right-to-left page, so a trigger at the start of the line doesn't push the panel off the screen. A corner you pass stays physical, so `bottom-left` lines up the left edges on either page.",
|
|
113
113
|
"required": false,
|
|
114
114
|
"inherited": false,
|
|
115
115
|
"deprecated": false
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
],
|
|
62
62
|
"storybook": "https://bestax.io/storybook/?path=/story/components-segmentedcontrol--default",
|
|
63
63
|
"summary": "The `SegmentedControl` component renders a row of buttons where only one can be on, and tells a screen reader it's a radio group. It's Bulma's `.buttons.has-addons` row, with the checked segment filled and marked `is-selected`, the way Bulma's button docs show it. To a screen reader it's `role=\"radiogroup\"`, with `role=\"radio\"` and `aria-checked` on each segment, which is how the APG toolbar example marks its alignment buttons. The keys follow the APG radio group: the row is one tab stop, the arrow keys move to the next or previous enabled segment and check it, wrapping at either end, Home and End go to the first and last, and Space checks the focused segment. Once a segment is checked, one always is. It carries no form value. A choice that's sent with a form is `Radios`.",
|
|
64
|
-
"import": "import { SegmentedControl } from '@allxsmith/bestax-bulma';",
|
|
64
|
+
"import": "import { SegmentedControl, SegmentedControlSegment } from '@allxsmith/bestax-bulma';",
|
|
65
65
|
"sourceFile": "bulma-ui/src/components/SegmentedControl.tsx",
|
|
66
66
|
"rootClass": "buttons",
|
|
67
67
|
"parts": [
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"related": ["Menu", "Modal"],
|
|
43
43
|
"storybook": "https://bestax.io/storybook/?path=/story/components-sidebar",
|
|
44
44
|
"summary": "The `Sidebar` component provides a slide-out navigation panel that appears from the left or right side of the screen.",
|
|
45
|
-
"import": "import { Sidebar } from '@allxsmith/bestax-bulma';",
|
|
45
|
+
"import": "import { Sidebar, SidebarHeader, SidebarTitle, SidebarClose, SidebarBody, SidebarFooter } from '@allxsmith/bestax-bulma';",
|
|
46
46
|
"sourceFile": "bulma-ui/src/components/Sidebar.tsx",
|
|
47
47
|
"rootClass": "sidebar",
|
|
48
48
|
"parts": [
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"code": "function example() {\n return (\n <Field\n horizontal\n label=\"Volume\"\n labelProps={{ htmlFor: 'volume-field-control' }}\n >\n <Field.Body>\n <Field>\n <Control iconLeftName=\"volume-up\">\n <Slider\n id=\"volume-field-control\"\n defaultValue={50}\n color=\"primary\"\n />\n </Control>\n </Field>\n </Field.Body>\n </Field>\n );\n}"
|
|
59
59
|
}
|
|
60
60
|
],
|
|
61
|
-
"accessibility": "- Uses native `<input type=\"range\">` element\n- The `label` prop, or the label of a `Field` the slider sits in, names its input.\n- In range mode the label starts each thumb's name, so `<Slider range label=\"Price range\" />` announces \"Price range Minimum value\" and \"Price range Maximum value\". Each thumb points `aria-labelledby` at the label and at a hidden span holding its own text, because an `aria-label` would outrank the label. The label's `for` still lands on the low thumb, so clicking the label focuses it.\n- `ariaLabel` wins over the label. In range mode each entry is that thumb's whole name, with no label in front, and an empty entry counts as unset.\n- An `aria-label` or `aria-labelledby` you pass straight to a range Slider names the whole Slider, so it takes the label's place at the start of both thumbs' names: `<Slider range aria-label=\"Budget\" />` announces \"Budget Minimum value\" and \"Budget Maximum value\". An `ariaLabel` entry still wins for its own thumb. To keep a label out of the thumbs' names altogether, pass `aria-labelledby={undefined}`, and they stay \"Minimum value\" and \"Maximum value\".\n- A `Field` label you wire by hand with `labelProps={{ htmlFor }}`, as in a horizontal form, gets no generated id, so give it one of your own there as well, as in `labelProps={{ htmlFor: 'price', id: 'price-label' }}`, and it starts both thumbs' names the same way. Without that `id` it reaches a range Slider only through its `for`, which the thumbs' default `aria-label` outranks, so they stay \"Minimum value\" and \"Maximum value\".\n- Has `aria-valuenow`, `aria-valuemin`, and `aria-valuemax` attributes\n- Fully keyboard accessible with arrow keys\n- Focus states clearly visible",
|
|
61
|
+
"accessibility": "- Uses native `<input type=\"range\">` element\n- The `label` prop, or the label of a `Field` the slider sits in, names its input.\n- In range mode the label starts each thumb's name, so `<Slider range label=\"Price range\" />` announces \"Price range Minimum value\" and \"Price range Maximum value\". Each thumb points `aria-labelledby` at the label and at a hidden span holding its own text, because an `aria-label` would outrank the label. The label's `for` still lands on the low thumb, so clicking the label focuses it.\n- `ariaLabel` wins over the label. In range mode each entry is that thumb's whole name, with no label in front, and an empty entry counts as unset.\n- An `aria-label` or `aria-labelledby` you pass straight to a range Slider names the whole Slider, so it takes the label's place at the start of both thumbs' names: `<Slider range aria-label=\"Budget\" />` announces \"Budget Minimum value\" and \"Budget Maximum value\". An `ariaLabel` entry still wins for its own thumb. To keep a label out of the thumbs' names altogether, pass `aria-labelledby={undefined}`, and they stay \"Minimum value\" and \"Maximum value\".\n- A `Field` label you wire by hand with `labelProps={{ htmlFor }}`, as in a horizontal form, gets no generated id, so give it one of your own there as well, as in `labelProps={{ htmlFor: 'price', id: 'price-label' }}`, and it starts both thumbs' names the same way. Without that `id` it reaches a range Slider only through its `for`, which the thumbs' default `aria-label` outranks, so they stay \"Minimum value\" and \"Maximum value\".\n- Has `aria-valuenow`, `aria-valuemin`, and `aria-valuemax` attributes\n- Fully keyboard accessible with arrow keys\n- Focus states clearly visible\n- On a right-to-left page the native range mirrors, and the fill, the tick marks and the value bubble follow it, so a value of 25 fills from the right. A vertical slider still fills from the bottom.",
|
|
62
62
|
"related": ["Numberinput", "Progress"],
|
|
63
63
|
"storybook": "https://bestax.io/storybook/?path=/story/form-slider",
|
|
64
64
|
"summary": "The `Slider` component provides a range slider input for selecting values within a range.",
|
|
@@ -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- 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
|
|
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`.\n- On a right-to-left page the launcher sits at the end of the line and the clock icon at the start. The wheels keep `dir=\"ltr\"`, so hours stay to the left of minutes.",
|
|
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.",
|
|
@@ -537,7 +537,7 @@
|
|
|
537
537
|
"name": "position",
|
|
538
538
|
"type": "'bottom-left' | 'bottom-right' | 'top-left' | 'top-right' | 'auto'",
|
|
539
539
|
"default": "'bottom-left'",
|
|
540
|
-
"description": "
|
|
540
|
+
"description": "Where the popover opens against the field. Left out, it opens below and lines up with the field's start edge, which is its right edge when the picker reads right to left. A corner you pass stays physical, so `bottom-left` lines up the left edges either way.",
|
|
541
541
|
"required": false,
|
|
542
542
|
"inherited": true,
|
|
543
543
|
"deprecated": false
|
|
@@ -908,7 +908,7 @@
|
|
|
908
908
|
"name": "position",
|
|
909
909
|
"type": "'bottom-left' | 'bottom-right' | 'top-left' | 'top-right' | 'auto'",
|
|
910
910
|
"default": "'bottom-left'",
|
|
911
|
-
"description": "
|
|
911
|
+
"description": "Where the popover opens against the field. Left out, it opens below and lines up with the field's start edge, which is its right edge when the picker reads right to left. A corner you pass stays physical, so `bottom-left` lines up the left edges either way.",
|
|
912
912
|
"required": false,
|
|
913
913
|
"inherited": false,
|
|
914
914
|
"deprecated": false
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"code": "function example() {\n return (\n <Paragraph style={{ lineHeight: 1.8 }}>\n Hover over{' '}\n <Tooltip label=\"Cascading Style Sheets\" color=\"info\" dashed>\n <abbr tabIndex={0}>CSS</abbr>\n </Tooltip>{' '}\n or{' '}\n <Tooltip label=\"HyperText Markup Language\" color=\"info\" dashed>\n <abbr tabIndex={0}>HTML</abbr>\n </Tooltip>{' '}\n to see their full names.\n </Paragraph>\n );\n}"
|
|
51
51
|
}
|
|
52
52
|
],
|
|
53
|
-
"accessibility": "`Tooltip` 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:\n\n- **Dismissible:** <kbd>Escape</kbd> hides a shown tooltip wherever focus is, without you moving the\n pointer or focus, and it stays hidden until the pointer or focus leaves the trigger and comes\n back, or, with `openOnTap`, until the next tap on the trigger. The key goes on as well, to\n whatever has focus, so a control in the trigger, such as a `Dropdown`, still gets its own Escape.\n Inside a `Popover` or `Modal`, one Escape hides the tooltip and closes that too, since a tooltip\n only adds to what's there.\n- **Hoverable:** the pointer can move from the trigger onto a shown tooltip, straight across the gap\n between them, and it stays. A hidden tooltip, or one only `active` shows, lets the pointer through\n to whatever is under it.\n- **Persistent:** no timer hides a tooltip that's hovered or focused.\n\nAnd around it:\n\n- Keyboard focus on the trigger shows the tooltip, as hover does. Focus that a click or a tap brings\n doesn't, and neither does a touch pointer, so tapping the trigger just does what the trigger does.\n `openOnTap` shows it with a tap, for a trigger with no tap action of its own.\n- An `active` tooltip is always shown, whatever the pointer, focus and Escape do.\n- Tooltip content has `role=\"tooltip\"`. While it's hidden, the stylesheet gives it\n `visibility: hidden`, which keeps it out of the accessibility tree.\n- The tooltip describes its trigger. The trigger's `aria-describedby` points at it, after any ids it\n already had, so a screen reader reads the tooltip when the trigger takes focus. A hidden tooltip\n still counts as a description, so that's before any `delay` runs out. `content` is read as plain\n text.\n- That takes a single element as `children`, which passes `aria-describedby` on to its DOM node, as\n native elements and bestax components do, and takes focus itself: a button, a link, or a `Span`\n with `tabIndex={0}`. Something focusable inside it doesn't get the link, and text, a fragment or\n several elements get none. A development build warns when the first element Tab reaches in the\n trigger doesn't carry the link, or there isn't one.\n- A tooltip describes and doesn't name, so give an icon-only trigger a name of its own, such as an\n `IconButton`'s `aria-label`, as [On Icons](https://bestax.io/docs/api/components/tooltip#on-icons) does.\n- The `dashed` style provides a visual cue that more information is available.",
|
|
53
|
+
"accessibility": "`Tooltip` 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:\n\n- **Dismissible:** <kbd>Escape</kbd> hides a shown tooltip wherever focus is, without you moving the\n pointer or focus, and it stays hidden until the pointer or focus leaves the trigger and comes\n back, or, with `openOnTap`, until the next tap on the trigger. The key goes on as well, to\n whatever has focus, so a control in the trigger, such as a `Dropdown`, still gets its own Escape.\n Inside a `Popover` or `Modal`, one Escape hides the tooltip and closes that too, since a tooltip\n only adds to what's there.\n- **Hoverable:** the pointer can move from the trigger onto a shown tooltip, straight across the gap\n between them, and it stays. A hidden tooltip, or one only `active` shows, lets the pointer through\n to whatever is under it.\n- **Persistent:** no timer hides a tooltip that's hovered or focused.\n\nAnd around it:\n\n- Keyboard focus on the trigger shows the tooltip, as hover does. Focus that a click or a tap brings\n doesn't, and neither does a touch pointer, so tapping the trigger just does what the trigger does.\n `openOnTap` shows it with a tap, for a trigger with no tap action of its own.\n- An `active` tooltip is always shown, whatever the pointer, focus and Escape do.\n- Tooltip content has `role=\"tooltip\"`. While it's hidden, the stylesheet gives it\n `visibility: hidden`, which keeps it out of the accessibility tree.\n- The tooltip describes its trigger. The trigger's `aria-describedby` points at it, after any ids it\n already had, so a screen reader reads the tooltip when the trigger takes focus. A hidden tooltip\n still counts as a description, so that's before any `delay` runs out. `content` is read as plain\n text.\n- That takes a single element as `children`, which passes `aria-describedby` on to its DOM node, as\n native elements and bestax components do, and takes focus itself: a button, a link, or a `Span`\n with `tabIndex={0}`. Something focusable inside it doesn't get the link, and text, a fragment or\n several elements get none. A development build warns when the first element Tab reaches in the\n trigger doesn't carry the link, or there isn't one.\n- A tooltip describes and doesn't name, so give an icon-only trigger a name of its own, such as an\n `IconButton`'s `aria-label`, as [On Icons](https://bestax.io/docs/api/components/tooltip#on-icons) does.\n- The `dashed` style provides a visual cue that more information is available.\n- **Forced colors:** forced colors (Windows' contrast themes) gives the tooltip the page's own\n background and paints every side of the arrow, so the box would read as loose text and the arrow\n as a square. bestax's styles outline the box in the system's text color there, and keep the\n arrow a triangle in that color, pointing at the trigger.",
|
|
54
54
|
"related": ["Button", "HoverCard", "Icon", "IconButton", "Popover"],
|
|
55
55
|
"storybook": null,
|
|
56
56
|
"summary": "The `Tooltip` component displays helpful information when users hover over or focus on an element. Hovering the trigger or giving it keyboard focus shows it. Touch doesn't, unless `openOnTap` is on, and neither does focus a click or a tap brings, so tapping the trigger just does what the trigger does. The pointer can move onto a shown tooltip. Escape hides it wherever focus is, without moving the pointer or focus, and it stays hidden until one of them leaves the trigger and comes back, or, with `openOnTap`, until the next tap on the trigger. The key always goes on too, to whatever has focus or a `Modal` or `Popover` around it, since a tooltip only adds to what's there. The tooltip is its trigger's description, so a screen reader reads it as the trigger takes focus, whether it's showing yet or not.",
|
|
@@ -399,7 +399,7 @@
|
|
|
399
399
|
"name": "position",
|
|
400
400
|
"type": "'bottom-left' | 'bottom-right' | 'top-left' | 'top-right' | 'auto'",
|
|
401
401
|
"default": "'bottom-left'",
|
|
402
|
-
"description": "Where the panel opens
|
|
402
|
+
"description": "Where the panel opens against the field, as on the pickers. Left out, it opens below and lines up with the field's start edge, which is its right edge on a right-to-left page. A corner you pass stays physical, so `bottom-left` lines up the left edges either way.",
|
|
403
403
|
"required": false,
|
|
404
404
|
"inherited": true,
|
|
405
405
|
"deprecated": false
|
|
@@ -22,8 +22,14 @@ instead of hand-writing markup.
|
|
|
22
22
|
(`m`/`p` spacing, `textColor`/`bgColor`, `textAlign`, `display`, flex, …) —
|
|
23
23
|
documented once in `references/api.md` — with rare exceptions (`Skeleton`).
|
|
24
24
|
- **Compound components** expose sub-parts via dot access (e.g. `Card.Header`,
|
|
25
|
-
`Navbar.Item`, `Tabs.Tab`, `Hero.Body`, `Columns.Column`, `Table.Tr`)
|
|
26
|
-
|
|
25
|
+
`Navbar.Item`, `Tabs.Tab`, `Hero.Body`, `Columns.Column`, `Table.Tr`) and as
|
|
26
|
+
named exports of the same component (`CardHeader`, `NavbarItem`). A Next.js
|
|
27
|
+
Server Component imports the named export: the dotted name is `undefined`
|
|
28
|
+
there. Build a `Card` or `Modal` from its parts in a client component, though,
|
|
29
|
+
since each checks which part each child is and can't recognize a part written in
|
|
30
|
+
a Server Component; a few other components do the same
|
|
31
|
+
(https://bestax.io/docs/guides/getting-started/react-setups#nextjs-specific).
|
|
32
|
+
See the component's linked page for the full set. Sub-parts do **not** all take helper
|
|
27
33
|
props: the `Card.*`, `Table.*`, `Menu.*`, and `Hero.*` families do (most
|
|
28
34
|
`Navbar.*` too), but `Modal.*`, `Tabs.*`, and `Message.*` sub-parts take none —
|
|
29
35
|
just `className`, HTML attributes, and their own few (`Tabs.Tab` requires
|
|
@@ -183,8 +183,13 @@ variants. Field/Control composition like the other convenience inputs, with pick
|
|
|
183
183
|
with custom fallback). An `inline` picker renders no `Control` anywhere, so leave its
|
|
184
184
|
Control-level props out: they do nothing there and warn in development.
|
|
185
185
|
|
|
186
|
-
Every one of them has a launcher button at the
|
|
187
|
-
|
|
186
|
+
Every one of them has a launcher button at the inline end (`triggerIcon`), the right edge on a
|
|
187
|
+
left-to-right page and the left edge on a right-to-left one. The calendar or clock icon sits at
|
|
188
|
+
the inline start. A picker with its own `locale` or `dir` gives the `Control` it renders the same
|
|
189
|
+
`dir`, so the two stay apart; inside your own `Control`, set that `dir` on it. With no `position`
|
|
190
|
+
the popover lines up with the field's start edge, its right edge right to left, and a `position`
|
|
191
|
+
you pass stays physical. The launcher gives way to the loading spinner of the `Control` they sit
|
|
192
|
+
in, which shares that edge. A convenience input sits in the
|
|
188
193
|
`Control` it renders for its own `isLoading`, unless it is inside your own `Control`; a `*Base`
|
|
189
194
|
variant only ever sits in yours. Inside your own `Control`, put `isLoading` on that `Control`: the
|
|
190
195
|
convenience input renders no `Control` of its own there, so its own `isLoading` draws nothing and
|
|
@@ -300,16 +300,16 @@ flexDirection="column"` + `flexGrow="1"` pattern applies to `Cell` + `Card`.
|
|
|
300
300
|
`Navbar.Burger`, `Navbar.Menu`, `Navbar.Start`, `Navbar.End`, `Navbar.Dropdown`,
|
|
301
301
|
`Navbar.DropdownMenu`, `Navbar.Divider`.
|
|
302
302
|
|
|
303
|
-
| Prop | Type
|
|
304
|
-
| --------------- |
|
|
305
|
-
| `fixed` | `'top' \| 'bottom'`
|
|
306
|
-
| `transparent` | `boolean`
|
|
307
|
-
| `isSpaced` | `boolean` (Bulma's `is-spaced`, from desktop up)
|
|
308
|
-
| `hasShadow` | `boolean` (default `false`, unlike `Card`'s; Bulma's `has-shadow`)
|
|
309
|
-
| `color` | `'primary' \| 'link' \| 'info' \| 'success' \| 'warning' \| 'danger' \| 'black' \| 'dark' \| 'light' \| 'white'`
|
|
310
|
-
| `Navbar.Item` | `as?`, `active
|
|
311
|
-
| `Navbar.Burger` | `active?`, `onClick`
|
|
312
|
-
| `Navbar.Menu` | `active?` (toggled open on mobile)
|
|
303
|
+
| Prop | Type |
|
|
304
|
+
| --------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
305
|
+
| `fixed` | `'top' \| 'bottom'` |
|
|
306
|
+
| `transparent` | `boolean` |
|
|
307
|
+
| `isSpaced` | `boolean` (Bulma's `is-spaced`, from desktop up) |
|
|
308
|
+
| `hasShadow` | `boolean` (default `false`, unlike `Card`'s; Bulma's `has-shadow`) |
|
|
309
|
+
| `color` | `'primary' \| 'link' \| 'info' \| 'success' \| 'warning' \| 'danger' \| 'black' \| 'dark' \| 'light' \| 'white'` |
|
|
310
|
+
| `Navbar.Item` | `as?`, `active?` (the current page: `is-active` plus `aria-current="page"`; an `aria-current` you pass wins), `href` |
|
|
311
|
+
| `Navbar.Burger` | `active?`, `onClick` |
|
|
312
|
+
| `Navbar.Menu` | `active?` (toggled open on mobile) |
|
|
313
313
|
|
|
314
314
|
The burger/menu is controlled state — toggle `Navbar.Burger active`/`onClick` and pass the same
|
|
315
315
|
flag to `Navbar.Menu active`. **A `fixed="top"` navbar requires `has-navbar-fixed-top` on `<html>`**
|
|
@@ -383,7 +383,12 @@ is a `div` with `role="button"`).
|
|
|
383
383
|
|
|
384
384
|
`<Card>` for catalog/grid items. Use the props form (`header`, `image`, `footer`) or the compound
|
|
385
385
|
subcomponents (`Card.Header` + `.Title`/`.Icon`, `Card.Image`, `Card.Content`, `Card.Footer`,
|
|
386
|
-
`Card.FooterItem`).
|
|
386
|
+
`Card.FooterItem`). Those parts are also named exports (`CardHeader`, `CardHeaderTitle`,
|
|
387
|
+
`CardHeaderIcon`, `CardImage`, `CardContent`, `CardFooter`, `CardFooterItem`), the same
|
|
388
|
+
components as the dotted names. In a Next.js App Router app, build a card from its parts inside a
|
|
389
|
+
client component (a file that starts with `'use client'`): `Card` lays out its parts by checking
|
|
390
|
+
which part each child is, and that check can't recognize a part written in a Server Component. A
|
|
391
|
+
Server Component uses the props form.
|
|
387
392
|
|
|
388
393
|
| Prop | Type |
|
|
389
394
|
| ------------------------------- | ----------------------------- |
|
|
@@ -138,7 +138,9 @@ anything else.
|
|
|
138
138
|
own navbar carries, so a `.navbar` that sets both converts (whatever the label says), and one
|
|
139
139
|
that doesn't gets a `defaults:Navbar` TODO. A `.navbar-item` `<button>` converts only with its
|
|
140
140
|
`type` written out as `button`, `submit` or `reset`, since `Navbar.Item` writes `type="button"` on
|
|
141
|
-
a button in place of anything else.
|
|
141
|
+
a button in place of anything else. `is-active` on a `.navbar-item` becomes `active` beside an
|
|
142
|
+
`aria-current` of the element's own, since `active` writes `aria-current="page"` otherwise; without
|
|
143
|
+
one, the class stays. A `.has-dropdown` item becomes a `Navbar.Item` that
|
|
142
144
|
keeps `has-dropdown` as a class, because a `Navbar.Dropdown` would give the `.navbar-link` inside
|
|
143
145
|
it dropdown semantics the markup didn't have. That link and the `.navbar-burger` stay markup with
|
|
144
146
|
a `family:<class>` TODO; converting either means building the dropdown or the toggle with bestax,
|
|
@@ -124,7 +124,8 @@ codemod's `modifier:title` (or `modifier:subtitle`) TODO on the element says the
|
|
|
124
124
|
| `.navbar` → `Navbar` | the ten `.hero` colors | `color` |
|
|
125
125
|
| `.navbar` → `Navbar` | `is-fixed-top`, `is-fixed-bottom` | `fixed` (`top`, `bottom`) |
|
|
126
126
|
| `.navbar` → `Navbar` | `is-transparent`, `is-spaced`, `has-shadow` | `transparent`, `isSpaced`, `hasShadow` |
|
|
127
|
-
| `.navbar-menu` → `Navbar.Menu
|
|
127
|
+
| `.navbar-menu` → `Navbar.Menu` | `is-active` | `active` (the menu is open) |
|
|
128
|
+
| `.navbar-item` → `Navbar.Item` | `is-active`, beside an `aria-current` of the element's own | `active` (without one, it stays a class) |
|
|
128
129
|
| `.navbar-dropdown` → `Navbar.DropdownMenu` | `is-right`, `is-up` | `right`, `up` |
|
|
129
130
|
| `.notification` → `Notification` | `is-primary`, `is-link`, `is-info`, `is-success`, `is-warning`, `is-danger`, `is-black`, `is-white`, `is-dark` | `color` |
|
|
130
131
|
| `.notification` → `Notification` | `is-light` | `isLight` |
|
|
@@ -107,6 +107,8 @@ Create `src/styles.scss` — base + themes always come first:
|
|
|
107
107
|
@use 'bulma/sass/components/navbar';
|
|
108
108
|
// …and per bestax extras component:
|
|
109
109
|
@use '@allxsmith/bestax-bulma/scss/components/dialog';
|
|
110
|
+
// …and bestax's partial for a stock component that has one:
|
|
111
|
+
@use '@allxsmith/bestax-bulma/scss/elements/button' as bestax-button;
|
|
110
112
|
// Helper categories only if the app uses those helper props:
|
|
111
113
|
@use 'bulma/sass/helpers/spacing';
|
|
112
114
|
```
|
|
@@ -125,9 +125,10 @@ Notes:
|
|
|
125
125
|
@use '@allxsmith/bestax-bulma/scss/components/tableofcontents'; // TableOfContents only
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
-
- The `pagination` partial **extends** stock Bulma pagination (
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
- The `pagination` partial **extends** stock Bulma pagination (the links' keyboard focus ring,
|
|
129
|
+
which Bulma's own styles turn off, and the current page marked in forced colors, where Bulma's
|
|
130
|
+
colors for it are replaced), so an app using `Pagination`, or a `DataTable` with pages, whose
|
|
131
|
+
pager is one, needs both, in either order:
|
|
131
132
|
|
|
132
133
|
```scss
|
|
133
134
|
@use 'bulma/sass/components/pagination';
|
|
@@ -223,9 +224,11 @@ Notes:
|
|
|
223
224
|
- `Button` is stock Bulma too (`bulma/sass/elements/button`). Bulma shows a focused button with
|
|
224
225
|
its border and a shadow, which a ghost button doesn't have, and forced colors (Windows'
|
|
225
226
|
contrast themes) drops the shadow and sets the border's color, so a focused button can look
|
|
226
|
-
like an unfocused one there.
|
|
227
|
-
|
|
228
|
-
|
|
227
|
+
like an unfocused one there. Forced colors also replaces a colored button's fill, which Bulma
|
|
228
|
+
draws with no border, so an icon-only one shows only its glyph there. The `button` extras
|
|
229
|
+
partial gives those focused buttons an outline, and a colored button a 1px border in forced
|
|
230
|
+
colors, so include it (`as bestax-button`) in any build that loads Bulma's button module. Its
|
|
231
|
+
rules win over Bulma's either way, so the order of the `@use` lines does not matter.
|
|
229
232
|
- `Stats` lays its row out on Bulma's smart grid (`.grid` and `is-col-min-*`), so a build with a
|
|
230
233
|
`Stats` row wants `bulma/sass/grid/grid` beside the `stat` partial, which only resets the row's
|
|
231
234
|
margins.
|
|
@@ -290,7 +293,7 @@ not `flexbox` — `flexbox` holds only the alignment props. Verified failure mod
|
|
|
290
293
|
The `npm create bestax` starter renders `Container`, `Section`, `Columns`/`Column`, `Image`,
|
|
291
294
|
`Title`/`SubTitle`, `Box`, `Card`, `Buttons`/`Button`, and `Notification` with its close
|
|
292
295
|
button: all stock Bulma, plus the `notification` and `delete` extras partials for that close
|
|
293
|
-
button and the `button` partial for the buttons' focus outline in forced colors. Its helper
|
|
296
|
+
button and the `button` partial for the buttons' focus outline and edge in forced colors. Its helper
|
|
294
297
|
props are `display` (visibility), `flexGrow` (flexbox), and `textAlign` (typography);
|
|
295
298
|
it uses no spacing or color props. That inventory compiles to the following, verified
|
|
296
299
|
pixel-equivalent to the prebuilt `complete` flavor in headless Chromium (light and dark, phone
|
|
@@ -322,7 +325,7 @@ Scaffolded with an icon library, the starter also needs `bulma/sass/elements/ico
|
|
|
322
325
|
@use 'bulma/sass/helpers/flexbox'; // flexGrow
|
|
323
326
|
@use 'bulma/sass/helpers/typography'; // textAlign
|
|
324
327
|
|
|
325
|
-
@use '@allxsmith/bestax-bulma/scss/elements/button' as bestax-button; // focus outline in forced colors
|
|
328
|
+
@use '@allxsmith/bestax-bulma/scss/elements/button' as bestax-button; // focus outline and edge in forced colors
|
|
326
329
|
@use '@allxsmith/bestax-bulma/scss/elements/delete' as bestax-delete; // the close button in forced colors
|
|
327
330
|
@use '@allxsmith/bestax-bulma/scss/elements/notification' as bestax-notification; // text clears the close button
|
|
328
331
|
```
|
|
@@ -225,7 +225,8 @@ class you pass through `className`, or with the component's `style` prop. A size
|
|
|
225
225
|
modifier can declare the variable again on a more specific selector (`.delete.is-small`), which a
|
|
226
226
|
lone class loses to and `style` does not. Each component's API page lists its variables under
|
|
227
227
|
**CSS & Sass Variables** and says where Bulma declares them; the extras below follow the same
|
|
228
|
-
rule.
|
|
228
|
+
rule. In forced colors a colored button's `--bulma-button-border-width` is `1px`, so it keeps an
|
|
229
|
+
edge when the theme replaces its fill, and an outlined button or a `text` one keeps its own.
|
|
229
230
|
|
|
230
231
|
## Shadow — override the upstream token, not the derived one
|
|
231
232
|
|
|
@@ -785,8 +786,10 @@ in `em`, so they follow the size of the boxes, and the caret is `currentColor`,
|
|
|
785
786
|
### Picker popover (DateInput / TimeInput / DateTimeInput / DateRangeInput / ColorInput / TreeSelect)
|
|
786
787
|
|
|
787
788
|
ColorInput's and TreeSelect's panels take the `--bulma-picker-popover-*` variables here. The `--bulma-picker-trigger-*`
|
|
788
|
-
ones are the date and time pickers' launcher
|
|
789
|
-
|
|
789
|
+
ones are the date and time pickers' launcher, which sits at the inline end, with the calendar or
|
|
790
|
+
clock icon at the inline start, so both swap sides on a right-to-left page. ColorInput's swatch
|
|
791
|
+
and launcher take the `--bulma-colorinput-*` variables in its own section, above. PasswordInput's
|
|
792
|
+
show button stays on the physical right.
|
|
790
793
|
|
|
791
794
|
`--bulma-picker-popover-animation-duration`, `--bulma-picker-popover-background`,
|
|
792
795
|
`--bulma-picker-popover-border-color`, `--bulma-picker-popover-offset`,
|
package/data/skills.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
{
|
|
11
11
|
"id": "component-catalog",
|
|
12
12
|
"file": "references/component-catalog.md",
|
|
13
|
-
"bytes":
|
|
13
|
+
"bytes": 27117
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
"id": "library-contributor",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"promptName": "form",
|
|
30
30
|
"dir": "bestax-form",
|
|
31
31
|
"references": [
|
|
32
|
-
{ "id": "api", "file": "references/api.md", "bytes":
|
|
32
|
+
{ "id": "api", "file": "references/api.md", "bytes": 32997 },
|
|
33
33
|
{ "id": "patterns", "file": "references/patterns.md", "bytes": 10001 }
|
|
34
34
|
],
|
|
35
35
|
"examples": []
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
{
|
|
65
65
|
"id": "layout-components",
|
|
66
66
|
"file": "references/layout-components.md",
|
|
67
|
-
"bytes":
|
|
67
|
+
"bytes": 25314
|
|
68
68
|
}
|
|
69
69
|
],
|
|
70
70
|
"examples": [
|
|
@@ -103,12 +103,12 @@
|
|
|
103
103
|
{
|
|
104
104
|
"id": "bulma-classes-component-map",
|
|
105
105
|
"file": "references/bulma-classes/component-map.md",
|
|
106
|
-
"bytes":
|
|
106
|
+
"bytes": 32883
|
|
107
107
|
},
|
|
108
108
|
{
|
|
109
109
|
"id": "bulma-classes-prop-map",
|
|
110
110
|
"file": "references/bulma-classes/prop-map.md",
|
|
111
|
-
"bytes":
|
|
111
|
+
"bytes": 39438
|
|
112
112
|
},
|
|
113
113
|
{
|
|
114
114
|
"id": "bulma-classes-unmappables",
|
|
@@ -162,7 +162,7 @@
|
|
|
162
162
|
{
|
|
163
163
|
"id": "modular-build",
|
|
164
164
|
"file": "references/modular-build.md",
|
|
165
|
-
"bytes":
|
|
165
|
+
"bytes": 18954
|
|
166
166
|
}
|
|
167
167
|
],
|
|
168
168
|
"examples": []
|
|
@@ -176,7 +176,7 @@
|
|
|
176
176
|
{
|
|
177
177
|
"id": "css-variables",
|
|
178
178
|
"file": "references/css-variables.md",
|
|
179
|
-
"bytes":
|
|
179
|
+
"bytes": 71903
|
|
180
180
|
},
|
|
181
181
|
{
|
|
182
182
|
"id": "themeable-components",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bestax-mcp",
|
|
3
|
-
"version": "1.18.
|
|
3
|
+
"version": "1.18.35",
|
|
4
4
|
"mcpName": "io.github.allxsmith/bestax-mcp",
|
|
5
5
|
"description": "MCP server for @allxsmith/bestax-bulma — component props, examples, CSS variables and agent skills, served offline from a version-pinned index",
|
|
6
6
|
"type": "module",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@modelcontextprotocol/sdk": "^1.32.2",
|
|
44
44
|
"zod": "^4.6.7",
|
|
45
|
-
"@allxsmith/bestax-bulma": "^5.
|
|
45
|
+
"@allxsmith/bestax-bulma": "^5.66.1"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/node": "^26.6.6",
|