bestax-mcp 1.15.2 → 1.15.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data/catalog.json +24 -1
- package/data/components/EmptyState.json +512 -0
- package/data/components/SubTitle.json +3 -3
- package/data/components/Title.json +3 -3
- package/data/skills/bestax-custom-component/references/component-catalog.md +2 -1
- package/data/skills/bestax-layout-scaffold/SKILL.md +12 -0
- package/data/skills/bestax-layout-scaffold/references/archetypes.md +57 -0
- package/data/skills/bestax-migrate/references/bloomer/prop-map.md +6 -6
- package/data/skills/bestax-migrate/references/rbx/prop-map.md +8 -8
- package/data/skills/bestax-migrate/references/react-bulma-components/unmappables.md +6 -6
- package/data/skills/bestax-optimize/references/modular-build.md +1 -1
- package/data/skills/bestax-theming/references/css-variables.md +14 -0
- package/data/skills/bestax-theming/references/themeable-components.md +3 -2
- package/data/skills.json +8 -8
- package/package.json +2 -2
package/data/catalog.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"generatedFrom": {
|
|
4
4
|
"package": "@allxsmith/bestax-bulma",
|
|
5
|
-
"version": "5.
|
|
5
|
+
"version": "5.34.0"
|
|
6
6
|
},
|
|
7
7
|
"docsBase": "https://bestax.io/docs",
|
|
8
8
|
"categories": [
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
"ContextMenu",
|
|
61
61
|
"Dialog",
|
|
62
62
|
"Dropdown",
|
|
63
|
+
"EmptyState",
|
|
63
64
|
"HoverCard",
|
|
64
65
|
"Loading",
|
|
65
66
|
"Menu",
|
|
@@ -495,6 +496,17 @@
|
|
|
495
496
|
"propCount": 4,
|
|
496
497
|
"exampleCount": 8
|
|
497
498
|
},
|
|
499
|
+
{
|
|
500
|
+
"name": "EmptyState",
|
|
501
|
+
"kind": "component",
|
|
502
|
+
"category": "components",
|
|
503
|
+
"purpose": "The `EmptyState` component renders the block an app shows where content would be: an empty list, a search with no results, or a first-run screen.",
|
|
504
|
+
"slug": "components/emptystate",
|
|
505
|
+
"import": "import { EmptyState } from '@allxsmith/bestax-bulma';",
|
|
506
|
+
"compound": true,
|
|
507
|
+
"propCount": 33,
|
|
508
|
+
"exampleCount": 10
|
|
509
|
+
},
|
|
498
510
|
{
|
|
499
511
|
"name": "Field",
|
|
500
512
|
"kind": "component",
|
|
@@ -1571,6 +1583,17 @@
|
|
|
1571
1583
|
"--bulma-dropdown-item-selected-l": ["Dropdown"],
|
|
1572
1584
|
"--bulma-dropdown-item-selected-s": ["Dropdown"],
|
|
1573
1585
|
"--bulma-dropdown-menu-min-width": ["Dropdown"],
|
|
1586
|
+
"--bulma-empty-state-description-color": ["EmptyState"],
|
|
1587
|
+
"--bulma-empty-state-description-max-width": ["EmptyState"],
|
|
1588
|
+
"--bulma-empty-state-description-size": ["EmptyState"],
|
|
1589
|
+
"--bulma-empty-state-gap": ["EmptyState"],
|
|
1590
|
+
"--bulma-empty-state-icon-size": ["EmptyState"],
|
|
1591
|
+
"--bulma-empty-state-indicator-background": ["EmptyState"],
|
|
1592
|
+
"--bulma-empty-state-indicator-color": ["EmptyState"],
|
|
1593
|
+
"--bulma-empty-state-indicator-radius": ["EmptyState"],
|
|
1594
|
+
"--bulma-empty-state-indicator-size": ["EmptyState"],
|
|
1595
|
+
"--bulma-empty-state-padding": ["EmptyState"],
|
|
1596
|
+
"--bulma-empty-state-title-size": ["EmptyState"],
|
|
1574
1597
|
"--bulma-field-block-spacing": ["Field"],
|
|
1575
1598
|
"--bulma-file-active-background-l-delta": ["File"],
|
|
1576
1599
|
"--bulma-file-active-border-l-delta": ["File"],
|
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "EmptyState",
|
|
3
|
+
"kind": "component",
|
|
4
|
+
"category": "components",
|
|
5
|
+
"slug": "components/emptystate",
|
|
6
|
+
"docsUrl": "https://bestax.io/docs/api/components/emptystate",
|
|
7
|
+
"examples": [
|
|
8
|
+
{
|
|
9
|
+
"title": "Basic Usage",
|
|
10
|
+
"code": "<Box>\n <EmptyState\n icon=\"folder-open\"\n title=\"No projects yet\"\n description=\"Projects you create or join show up here.\"\n >\n <Button color=\"primary\">New project</Button>\n </EmptyState>\n</Box>"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"title": "More Than One Action",
|
|
14
|
+
"code": "<Box>\n <EmptyState\n icon=\"folder-open\"\n title=\"No projects yet\"\n description=\"Projects you create or join show up here.\"\n >\n <EmptyState.Actions>\n <Button color=\"primary\">New project</Button>\n <Button>Import</Button>\n </EmptyState.Actions>\n </EmptyState>\n</Box>"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"title": "Sizes",
|
|
18
|
+
"code": "<Columns isMultiline>\n {(['small', 'normal', 'medium', 'large'] as const).map(size => (\n <Column key={size} size=\"half\" display=\"flex\" flexDirection=\"column\">\n <Box\n flexGrow=\"1\"\n display=\"flex\"\n flexDirection=\"column\"\n justifyContent=\"center\"\n >\n <EmptyState\n size={size}\n icon=\"inbox\"\n title=\"No messages\"\n description=\"Messages people send you show up here.\"\n >\n <Button>Write a message</Button>\n </EmptyState>\n </Box>\n </Column>\n ))}\n</Columns>"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"title": "Colors",
|
|
22
|
+
"code": "<Columns isMultiline>\n <Column size=\"one-third\">\n <Box>\n <EmptyState\n size=\"small\"\n color=\"primary\"\n icon=\"folder-open\"\n title=\"No projects yet\"\n />\n </Box>\n </Column>\n <Column size=\"one-third\">\n <Box>\n <EmptyState\n size=\"small\"\n color=\"link\"\n icon=\"bookmark\"\n title=\"No bookmarks yet\"\n />\n </Box>\n </Column>\n <Column size=\"one-third\">\n <Box>\n <EmptyState\n size=\"small\"\n color=\"info\"\n icon=\"upload\"\n title=\"Nothing uploaded yet\"\n />\n </Box>\n </Column>\n <Column size=\"one-third\">\n <Box>\n <EmptyState size=\"small\" color=\"success\" icon=\"check\" title=\"All done\" />\n </Box>\n </Column>\n <Column size=\"one-third\">\n <Box>\n <EmptyState\n size=\"small\"\n color=\"warning\"\n icon=\"box-archive\"\n title=\"No backups yet\"\n />\n </Box>\n </Column>\n <Column size=\"one-third\">\n <Box>\n <EmptyState\n size=\"small\"\n color=\"danger\"\n icon=\"trash\"\n title=\"The trash is empty\"\n />\n </Box>\n </Column>\n</Columns>"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"title": "Variants",
|
|
26
|
+
"code": "<Columns>\n <Column>\n <Box>\n <EmptyState size=\"small\" icon=\"bell\" title=\"No alerts\" />\n </Box>\n </Column>\n <Column>\n <Box>\n <EmptyState size=\"small\" variant=\"filled\" icon=\"bell\" title=\"No alerts\" />\n </Box>\n </Column>\n <Column>\n <Box>\n <EmptyState size=\"small\" color=\"success\" icon=\"check\" title=\"All done\" />\n </Box>\n </Column>\n <Column>\n <Box>\n <EmptyState\n size=\"small\"\n color=\"success\"\n variant=\"filled\"\n icon=\"check\"\n title=\"All done\"\n />\n </Box>\n </Column>\n</Columns>"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"title": "Alignment",
|
|
30
|
+
"code": "<Box>\n <EmptyState\n align=\"left\"\n color=\"primary\"\n icon=\"users\"\n title=\"No one else is here yet\"\n description=\"Invite the people you work with, and they'll show up in this list.\"\n >\n <EmptyState.Actions>\n <Button color=\"primary\">Invite people</Button>\n <Button>Copy invite link</Button>\n </EmptyState.Actions>\n </EmptyState>\n</Box>"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"title": "In a Card",
|
|
34
|
+
"code": "<Columns>\n <Column>\n <Card header=\"Invoices\">\n <EmptyState\n size=\"small\"\n align=\"left\"\n color=\"success\"\n variant=\"filled\"\n icon=\"check\"\n title=\"All paid up\"\n titleAs=\"h3\"\n description=\"New invoices show up here when they arrive.\"\n />\n </Card>\n </Column>\n <Column>\n <Card header=\"Files\">\n <EmptyState\n size=\"small\"\n icon=\"cloud-arrow-up\"\n title=\"Nothing uploaded yet\"\n titleAs=\"h3\"\n description=\"Files you add to this project show up here.\"\n >\n <Button size=\"small\" color=\"info\">\n Upload files\n </Button>\n </EmptyState>\n </Card>\n </Column>\n</Columns>"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"title": "A Search With No Results",
|
|
38
|
+
"code": "function example() {\n const projects = ['Apollo', 'Gemini', 'Mercury'];\n const [query, setQuery] = useState('kraken');\n const searchRef = React.useRef<HTMLInputElement>(null);\n const term = query.trim().toLowerCase();\n const shown = projects.filter(name => name.toLowerCase().includes(term));\n\n function clear() {\n setQuery('');\n // The button goes away with the empty state, so focus goes back to the field.\n searchRef.current?.focus();\n }\n\n return (\n <Box>\n <Title as=\"h2\" textSize=\"5\">\n Projects\n </Title>\n <Field label=\"Search projects\">\n <Control>\n <Input\n ref={searchRef}\n type=\"search\"\n value={query}\n onChange={e => setQuery(e.target.value)}\n />\n </Control>\n </Field>\n {/* Always in the page, so a change to its text is announced. */}\n <Paragraph role=\"status\" aria-atomic=\"true\" visibility=\"sr-only\">\n {shown.length === 0\n ? 'No projects match the search'\n : `${shown.length} of ${projects.length} projects`}\n </Paragraph>\n {shown.length === 0 ? (\n <EmptyState\n icon=\"magnifying-glass\"\n title={`No projects match “${query}”`}\n titleAs=\"h3\"\n description=\"Check the spelling, or clear the search.\"\n >\n <Button onClick={clear}>Clear search</Button>\n </EmptyState>\n ) : (\n <UnorderedList>\n {shown.map(name => (\n <ListItem key={name}>{name}</ListItem>\n ))}\n </UnorderedList>\n )}\n </Box>\n );\n}"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"title": "A First-Run Screen",
|
|
42
|
+
"code": "<Hero color=\"primary\">\n <Hero.Body>\n <EmptyState\n size=\"large\"\n icon=\"rocket\"\n title=\"Welcome to your workspace\"\n titleAs=\"h1\"\n description=\"Make a project to get started. You can invite people once it's set up.\"\n >\n <Button color=\"primary\" isInverted>\n Make a project\n </Button>\n </EmptyState>\n </Hero.Body>\n</Hero>"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"title": "Compound (dot-notation) usage",
|
|
46
|
+
"code": "<Box>\n <EmptyState align=\"left\" color=\"warning\">\n <EmptyState.Indicator>\n <Icon name=\"star\" variant=\"regular\" />\n </EmptyState.Indicator>\n <EmptyState.Title as=\"h3\">No favorites yet</EmptyState.Title>\n <EmptyState.Description>\n Star a project to keep it here. A few to start with:\n </EmptyState.Description>\n <UnorderedList>\n <ListItem>\n <a href=\"#apollo\">Apollo</a>\n </ListItem>\n <ListItem>\n <a href=\"#gemini\">Gemini</a>\n </ListItem>\n </UnorderedList>\n <EmptyState.Actions size=\"small\">\n <Button color=\"warning\">Browse projects</Button>\n <Button>Not now</Button>\n </EmptyState.Actions>\n </EmptyState>\n</Box>"
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
"accessibility": "- **The title is a heading:** it's always one, `h1` to `h6`, and `h2` by default. Pick the level\n under the heading of the list it stands in for: an `h2` on a page, an `h3` or an `h4` in a Card.\n `titleAs` sets it for the `title` prop and `as` sets it on `EmptyState.Title`, and nothing about\n the size changes it. The size comes from the EmptyState, so `EmptyState.Title` doesn't take\n `Title`'s `size`.\n- **The picture is decoration:** the indicator has `aria-hidden=\"true\"`, so everything in it is\n hidden, an `Icon` with an `ariaLabel` included. Say what it means in the title or the\n description.\n- **No role and no live region:** an empty state is content, and the heading makes it findable. It\n doesn't announce itself, since it arrives already filled, would read its buttons along with it,\n and is gone when results come back. After a search or a filter, announce the result with a\n `role=\"status\"` region that's in the page the whole time, beside the search field, as in\n [A Search With No Results](https://bestax.io/docs/api/components/emptystate#a-search-with-no-results). Primer's\n [loading pattern](https://primer.style/product/ui-patterns/loading/) describes the same thing.\n- **Focus:** nothing in the component moves focus. A \"Clear search\" button goes away with the\n empty state, so its click handler puts focus back in the search field rather than leaving it on\n the page's `<body>`.\n- **Not for loading or errors:** while the data loads, show a [`Skeleton`](https://bestax.io/docs/api/elements/skeleton)\n or a [`Loader`](https://bestax.io/docs/api/elements/loader), so \"No projects yet\" doesn't flash before the projects\n arrive. A load that failed is a [`Message`](https://bestax.io/docs/api/components/message) or a\n [`Notification`](https://bestax.io/docs/api/elements/notification).\n- **Contrast:** the description is the color of the text around it, so it keeps the contrast its\n container has, a colored Hero included, and the title is Bulma's title color. The circle is\n decoration, so it doesn't owe a contrast ratio, but every pairing reads in light and dark mode.\n- **Forced colors:** in Windows high contrast mode the icon takes the system's text color and\n stays visible. The circle's fill drops out, since it's decoration.\n- **No motion:** nothing animates.",
|
|
50
|
+
"related": [
|
|
51
|
+
"Buttons",
|
|
52
|
+
"Icon",
|
|
53
|
+
"Loader",
|
|
54
|
+
"Media",
|
|
55
|
+
"Message",
|
|
56
|
+
"Skeleton",
|
|
57
|
+
"Title",
|
|
58
|
+
"useBulmaClasses"
|
|
59
|
+
],
|
|
60
|
+
"storybook": "https://bestax.io/storybook/?path=/story/components-emptystate--default",
|
|
61
|
+
"summary": "The `EmptyState` component renders the block an app shows where content would be: an empty list, a search with no results, or a first-run screen. It's a column of a picture in a circle, a heading, a line of text and the actions, with one layout whether it's written with the `icon`, `title` and `description` props or with the parts. The children always render as written, after the parts the props render. It has no role and no live region. It arrives already filled and goes away when results come back, so it can't announce a search that matched nothing: keep a `role=\"status\"` region beside the search field for that, in the page the whole time. While the data loads, show a `Skeleton` or a `Loader` instead, so \"No projects yet\" doesn't flash first, and show a load that failed in a `Message` or a `Notification`.",
|
|
62
|
+
"import": "import { EmptyState } from '@allxsmith/bestax-bulma';",
|
|
63
|
+
"sourceFile": "bulma-ui/src/components/EmptyState.tsx",
|
|
64
|
+
"rootClass": "empty-state",
|
|
65
|
+
"parts": [
|
|
66
|
+
{
|
|
67
|
+
"path": "EmptyState",
|
|
68
|
+
"summary": "The `EmptyState` component renders the block an app shows where content would be: an empty list, a search with no results, or a first-run screen. It's a column of a picture in a circle, a heading, a line of text and the actions, with one layout whether it's written with the `icon`, `title` and `description` props or with the parts. The children always render as written, after the parts the props render. It has no role and no live region. It arrives already filled and goes away when results come back, so it can't announce a search that matched nothing: keep a `role=\"status\"` region beside the search field for that, in the page the whole time. While the data loads, show a `Skeleton` or a `Loader` instead, so \"No projects yet\" doesn't flash first, and show a load that failed in a `Message` or a `Notification`.",
|
|
69
|
+
"component": null,
|
|
70
|
+
"props": [
|
|
71
|
+
{
|
|
72
|
+
"name": "className",
|
|
73
|
+
"type": "string",
|
|
74
|
+
"default": null,
|
|
75
|
+
"description": "Additional CSS classes to apply.",
|
|
76
|
+
"required": false,
|
|
77
|
+
"inherited": false,
|
|
78
|
+
"deprecated": false
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"name": "icon",
|
|
82
|
+
"type": "React.ReactNode",
|
|
83
|
+
"default": null,
|
|
84
|
+
"description": "The picture in the indicator's circle. A string is an `Icon` name, drawn from the icon library `ConfigProvider` sets. Anything else (an `<Icon>` with its own `variant` or `library`, an SVG, an `<img>`) renders as it is. It's decorative and hidden from assistive tech, so the title says what it means.",
|
|
85
|
+
"required": false,
|
|
86
|
+
"inherited": false,
|
|
87
|
+
"deprecated": false
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"name": "title",
|
|
91
|
+
"type": "React.ReactNode",
|
|
92
|
+
"default": null,
|
|
93
|
+
"description": "The heading, rendered as `EmptyState.Title`. It's always a real heading, at the level `titleAs` sets.",
|
|
94
|
+
"required": false,
|
|
95
|
+
"inherited": false,
|
|
96
|
+
"deprecated": false
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"name": "titleAs",
|
|
100
|
+
"type": "'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'",
|
|
101
|
+
"default": "'h2'",
|
|
102
|
+
"description": "The heading level for `title`: the level under the heading of the list it stands in for, such as `h3` for a list under an `h2`. Only this sets the level, and the size comes from `size`.",
|
|
103
|
+
"required": false,
|
|
104
|
+
"inherited": false,
|
|
105
|
+
"deprecated": false
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"name": "description",
|
|
109
|
+
"type": "React.ReactNode",
|
|
110
|
+
"default": null,
|
|
111
|
+
"description": "A sentence or two under the title, rendered as `EmptyState.Description`.",
|
|
112
|
+
"required": false,
|
|
113
|
+
"inherited": false,
|
|
114
|
+
"deprecated": false
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"name": "children",
|
|
118
|
+
"type": "React.ReactNode",
|
|
119
|
+
"default": null,
|
|
120
|
+
"description": "Rendered as written, after whatever `icon`, `title` and `description` render. One button can go straight in, and it sits centered under the text. Group two or more in `EmptyState.Actions`, or they stack. Without the props, write the parts here in the order they're shown: `EmptyState.Indicator`, `.Title`, `.Description`, then the actions.",
|
|
121
|
+
"required": false,
|
|
122
|
+
"inherited": false,
|
|
123
|
+
"deprecated": false
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"name": "color",
|
|
127
|
+
"type": "'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger'",
|
|
128
|
+
"default": null,
|
|
129
|
+
"description": "The indicator's color. It colors the circle and its icon, not the text. Without it the circle is neutral, since an empty list isn't a status.",
|
|
130
|
+
"required": false,
|
|
131
|
+
"inherited": false,
|
|
132
|
+
"deprecated": false
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"name": "variant",
|
|
136
|
+
"type": "'light' | 'filled'",
|
|
137
|
+
"default": "'light'",
|
|
138
|
+
"description": "`light` is a soft tint of `color` behind the icon in the color. `filled` is the color itself, with the icon in its invert.",
|
|
139
|
+
"required": false,
|
|
140
|
+
"inherited": false,
|
|
141
|
+
"deprecated": false
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"name": "size",
|
|
145
|
+
"type": "'small' | 'normal' | 'medium' | 'large'",
|
|
146
|
+
"default": "'normal'",
|
|
147
|
+
"description": "Sizes the indicator, the title, the description and the spacing together.",
|
|
148
|
+
"required": false,
|
|
149
|
+
"inherited": false,
|
|
150
|
+
"deprecated": false
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"name": "align",
|
|
154
|
+
"type": "'center' | 'left'",
|
|
155
|
+
"default": "'center'",
|
|
156
|
+
"description": "`center` stacks everything in a centered column. `left` puts the indicator beside the text, at the start of the line, so on the right in a right-to-left page, and keeps the block at least as tall as the circle whatever block padding is in effect. Without an indicator, it only puts the text at the start of the line. In `left`, the padding at the start of the line is what makes room for the indicator, so pad it with `py` rather than `p` or `px`.",
|
|
157
|
+
"required": false,
|
|
158
|
+
"inherited": false,
|
|
159
|
+
"deprecated": false
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"name": "textColor",
|
|
163
|
+
"type": "Bulma color | 'inherit' | 'current'",
|
|
164
|
+
"default": null,
|
|
165
|
+
"description": "Text color helper.",
|
|
166
|
+
"required": false,
|
|
167
|
+
"inherited": false,
|
|
168
|
+
"deprecated": false,
|
|
169
|
+
"valuesRef": "helpers/valid-values"
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"name": "bgColor",
|
|
173
|
+
"type": "Bulma color | 'inherit' | 'current'",
|
|
174
|
+
"default": null,
|
|
175
|
+
"description": "Background color helper.",
|
|
176
|
+
"required": false,
|
|
177
|
+
"inherited": false,
|
|
178
|
+
"deprecated": false,
|
|
179
|
+
"valuesRef": "helpers/valid-values"
|
|
180
|
+
}
|
|
181
|
+
],
|
|
182
|
+
"extraProps": [
|
|
183
|
+
{
|
|
184
|
+
"name": "ref",
|
|
185
|
+
"type": "React.Ref<HTMLDivElement>",
|
|
186
|
+
"default": null,
|
|
187
|
+
"description": "Ref forwarded to the root `<div>`.",
|
|
188
|
+
"required": false,
|
|
189
|
+
"inherited": false,
|
|
190
|
+
"deprecated": false
|
|
191
|
+
}
|
|
192
|
+
],
|
|
193
|
+
"catchAll": "All standard <div> attributes and Bulma helper props",
|
|
194
|
+
"types": []
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"path": "EmptyState.Indicator",
|
|
198
|
+
"summary": "The circle the picture sits in, hidden from assistive tech whatever is in it.",
|
|
199
|
+
"component": null,
|
|
200
|
+
"props": [
|
|
201
|
+
{
|
|
202
|
+
"name": "className",
|
|
203
|
+
"type": "string",
|
|
204
|
+
"default": null,
|
|
205
|
+
"description": "Additional CSS classes to apply.",
|
|
206
|
+
"required": false,
|
|
207
|
+
"inherited": false,
|
|
208
|
+
"deprecated": false
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
"name": "children",
|
|
212
|
+
"type": "React.ReactNode",
|
|
213
|
+
"default": null,
|
|
214
|
+
"description": "The picture: an `Icon`, an SVG or an `<img>`. The indicator is hidden from assistive tech, an `Icon` with an `ariaLabel` included, so anything it means goes in the title or the description.",
|
|
215
|
+
"required": false,
|
|
216
|
+
"inherited": false,
|
|
217
|
+
"deprecated": false
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"name": "textColor",
|
|
221
|
+
"type": "Bulma color | 'inherit' | 'current'",
|
|
222
|
+
"default": null,
|
|
223
|
+
"description": "Text color helper.",
|
|
224
|
+
"required": false,
|
|
225
|
+
"inherited": false,
|
|
226
|
+
"deprecated": false,
|
|
227
|
+
"valuesRef": "helpers/valid-values"
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
"name": "bgColor",
|
|
231
|
+
"type": "Bulma color | 'inherit' | 'current'",
|
|
232
|
+
"default": null,
|
|
233
|
+
"description": "Background color helper.",
|
|
234
|
+
"required": false,
|
|
235
|
+
"inherited": false,
|
|
236
|
+
"deprecated": false,
|
|
237
|
+
"valuesRef": "helpers/valid-values"
|
|
238
|
+
}
|
|
239
|
+
],
|
|
240
|
+
"extraProps": [],
|
|
241
|
+
"catchAll": "All standard <div> attributes and Bulma helper props",
|
|
242
|
+
"types": []
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"path": "EmptyState.Title",
|
|
246
|
+
"summary": "The heading, a Bulma `Title` at the level `as` sets, `h2` by default, and at the EmptyState's size.",
|
|
247
|
+
"component": null,
|
|
248
|
+
"props": [
|
|
249
|
+
{
|
|
250
|
+
"name": "as",
|
|
251
|
+
"type": "'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'",
|
|
252
|
+
"default": "'h2'",
|
|
253
|
+
"description": "The heading level: the level under the heading of the list the empty state stands in for.",
|
|
254
|
+
"required": false,
|
|
255
|
+
"inherited": false,
|
|
256
|
+
"deprecated": false
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
"name": "className",
|
|
260
|
+
"type": "string",
|
|
261
|
+
"default": null,
|
|
262
|
+
"description": "Additional CSS classes to apply.",
|
|
263
|
+
"required": false,
|
|
264
|
+
"inherited": true,
|
|
265
|
+
"deprecated": false
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"name": "hasSkeleton",
|
|
269
|
+
"type": "boolean",
|
|
270
|
+
"default": "false",
|
|
271
|
+
"description": "Applies the `has-skeleton` class to part of the content.",
|
|
272
|
+
"required": false,
|
|
273
|
+
"inherited": true,
|
|
274
|
+
"deprecated": false
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
"name": "children",
|
|
278
|
+
"type": "React.ReactNode",
|
|
279
|
+
"default": null,
|
|
280
|
+
"description": "Title content.",
|
|
281
|
+
"required": false,
|
|
282
|
+
"inherited": true,
|
|
283
|
+
"deprecated": false
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
"name": "textColor",
|
|
287
|
+
"type": "Bulma color | 'inherit' | 'current'",
|
|
288
|
+
"default": null,
|
|
289
|
+
"description": "Text color helper.",
|
|
290
|
+
"required": false,
|
|
291
|
+
"inherited": true,
|
|
292
|
+
"deprecated": false,
|
|
293
|
+
"valuesRef": "helpers/valid-values"
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
"name": "bgColor",
|
|
297
|
+
"type": "Bulma color | 'inherit' | 'current'",
|
|
298
|
+
"default": null,
|
|
299
|
+
"description": "Background color helper.",
|
|
300
|
+
"required": false,
|
|
301
|
+
"inherited": true,
|
|
302
|
+
"deprecated": false,
|
|
303
|
+
"valuesRef": "helpers/valid-values"
|
|
304
|
+
}
|
|
305
|
+
],
|
|
306
|
+
"extraProps": [
|
|
307
|
+
{
|
|
308
|
+
"name": "skeleton",
|
|
309
|
+
"type": "boolean",
|
|
310
|
+
"default": null,
|
|
311
|
+
"description": "Applies the `is-skeleton` class to the entire component.",
|
|
312
|
+
"required": false,
|
|
313
|
+
"inherited": false,
|
|
314
|
+
"deprecated": false
|
|
315
|
+
}
|
|
316
|
+
],
|
|
317
|
+
"catchAll": "All standard <h1>–<h6> / <p> attributes and Bulma helper props",
|
|
318
|
+
"types": []
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
"path": "EmptyState.Description",
|
|
322
|
+
"summary": "A sentence or two under the title, in the color of the text around it.",
|
|
323
|
+
"component": null,
|
|
324
|
+
"props": [
|
|
325
|
+
{
|
|
326
|
+
"name": "className",
|
|
327
|
+
"type": "string",
|
|
328
|
+
"default": null,
|
|
329
|
+
"description": "Additional CSS classes to apply.",
|
|
330
|
+
"required": false,
|
|
331
|
+
"inherited": true,
|
|
332
|
+
"deprecated": false
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
"name": "textColor",
|
|
336
|
+
"type": "Bulma color | 'inherit' | 'current'",
|
|
337
|
+
"default": null,
|
|
338
|
+
"description": "Text color helper.",
|
|
339
|
+
"required": false,
|
|
340
|
+
"inherited": true,
|
|
341
|
+
"deprecated": false,
|
|
342
|
+
"valuesRef": "helpers/valid-values"
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
"name": "bgColor",
|
|
346
|
+
"type": "Bulma color | 'inherit' | 'current'",
|
|
347
|
+
"default": null,
|
|
348
|
+
"description": "Background color helper.",
|
|
349
|
+
"required": false,
|
|
350
|
+
"inherited": true,
|
|
351
|
+
"deprecated": false,
|
|
352
|
+
"valuesRef": "helpers/valid-values"
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
"name": "children",
|
|
356
|
+
"type": "React.ReactNode",
|
|
357
|
+
"default": null,
|
|
358
|
+
"description": "Content to render inside the paragraph.",
|
|
359
|
+
"required": false,
|
|
360
|
+
"inherited": true,
|
|
361
|
+
"deprecated": false
|
|
362
|
+
}
|
|
363
|
+
],
|
|
364
|
+
"extraProps": [],
|
|
365
|
+
"catchAll": "All standard <p> attributes and Bulma helper props",
|
|
366
|
+
"types": []
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
"path": "EmptyState.Actions",
|
|
370
|
+
"summary": "A row of buttons, centered under the text or at the start of the line beside the indicator.",
|
|
371
|
+
"component": null,
|
|
372
|
+
"props": [
|
|
373
|
+
{
|
|
374
|
+
"name": "className",
|
|
375
|
+
"type": "string",
|
|
376
|
+
"default": null,
|
|
377
|
+
"description": "Additional CSS classes to apply.",
|
|
378
|
+
"required": false,
|
|
379
|
+
"inherited": true,
|
|
380
|
+
"deprecated": false
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
"name": "textColor",
|
|
384
|
+
"type": "Bulma color | 'inherit' | 'current'",
|
|
385
|
+
"default": null,
|
|
386
|
+
"description": "Text color helper for the button group.",
|
|
387
|
+
"required": false,
|
|
388
|
+
"inherited": true,
|
|
389
|
+
"deprecated": false,
|
|
390
|
+
"valuesRef": "helpers/valid-values"
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
"name": "color",
|
|
394
|
+
"type": "'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger'",
|
|
395
|
+
"default": null,
|
|
396
|
+
"description": "Text color alias: renders `has-text-<color>`, exactly like `textColor`. Not a filled variant (no `.buttons.is-<color>` CSS exists; color the individual `Button`s instead). Prefer `textColor`, which takes precedence when both are set; use `bgColor` for a colored surface.",
|
|
397
|
+
"required": false,
|
|
398
|
+
"inherited": true,
|
|
399
|
+
"deprecated": false
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
"name": "bgColor",
|
|
403
|
+
"type": "Bulma color | 'inherit' | 'current'",
|
|
404
|
+
"default": null,
|
|
405
|
+
"description": "Background color helper for the button group.",
|
|
406
|
+
"required": false,
|
|
407
|
+
"inherited": true,
|
|
408
|
+
"deprecated": false,
|
|
409
|
+
"valuesRef": "helpers/valid-values"
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
"name": "hasAddons",
|
|
413
|
+
"type": "boolean",
|
|
414
|
+
"default": "false",
|
|
415
|
+
"description": "Group buttons together as addons (removes spacing between them).",
|
|
416
|
+
"required": false,
|
|
417
|
+
"inherited": true,
|
|
418
|
+
"deprecated": false
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
"name": "size",
|
|
422
|
+
"type": "'small' | 'medium' | 'large'",
|
|
423
|
+
"default": null,
|
|
424
|
+
"description": "Size of the button group.",
|
|
425
|
+
"required": false,
|
|
426
|
+
"inherited": true,
|
|
427
|
+
"deprecated": false
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
"name": "children",
|
|
431
|
+
"type": "React.ReactNode",
|
|
432
|
+
"default": null,
|
|
433
|
+
"description": "The button elements to render inside the group.",
|
|
434
|
+
"required": false,
|
|
435
|
+
"inherited": true,
|
|
436
|
+
"deprecated": false
|
|
437
|
+
}
|
|
438
|
+
],
|
|
439
|
+
"extraProps": [],
|
|
440
|
+
"catchAll": "All standard <div> attributes and Bulma helper props",
|
|
441
|
+
"types": []
|
|
442
|
+
}
|
|
443
|
+
],
|
|
444
|
+
"cssVars": [
|
|
445
|
+
{
|
|
446
|
+
"css": "--bulma-empty-state-gap",
|
|
447
|
+
"sass": "$empty-state-gap",
|
|
448
|
+
"default": "1rem",
|
|
449
|
+
"scope": "root"
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
"css": "--bulma-empty-state-padding",
|
|
453
|
+
"sass": "$empty-state-padding",
|
|
454
|
+
"default": "3rem",
|
|
455
|
+
"scope": "root"
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
"css": "--bulma-empty-state-indicator-size",
|
|
459
|
+
"sass": "$empty-state-indicator-size",
|
|
460
|
+
"default": "3rem",
|
|
461
|
+
"scope": "root"
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
"css": "--bulma-empty-state-indicator-radius",
|
|
465
|
+
"sass": "$empty-state-indicator-radius",
|
|
466
|
+
"default": "var(--bulma-radius-rounded)",
|
|
467
|
+
"scope": "root"
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
"css": "--bulma-empty-state-indicator-background",
|
|
471
|
+
"sass": "$empty-state-indicator-background",
|
|
472
|
+
"default": "var(--bulma-background)",
|
|
473
|
+
"scope": "root"
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
"css": "--bulma-empty-state-indicator-color",
|
|
477
|
+
"sass": "$empty-state-indicator-color",
|
|
478
|
+
"default": "var(--bulma-text-weak)",
|
|
479
|
+
"scope": "root"
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
"css": "--bulma-empty-state-icon-size",
|
|
483
|
+
"sass": "$empty-state-icon-size",
|
|
484
|
+
"default": "1.5rem",
|
|
485
|
+
"scope": "root"
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
"css": "--bulma-empty-state-title-size",
|
|
489
|
+
"sass": "$empty-state-title-size",
|
|
490
|
+
"default": "var(--bulma-size-5)",
|
|
491
|
+
"scope": "root"
|
|
492
|
+
},
|
|
493
|
+
{
|
|
494
|
+
"css": "--bulma-empty-state-description-size",
|
|
495
|
+
"sass": "$empty-state-description-size",
|
|
496
|
+
"default": "var(--bulma-size-6)",
|
|
497
|
+
"scope": "root"
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
"css": "--bulma-empty-state-description-color",
|
|
501
|
+
"sass": "$empty-state-description-color",
|
|
502
|
+
"default": "currentColor",
|
|
503
|
+
"scope": "root"
|
|
504
|
+
},
|
|
505
|
+
{
|
|
506
|
+
"css": "--bulma-empty-state-description-max-width",
|
|
507
|
+
"sass": "$empty-state-description-max-width",
|
|
508
|
+
"default": "32em",
|
|
509
|
+
"scope": "root"
|
|
510
|
+
}
|
|
511
|
+
]
|
|
512
|
+
}
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"code": "<Block>\n <Title as=\"p\" size=\"1\">\n Title 1\n </Title>\n <SubTitle as=\"p\" size=\"3\">\n Subtitle 3\n </SubTitle>\n</Block>"
|
|
39
39
|
}
|
|
40
40
|
],
|
|
41
|
-
"accessibility": "- **Semantic HTML:** Use appropriate heading levels for document structure.\n- **Screen readers:** Subtitles should be used in conjunction with titles for clarity.\n\n:::tip\n`SubTitle` is visually styled as a heading,
|
|
41
|
+
"accessibility": "- **Semantic HTML:** Use appropriate heading levels for document structure.\n- **Screen readers:** Subtitles should be used in conjunction with titles for clarity.\n\n:::tip\n`SubTitle` is visually styled as a heading. Its level comes from `size` when it has one and from\n`as` when it doesn't, and with neither it's an `<h1>`. `as=\"p\"` makes it a paragraph whatever its\nsize, and the `textSize` helper sizes it without changing the level.\n:::",
|
|
42
42
|
"related": ["Block", "Title", "useBulmaClasses"],
|
|
43
43
|
"storybook": "https://bestax.io/storybook/?path=/story/elements-subtitle--default",
|
|
44
44
|
"summary": "The `SubTitle` component renders a Bulma-styled subtitle (secondary heading), supporting sizes `1-6` and rendering as any heading or paragraph element (`h1-h6`, `p`).",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"name": "size",
|
|
65
65
|
"type": "'1' | '2' | '3' | '4' | '5' | '6' | 1 | 2 | 3 | 4 | 5 | 6",
|
|
66
66
|
"default": null,
|
|
67
|
-
"description": "Size of the subtitle (Bulma sizes `1`-`6`, as a string or number).",
|
|
67
|
+
"description": "Size of the subtitle (Bulma sizes `1`-`6`, as a string or number). It also picks the heading level: unless `as` is `p`, `size=\"5\"` renders an `<h5>`, whatever `as` says. For a heading whose level and size differ, set the level with `as` and the size with the `textSize` helper.",
|
|
68
68
|
"required": false,
|
|
69
69
|
"inherited": false,
|
|
70
70
|
"deprecated": false
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"name": "as",
|
|
74
74
|
"type": "'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p'",
|
|
75
75
|
"default": "'h1'",
|
|
76
|
-
"description": "HTML element to render as (h1
|
|
76
|
+
"description": "HTML element to render as (`h1`-`h6` or `p`). With neither `as` nor `size` set it's an `<h1>`, so a subtitle that isn't a heading of its own takes `as=\"p\"`. A `size` overrides `as` unless it's `p`, so `as=\"h3\" size=\"5\"` renders an `<h5>`. To keep the level `as` sets, size the subtitle with the `textSize` helper instead.",
|
|
77
77
|
"required": false,
|
|
78
78
|
"inherited": false,
|
|
79
79
|
"deprecated": false
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"code": "<Block>\n <Title as=\"p\" size=\"1\">\n Title 1\n </Title>\n <SubTitle as=\"p\" size=\"3\">\n Subtitle 3\n </SubTitle>\n</Block>"
|
|
37
37
|
}
|
|
38
38
|
],
|
|
39
|
-
"accessibility": "- **Semantic HTML:** Use appropriate heading levels for document structure.\n- **Spacing:** Use `isSpaced` for extra margin when needed.\n- **Screen readers:** Headings are key landmarks, so set the
|
|
39
|
+
"accessibility": "- **Semantic HTML:** Use appropriate heading levels for document structure.\n- **Spacing:** Use `isSpaced` for extra margin when needed.\n- **Screen readers:** Headings are key landmarks, so give each one the level the page's hierarchy\n needs. `size` picks that level as well as the size, unless `as` is `p`: `as=\"h2\" size=\"4\"`\n renders an `<h4>`. For a heading whose level and size differ, set the level with `as` and the\n size with the `textSize` helper, as in `<Title as=\"h2\" textSize=\"4\">`.\n\n:::tip\nWhen using `as=\"p\"`, the element is visually styled as a heading but semantically a paragraph.\n:::",
|
|
40
40
|
"related": ["Block", "SubTitle", "useBulmaClasses"],
|
|
41
41
|
"storybook": "https://bestax.io/storybook/?path=/story/elements-title--default",
|
|
42
42
|
"summary": "The `Title` component renders a Bulma-styled title (heading), supporting sizes `1`-`6`, spacing, and rendering as any heading or paragraph element (`h1`-`h6`, `p`).",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"name": "size",
|
|
63
63
|
"type": "'1' | '2' | '3' | '4' | '5' | '6' | 1 | 2 | 3 | 4 | 5 | 6",
|
|
64
64
|
"default": null,
|
|
65
|
-
"description": "Size of the title (Bulma sizes `1`-`6`, as a string or number).",
|
|
65
|
+
"description": "Size of the title (Bulma sizes `1`-`6`, as a string or number). It also picks the heading level: unless `as` is `p`, `size=\"4\"` renders an `<h4>`, whatever `as` says. For a heading whose level and size differ, set the level with `as` and the size with the `textSize` helper.",
|
|
66
66
|
"required": false,
|
|
67
67
|
"inherited": false,
|
|
68
68
|
"deprecated": false
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"name": "as",
|
|
81
81
|
"type": "'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p'",
|
|
82
82
|
"default": "'h1'",
|
|
83
|
-
"description": "HTML element to render as (h1
|
|
83
|
+
"description": "HTML element to render as (`h1`-`h6` or `p`). A `size` overrides it unless it's `p`, so `as=\"h2\" size=\"4\"` renders an `<h4>`. To keep the level `as` sets, size the title with the `textSize` helper instead.",
|
|
84
84
|
"required": false,
|
|
85
85
|
"inherited": false,
|
|
86
86
|
"deprecated": false
|
|
@@ -37,7 +37,7 @@ instead of hand-writing markup.
|
|
|
37
37
|
- Raw `*Base` form exports (`InputBase`, `SelectBase`, `TextAreaBase`, …) are
|
|
38
38
|
escape-hatch variants of the convenience wrappers above them; see the Form docs.
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
100 documented components. Generated from the API docs — every exported
|
|
41
41
|
component is guaranteed to appear (the generator fails if one lacks an API page).
|
|
42
42
|
|
|
43
43
|
## Elements
|
|
@@ -89,6 +89,7 @@ component is guaranteed to appear (the generator fails if one lacks an API page)
|
|
|
89
89
|
- [ContextMenu](https://bestax.io/docs/api/components/contextmenu) — The `ContextMenu` component opens a menu of actions where you right-click an element, such as a table row or a card, or long press it on a touch screen.
|
|
90
90
|
- [Dialog](https://bestax.io/docs/api/components/dialog) — The `Dialog` component provides ready-made confirm and alert dialogs, so a destructive action stays one `await dialog.confirm()` call away.
|
|
91
91
|
- [Dropdown](https://bestax.io/docs/api/components/dropdown) — The `Dropdown` component provides Bulma's versatile dropdown menu for your Bulma React UI.
|
|
92
|
+
- [EmptyState](https://bestax.io/docs/api/components/emptystate) — The `EmptyState` component renders the block an app shows where content would be: an empty list, a search with no results, or a first-run screen.
|
|
92
93
|
- [HoverCard](https://bestax.io/docs/api/components/hovercard) — The `HoverCard` component shows a card previewing what's behind a link or a button while the pointer rests on it or keyboard focus is on it.
|
|
93
94
|
- [Loading](https://bestax.io/docs/api/components/loading) — The `Loading` component provides a loading overlay with a spinner animation.
|
|
94
95
|
- [Menu](https://bestax.io/docs/api/components/menu) — The `Menu` component provides Bulma's vertical navigation menu: a simple, accessible sidebar or section menu for your Bulma React UI.
|
|
@@ -87,6 +87,16 @@ Centered; a collection of items → Card grid. For mixed requests, pick the domi
|
|
|
87
87
|
`Steps value={i}/onStepClick items={[{label, icon?}]}` (child form is `Steps.Step`, not
|
|
88
88
|
`Steps.Item`). `Reveal cascade` staggers only its **direct children** — to stagger a grid,
|
|
89
89
|
put `<Reveal delay={i * 80}>` inside each `Cell`, not around the container.
|
|
90
|
+
- **An empty list, table or search with no results is `EmptyState`**, not a hand-built `Box`
|
|
91
|
+
of `Icon`, `Title` and `Buttons isCentered`:
|
|
92
|
+
`<EmptyState icon="folder-open" title="No projects yet" titleAs="h3" description="…">` with
|
|
93
|
+
its one `<Button>` as a child (two or more go in `EmptyState.Actions`). Its `title` is always a
|
|
94
|
+
heading, so set `titleAs` to the level under the list's own heading. It has no live region:
|
|
95
|
+
after a search or a filter, keep a `Paragraph` with `role="status"`, `aria-atomic="true"` and
|
|
96
|
+
`visibility="sr-only"` beside the search field the whole time, saying the count, and have
|
|
97
|
+
"Clear search" put focus back in the field. While data loads show a `Skeleton` or a `Loader`,
|
|
98
|
+
and a failed load is a `Message` or a `Notification`, never an EmptyState. The archetypes
|
|
99
|
+
reference has the full pattern under Card grid.
|
|
90
100
|
- Link lists (footer nav, sidebars): a bare `UnorderedList` of `ListItem`s is already
|
|
91
101
|
marker-less and flush — Bulma's reset unstyles `ul` — so no prop or CSS is needed;
|
|
92
102
|
bullets appear only inside `Content`.
|
|
@@ -221,6 +231,8 @@ inline `style`.
|
|
|
221
231
|
- [ ] Do not use `Tile` — it is not shipped.
|
|
222
232
|
- [ ] Action feedback goes through `Toast`, a confirmation through `Dialog`, a text-styled
|
|
223
233
|
action through `LinkButton` — not `Notification`, `Modal` or a bare `<a>`.
|
|
234
|
+
- [ ] An empty list or a search with no results renders `EmptyState`, and a search or a filter
|
|
235
|
+
keeps a `role="status"` region beside its field that says the count.
|
|
224
236
|
- [ ] Style with helper props, not inline `style` — translate via the mapping table; values
|
|
225
237
|
with no helper get a named class in the stylesheet, never `style={{}}`. No raw Bulma
|
|
226
238
|
`className`s either (`Span`/`Paragraph` wrap bare text; `Th`/`Td` take `textAlign`/`textWeight`).
|
|
@@ -239,6 +239,63 @@ build the whole grid with `Grid`/`Cell` (`<Grid isFixed fixedColsMobile={1} fixe
|
|
|
239
239
|
fixedColsDesktop={3} gap={4}>`) — CSS Grid keeps cells equal-height for free; see the
|
|
240
240
|
`Grid / Cell` section in `layout-components.md`.
|
|
241
241
|
|
|
242
|
+
**Nothing to show:** when the collection is empty, or a search or a filter matches nothing,
|
|
243
|
+
render an `EmptyState` in the grid's place rather than composing one from `Box`, `Icon` and
|
|
244
|
+
`Title`. Its `title` is always a heading: set `titleAs` to the level under the section's own
|
|
245
|
+
heading. It doesn't announce itself, so a search keeps a status region beside its field the
|
|
246
|
+
whole time, saying the count, and "Clear search" puts focus back in the field, since the button
|
|
247
|
+
goes away with the empty state:
|
|
248
|
+
|
|
249
|
+
```tsx
|
|
250
|
+
const searchRef = useRef<HTMLInputElement>(null);
|
|
251
|
+
const shown = items.filter(item =>
|
|
252
|
+
item.name.toLowerCase().includes(query.trim().toLowerCase())
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
<>
|
|
256
|
+
<Field label="Search products">
|
|
257
|
+
<Control>
|
|
258
|
+
<Input
|
|
259
|
+
ref={searchRef}
|
|
260
|
+
type="search"
|
|
261
|
+
value={query}
|
|
262
|
+
onChange={e => setQuery(e.target.value)}
|
|
263
|
+
/>
|
|
264
|
+
</Control>
|
|
265
|
+
</Field>
|
|
266
|
+
{/* Always in the page, so a change to its text is announced. */}
|
|
267
|
+
<Paragraph role="status" aria-atomic="true" visibility="sr-only">
|
|
268
|
+
{shown.length === 0
|
|
269
|
+
? 'No products match the search'
|
|
270
|
+
: `${shown.length} products`}
|
|
271
|
+
</Paragraph>
|
|
272
|
+
{shown.length === 0 ? (
|
|
273
|
+
<EmptyState
|
|
274
|
+
icon="magnifying-glass"
|
|
275
|
+
title={`No products match “${query}”`}
|
|
276
|
+
titleAs="h2"
|
|
277
|
+
description="Check the spelling, or clear the search."
|
|
278
|
+
>
|
|
279
|
+
<Button
|
|
280
|
+
onClick={() => {
|
|
281
|
+
setQuery('');
|
|
282
|
+
searchRef.current?.focus();
|
|
283
|
+
}}
|
|
284
|
+
>
|
|
285
|
+
Clear search
|
|
286
|
+
</Button>
|
|
287
|
+
</EmptyState>
|
|
288
|
+
) : (
|
|
289
|
+
<Columns isMultiline>{/* the cards, as above */}</Columns>
|
|
290
|
+
)}
|
|
291
|
+
</>;
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
With nothing in the collection at all, the same component says so and offers the first step:
|
|
295
|
+
`<EmptyState icon="box-open" title="No products yet" titleAs="h2" description="…">` with one
|
|
296
|
+
`<Button color="primary">` as its child, or two or more in `EmptyState.Actions`. While the items
|
|
297
|
+
load, show a `Skeleton` or a `Loader` instead, so the empty state doesn't flash first.
|
|
298
|
+
|
|
242
299
|
---
|
|
243
300
|
|
|
244
301
|
## Combining archetypes
|
|
@@ -161,13 +161,13 @@ value is flagged. The same conversion covers the modifiers bestax has no prop fo
|
|
|
161
161
|
|
|
162
162
|
## Refs
|
|
163
163
|
|
|
164
|
-
bloomer forwarded no refs. bestax forwards a ref from the form controls, plus `Avatar`,
|
|
165
|
-
`
|
|
164
|
+
bloomer forwarded no refs. bestax forwards a ref from the form controls, plus `Avatar`, `Button`,
|
|
165
|
+
`Carousel`, `CarouselItem`, `Dialog`, `Dropdown`, `EmptyState`, `Kbd`, `Kbd.Group`, `Link`,
|
|
166
166
|
`LinkButton`, `Loader`, `Menu.Item`, `Modal`, `Navbar`, `Navbar.Burger`, `Navbar.Dropdown`,
|
|
167
|
-
`Navbar.Item`, `Navbar.Link`, `SegmentedControl`, `SegmentedControl.Segment`, `Sidebar`, `Toast`
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
167
|
+
`Navbar.Item`, `Navbar.Link`, `SegmentedControl`, `SegmentedControl.Segment`, `Sidebar`, `Toast` and
|
|
168
|
+
`ToggleButton` — pass `ref` directly on those. "The form controls" means the inputs themselves: the
|
|
169
|
+
`Field`, `Field.Label`, `Field.Body`, `Checkboxes` and `Radios` wrappers around them forward
|
|
170
|
+
nothing.
|
|
171
171
|
|
|
172
172
|
A `ref` on anything else is unsupported, and the two React majors fail differently: React 18
|
|
173
173
|
drops it and logs "Function components cannot be given refs", while React 19 hands it to the
|
|
@@ -156,14 +156,14 @@ becomes.
|
|
|
156
156
|
Beside a `ref` the element already has, a rename leaves `innerRef` in place with a `prop:innerRef`
|
|
157
157
|
TODO rather than write a second `ref`; keep whichever one you meant.
|
|
158
158
|
|
|
159
|
-
An existing `ref` is passed through untouched — which is safe only where the bestax target
|
|
160
|
-
|
|
161
|
-
`
|
|
162
|
-
`Link`, `LinkButton`, `Loader`, `Menu.Item`, `Modal`, `Navbar`, `Navbar.Burger`,
|
|
163
|
-
`Navbar.
|
|
164
|
-
`
|
|
165
|
-
`Field
|
|
166
|
-
|
|
159
|
+
An existing `ref` is passed through untouched — which is safe only where the bestax target forwards
|
|
160
|
+
one. rbx forwards a ref on every component; bestax does so on the form controls, plus `Avatar`,
|
|
161
|
+
`Button`, `Carousel`, `CarouselItem`, `Dialog`, `Dropdown`, `EmptyState`, `Kbd`, `Kbd.Group`,
|
|
162
|
+
`Link`, `LinkButton`, `Loader`, `Menu.Item`, `Modal`, `Navbar`, `Navbar.Burger`, `Navbar.Dropdown`,
|
|
163
|
+
`Navbar.Item`, `Navbar.Link`, `SegmentedControl`, `SegmentedControl.Segment`, `Sidebar`, `Toast` and
|
|
164
|
+
`ToggleButton`. "The form controls" there means the inputs themselves: the `Field`, `Field.Label`,
|
|
165
|
+
`Field.Body`, `Checkboxes` and `Radios` wrappers around them forward nothing, and `Field` is a
|
|
166
|
+
target this codemod emits.
|
|
167
167
|
|
|
168
168
|
Carry a `ref` onto anything else — `Card`, `Box`, `Section`, `Message`, `Tabs` and most of the
|
|
169
169
|
catalogue — and it is unsupported, but the two React majors fail differently. React 18 drops
|
|
@@ -144,14 +144,14 @@ that lists the sizes that component takes: use one of them, or drop the prop.
|
|
|
144
144
|
|
|
145
145
|
## `domRef`
|
|
146
146
|
|
|
147
|
-
bestax components don't take `domRef`, but many forward a plain `ref` — the form controls,
|
|
148
|
-
|
|
149
|
-
`Link`, `LinkButton`, `Loader`, `Menu.Item`, `Modal`, `Navbar`, `Navbar.Burger`,
|
|
147
|
+
bestax components don't take `domRef`, but many forward a plain `ref` — the form controls, plus
|
|
148
|
+
`Avatar`, `Button`, `Carousel`, `CarouselItem`, `Dialog`, `Dropdown`, `EmptyState`, `Kbd`,
|
|
149
|
+
`Kbd.Group`, `Link`, `LinkButton`, `Loader`, `Menu.Item`, `Modal`, `Navbar`, `Navbar.Burger`,
|
|
150
150
|
`Navbar.Dropdown`, `Navbar.Item`, `Navbar.Link`, `SegmentedControl`, `SegmentedControl.Segment`,
|
|
151
151
|
`Sidebar`, `Toast` and `ToggleButton`. On those, rename `domRef` to `ref` and it works; do not
|
|
152
|
-
restructure the markup. "The form controls" means the inputs themselves: the `Field`,
|
|
153
|
-
`Field.
|
|
154
|
-
|
|
152
|
+
restructure the markup. "The form controls" means the inputs themselves: the `Field`, `Field.Label`,
|
|
153
|
+
`Field.Body`, `Checkboxes` and `Radios` wrappers around them forward nothing, and `Field` is a
|
|
154
|
+
target this codemod emits.
|
|
155
155
|
|
|
156
156
|
Everywhere else the rename is not enough, and the two React majors differ: React 18 drops the
|
|
157
157
|
ref and logs "Function components cannot be given refs", while React 19 passes it through as
|
|
@@ -74,7 +74,7 @@ is **more complete** than the docs page's Option C example, which omits several)
|
|
|
74
74
|
|
|
75
75
|
**Components** (`@allxsmith/bestax-bulma/scss/components/<name>`):
|
|
76
76
|
`loading`, `collapse`, `tooltip`, `popover`, `hovercard`, `contextmenu`, `steps`, `sidebar`,
|
|
77
|
-
`toast`, `dialog`, `carousel`, `tabs`, `reveal`, `avatar`, `avatars`, `badge`
|
|
77
|
+
`toast`, `dialog`, `carousel`, `tabs`, `reveal`, `avatar`, `avatars`, `badge`, `emptystate`
|
|
78
78
|
|
|
79
79
|
**Form** (`@allxsmith/bestax-bulma/scss/form/<name>`):
|
|
80
80
|
`checkbox`, `radio`, `switch`, `slider`, `numberinput`, `rate`, `autocomplete`, `taginput`,
|
|
@@ -311,6 +311,20 @@ The field around the two inputs. Its calendar is the `DateInput` one, with the v
|
|
|
311
311
|
`--bulma-dialog-radius`, `--bulma-dialog-shadow`, `--bulma-dialog-title-color`,
|
|
312
312
|
`--bulma-dialog-title-size`, `--bulma-dialog-title-weight`, `--bulma-dialog-width`
|
|
313
313
|
|
|
314
|
+
### EmptyState
|
|
315
|
+
|
|
316
|
+
Declared on the root, `.empty-state`. Each size class (`.is-small`, `.is-medium`, `.is-large`)
|
|
317
|
+
sets its own gap, padding, indicator and icon sizes, and title and description sizes, so retune a
|
|
318
|
+
size on that class. The color classes and `.is-filled` set the indicator's background and color
|
|
319
|
+
from Bulma's scheme tokens, so the circle follows dark mode with no override. The description is
|
|
320
|
+
`currentColor`, so it reads on whatever surface holds it.
|
|
321
|
+
|
|
322
|
+
`--bulma-empty-state-description-color`, `--bulma-empty-state-description-max-width`,
|
|
323
|
+
`--bulma-empty-state-description-size`, `--bulma-empty-state-gap`, `--bulma-empty-state-icon-size`,
|
|
324
|
+
`--bulma-empty-state-indicator-background`, `--bulma-empty-state-indicator-color`,
|
|
325
|
+
`--bulma-empty-state-indicator-radius`, `--bulma-empty-state-indicator-size`,
|
|
326
|
+
`--bulma-empty-state-padding`, `--bulma-empty-state-title-size`
|
|
327
|
+
|
|
314
328
|
### HoverCard
|
|
315
329
|
|
|
316
330
|
All are declared on the card, `.hover-card-content`, so a card rendered with `appendToBody` keeps
|
|
@@ -56,13 +56,14 @@ Shades (`colorShade` / `backgroundColorShade`): `00, 05, 10, … 95, invert, lig
|
|
|
56
56
|
| `Input` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | also `isRounded`, `isStatic` |
|
|
57
57
|
| `Avatar` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `16x16 \| 24x24 \| 32x32 \| 48x48 \| 64x64 \| 96x96 \| 128x128 \| number` | initials/icon background (auto-derived from `name` when unset); also `shape` |
|
|
58
58
|
| `Badge` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | — | pill background; default `danger` |
|
|
59
|
-
| `Title` | — (no `color`; use `textColor`) | `1`–`6` (string or number) | also `isSpaced`
|
|
60
|
-
| `SubTitle` | — (no `color`; use `textColor`) | `1`–`6` (string or number) |
|
|
59
|
+
| `Title` | — (no `color`; use `textColor`) | `1`–`6` (string or number) | also `isSpaced`; `size` also sets the heading level unless `as="p"`: pair `as` with `textSize` instead |
|
|
60
|
+
| `SubTitle` | — (no `color`; use `textColor`) | `1`–`6` (string or number) | `size` also sets the heading level unless `as="p"` (an `<h1>` with neither): pair `as` with `textSize` instead |
|
|
61
61
|
| `Autocomplete` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | the 6 only |
|
|
62
62
|
| `Checkbox` | `primary \| link \| info \| success \| warning \| danger` | `small \| normal \| medium \| large` | the 6 only |
|
|
63
63
|
| `DateInput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `isRounded` |
|
|
64
64
|
| `DateRangeInput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `isRounded`; `color` also fills the calendar range |
|
|
65
65
|
| `DateTimeInput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `isRounded` |
|
|
66
|
+
| `EmptyState` | `primary \| link \| info \| success \| warning \| danger` (the indicator circle and its icon only, never the text) | `small \| normal \| medium \| large` | also `variant`: `light` (default) \| `filled`; neutral with no `color`; tint text with `textColor`; `--bulma-empty-state-*` |
|
|
66
67
|
| `File` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | also `isBoxed`, `isFullwidth` |
|
|
67
68
|
| `Hero` | every `validColors` member + `inherit`/`current` (the `-bis`/`-ter` shades, the greys, `inherit` and `current` deprecated: no CSS, dev-warn, removed next major — see ⚠️) | `small \| medium \| large \| fullheight \| fullheight-with-navbar` | section background |
|
|
68
69
|
| `Kbd` | — (no `color`: the edge and fill are mixed from the text color, so `textColor` tints them; `bgColor` replaces the fill, so pair it with a `textColor`) | — (sized in `em` from the text around it; size it with `textSize`) | one keycap look, no `variant`; `Kbd.Group` takes `textColor` too; retheme through `--bulma-kbd-*` |
|
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": 19985
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
"id": "library-contributor",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
{
|
|
60
60
|
"id": "archetypes",
|
|
61
61
|
"file": "references/archetypes.md",
|
|
62
|
-
"bytes":
|
|
62
|
+
"bytes": 10240
|
|
63
63
|
},
|
|
64
64
|
{
|
|
65
65
|
"id": "layout-components",
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
{
|
|
94
94
|
"id": "bloomer-prop-map",
|
|
95
95
|
"file": "references/bloomer/prop-map.md",
|
|
96
|
-
"bytes":
|
|
96
|
+
"bytes": 24639
|
|
97
97
|
},
|
|
98
98
|
{
|
|
99
99
|
"id": "bloomer-unmappables",
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
{
|
|
129
129
|
"id": "rbx-prop-map",
|
|
130
130
|
"file": "references/rbx/prop-map.md",
|
|
131
|
-
"bytes":
|
|
131
|
+
"bytes": 12404
|
|
132
132
|
},
|
|
133
133
|
{
|
|
134
134
|
"id": "rbx-unmappables",
|
|
@@ -148,7 +148,7 @@
|
|
|
148
148
|
{
|
|
149
149
|
"id": "react-bulma-components-unmappables",
|
|
150
150
|
"file": "references/react-bulma-components/unmappables.md",
|
|
151
|
-
"bytes":
|
|
151
|
+
"bytes": 12266
|
|
152
152
|
}
|
|
153
153
|
],
|
|
154
154
|
"examples": []
|
|
@@ -162,7 +162,7 @@
|
|
|
162
162
|
{
|
|
163
163
|
"id": "modular-build",
|
|
164
164
|
"file": "references/modular-build.md",
|
|
165
|
-
"bytes":
|
|
165
|
+
"bytes": 10312
|
|
166
166
|
}
|
|
167
167
|
],
|
|
168
168
|
"examples": []
|
|
@@ -176,12 +176,12 @@
|
|
|
176
176
|
{
|
|
177
177
|
"id": "css-variables",
|
|
178
178
|
"file": "references/css-variables.md",
|
|
179
|
-
"bytes":
|
|
179
|
+
"bytes": 34455
|
|
180
180
|
},
|
|
181
181
|
{
|
|
182
182
|
"id": "themeable-components",
|
|
183
183
|
"file": "references/themeable-components.md",
|
|
184
|
-
"bytes":
|
|
184
|
+
"bytes": 23417
|
|
185
185
|
}
|
|
186
186
|
],
|
|
187
187
|
"examples": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bestax-mcp",
|
|
3
|
-
"version": "1.15.
|
|
3
|
+
"version": "1.15.3",
|
|
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.31.0",
|
|
44
44
|
"zod": "^4.4.3",
|
|
45
|
-
"@allxsmith/bestax-bulma": "^5.
|
|
45
|
+
"@allxsmith/bestax-bulma": "^5.34.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@jest/globals": "^30.0.0",
|