create-bestax 4.2.15 → 4.2.17
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/dist/constants.js +2 -2
- package/package.json +6 -6
- package/templates/skills/bestax-custom-component/SKILL.md +36 -1
- package/templates/skills/bestax-custom-component/references/api.md +36 -14
- package/templates/skills/bestax-custom-component/references/component-catalog.md +8 -2
- package/templates/skills/bestax-custom-component/references/library-contributor.md +4 -1
- package/templates/skills/bestax-form/SKILL.md +42 -29
- package/templates/skills/bestax-form/references/api.md +12 -10
- package/templates/skills/bestax-form/references/patterns.md +17 -5
- package/templates/skills/bestax-icons/SKILL.md +8 -1
- package/templates/skills/bestax-icons/references/icon-libraries.md +35 -2
- package/templates/skills/bestax-layout-scaffold/SKILL.md +34 -1
- package/templates/skills/bestax-layout-scaffold/references/archetypes.md +57 -0
- package/templates/skills/bestax-migrate/references/bloomer/prop-map.md +34 -8
- package/templates/skills/bestax-migrate/references/bloomer/unmappables.md +18 -0
- package/templates/skills/bestax-migrate/references/rbx/prop-map.md +31 -7
- package/templates/skills/bestax-migrate/references/rbx/unmappables.md +41 -14
- package/templates/skills/bestax-migrate/references/react-bulma-components/component-map.md +3 -3
- package/templates/skills/bestax-migrate/references/react-bulma-components/prop-map.md +22 -0
- package/templates/skills/bestax-migrate/references/react-bulma-components/unmappables.md +33 -8
- package/templates/skills/bestax-optimize/SKILL.md +2 -0
- package/templates/skills/bestax-optimize/references/modular-build.md +19 -10
- package/templates/skills/bestax-theming/SKILL.md +4 -1
- package/templates/skills/bestax-theming/references/css-variables.md +87 -2
- package/templates/skills/bestax-theming/references/themeable-components.md +6 -2
- package/templates/vite-ts/package.json +1 -0
- package/templates/vite-ts/tsconfig.app.json +10 -9
- package/templates/vite-ts/tsconfig.node.json +15 -5
- package/templates/vite-ts/src/vite-env.d.ts +0 -1
|
@@ -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
|
|
@@ -54,8 +54,8 @@ leftover would be a type error rather than a no-op.
|
|
|
54
54
|
| ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
55
55
|
| `isColor="primary"` | `color="primary"` (every component that had it) |
|
|
56
56
|
| `isSize="large"` | `size="large"` — Button, Content, Delete, Icon, Input, Progress, Section, Select, Tag, TextArea, Breadcrumb, Pagination, Tabs, Field.Label, Modal.Close |
|
|
57
|
-
| `Title isSize={3}` | `
|
|
58
|
-
| `Subtitle isSize={4}` | `SubTitle
|
|
57
|
+
| `Title isSize={3}` | `textSize="3"`, so the `<h1>` stays an `<h1>` (see [Title and Subtitle sizes](#title-and-subtitle-sizes)) |
|
|
58
|
+
| `Subtitle isSize={4}` | `SubTitle textSize="4" as="h2"`: bloomer's default was an `<h2>`, bestax's is an `<h1>`, so the level is written out |
|
|
59
59
|
| `Image isSize="128x128"` | `size="128x128"` |
|
|
60
60
|
| `Image isRatio="16:9"` | `size="16by9"` (`square`→`square`, `1:1`→`1by1`, `4:3`→`4by3`, `3:2`→`3by2`, `2:1`→`2by1`) |
|
|
61
61
|
| `Breadcrumb isAlign` | `alignment` |
|
|
@@ -77,6 +77,31 @@ leftover would be a type error rather than a no-op.
|
|
|
77
77
|
| `isActive` on Dropdown, DropdownItem, MenuLink, Modal, NavbarBurger, NavbarMenu, NavbarItem, PanelBlock, Tab | `active` |
|
|
78
78
|
| `Input`, `Select`, `TextArea` | `InputBase`, `SelectBase`, `TextAreaBase` — bloomer's were bare elements; bestax's `Input`/`Select`/`TextArea` wrap themselves in `Field` and `Control`, so the bare `*Base` exports are the faithful targets and your existing `Field`/`Control` markup stays as written |
|
|
79
79
|
|
|
80
|
+
## Title and Subtitle sizes
|
|
81
|
+
|
|
82
|
+
bloomer's `Title` rendered an `<h1>` and its `Subtitle` an `<h2>` whatever `isSize` said, or
|
|
83
|
+
the element `tag` named. bestax's `Title` and `SubTitle` render the heading their `size` names
|
|
84
|
+
unless `as="p"`, so `<SubTitle size={4} as="h2">` is an `<h4>`. The codemod keeps the element
|
|
85
|
+
bloomer rendered:
|
|
86
|
+
|
|
87
|
+
| bloomer | bestax-bulma | renders |
|
|
88
|
+
| ----------------------------- | --------------------------------- | ------- |
|
|
89
|
+
| `<Title isSize={4}>` | `<Title textSize="4">` | `<h1>` |
|
|
90
|
+
| `<Title isSize={1}>` | `<Title size={1}>` | `<h1>` |
|
|
91
|
+
| `<Title isSize={4} tag="h2">` | `<Title textSize="4" as="h2">` | `<h2>` |
|
|
92
|
+
| `<Title isSize={6} tag="p">` | `<Title size={6} as="p">` | `<p>` |
|
|
93
|
+
| `<Subtitle>` | `<SubTitle as="h2">` | `<h2>` |
|
|
94
|
+
| `<Subtitle isSize={2}>` | `<SubTitle size={2}>` | `<h2>` |
|
|
95
|
+
| `<Subtitle isSize={4}>` | `<SubTitle textSize="4" as="h2">` | `<h2>` |
|
|
96
|
+
|
|
97
|
+
`size` stays only where it renders the same element: a `<p>`, or the heading the size names.
|
|
98
|
+
Everywhere else the size moves to the `textSize` helper, and so does a 7, which bestax's `size`
|
|
99
|
+
does not take. The helper sets the same font size through Bulma's `is-size-4` class rather than the
|
|
100
|
+
title's own `is-4`, so a rule of your own that targets `.title.is-4` needs the new class too.
|
|
101
|
+
`is-size-4` is also `!important`, so a font size your own CSS gives the title, such as
|
|
102
|
+
`.hero .title`, now loses to it where it used to beat `is-4`. A literal outside 1 to 7 keeps `size`
|
|
103
|
+
and gets a `prop:isSize` TODO.
|
|
104
|
+
|
|
80
105
|
## Column sizes
|
|
81
106
|
|
|
82
107
|
| bloomer | bestax-bulma |
|
|
@@ -161,12 +186,13 @@ value is flagged. The same conversion covers the modifiers bestax has no prop fo
|
|
|
161
186
|
|
|
162
187
|
## Refs
|
|
163
188
|
|
|
164
|
-
bloomer forwarded no refs. bestax forwards a ref from the form controls, plus `Avatar`,
|
|
165
|
-
`
|
|
166
|
-
`Menu.Item`, `Modal`, `Navbar`, `Navbar.Burger`, `Navbar.Dropdown`,
|
|
167
|
-
`Navbar.Link`, `
|
|
168
|
-
|
|
169
|
-
wrappers around them forward
|
|
189
|
+
bloomer forwarded no refs. bestax forwards a ref from the form controls, plus `Avatar`, `Button`,
|
|
190
|
+
`Carousel`, `CarouselItem`, `Dialog`, `Dropdown`, `EmptyState`, `Kbd`, `Kbd.Group`, `Link`,
|
|
191
|
+
`LinkButton`, `Loader`, `Menu.Item`, `Modal`, `Navbar`, `Navbar.Burger`, `Navbar.Dropdown`,
|
|
192
|
+
`Navbar.Item`, `Navbar.Link`, `SegmentedControl`, `SegmentedControl.Segment`, `Sidebar`, `Toast` and
|
|
193
|
+
`ToggleButton` — pass `ref` directly on those. "The form controls" means the inputs themselves: the
|
|
194
|
+
`Field`, `Field.Label`, `Field.Body`, `Checkboxes` and `Radios` wrappers around them forward
|
|
195
|
+
nothing.
|
|
170
196
|
|
|
171
197
|
A `ref` on anything else is unsupported, and the two React majors fail differently: React 18
|
|
172
198
|
drops it and logs "Function components cannot be given refs", while React 19 hands it to the
|
|
@@ -274,6 +274,24 @@ prop conditionally:
|
|
|
274
274
|
counterpart in bestax (only `isNarrowTouch`) — Bulma keeps the `is-*-touch` classes, so use
|
|
275
275
|
`className`.
|
|
276
276
|
|
|
277
|
+
## `prop:isSize` on `Title` and `Subtitle`: a size the codemod cannot carry
|
|
278
|
+
|
|
279
|
+
bloomer's `Title` and `Subtitle` kept their element at every size. bestax's render the heading
|
|
280
|
+
their `size` names, so a literal `isSize` moves to `textSize` to keep the level (see "Title and
|
|
281
|
+
Subtitle sizes" in the prop map). A dynamic one cannot move, because `textSize` takes a string,
|
|
282
|
+
so it becomes `size`. Pass it to `textSize` yourself:
|
|
283
|
+
|
|
284
|
+
```jsx
|
|
285
|
+
<Subtitle isSize={compact ? 5 : 4}>Report</Subtitle>
|
|
286
|
+
<SubTitle textSize={compact ? '5' : '4'} as="h2">Report</SubTitle>
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
A literal outside 1 to 7 has no Bulma class, and bestax renders none for it either: drop it, or set
|
|
290
|
+
a `textSize` from `'1'` to `'7'`.
|
|
291
|
+
|
|
292
|
+
A dynamic size beside `tag="p"` is not flagged, since bestax never turns a `<p>` into a
|
|
293
|
+
heading.
|
|
294
|
+
|
|
277
295
|
## `value-reference` — a component used as a value
|
|
278
296
|
|
|
279
297
|
`const Wrapped = Box` and `{ Subtitle }` are rewritten to the bestax binding (`Hero.Foot`,
|
|
@@ -118,6 +118,29 @@ wrong:
|
|
|
118
118
|
Note that this one does change the rendered element: rbx's `forwardRefAs` rendered the tag you
|
|
119
119
|
gave it, so that really was a `<span>`, and the TODO exists to tell you the element moved.
|
|
120
120
|
|
|
121
|
+
## Title sizes
|
|
122
|
+
|
|
123
|
+
rbx's `Title` rendered an `<h1>` at every size, subtitle or not, or the element `as` named.
|
|
124
|
+
bestax's `Title` and `SubTitle` render the heading their `size` names unless `as="p"`, so the
|
|
125
|
+
codemod keeps the element rbx rendered:
|
|
126
|
+
|
|
127
|
+
| rbx | bestax-bulma | renders |
|
|
128
|
+
| ---------------------------------- | ------------------------------ | ------- |
|
|
129
|
+
| `<Title size={4}>` | `<Title textSize="4">` | `<h1>` |
|
|
130
|
+
| `<Title size={1}>` | `<Title size={1}>` | `<h1>` |
|
|
131
|
+
| `<Title subtitle size={6}>` | `<SubTitle textSize="6">` | `<h1>` |
|
|
132
|
+
| `<Title as="h2" size={5}>` | `<Title as="h2" textSize="5">` | `<h2>` |
|
|
133
|
+
| `<Title as="p" subtitle size={5}>` | `<SubTitle as="p" size={5}>` | `<p>` |
|
|
134
|
+
|
|
135
|
+
`size` stays only where it renders the same element: a `<p>`, or the heading the size names.
|
|
136
|
+
Everywhere else the size moves to the `textSize` helper, and so does a 7, which bestax's `size`
|
|
137
|
+
does not take. The helper sets the same font size through Bulma's `is-size-4` class rather than the
|
|
138
|
+
title's own `is-4`, so a rule of your own that targets `.title.is-4` needs the new class too.
|
|
139
|
+
`is-size-4` is also `!important`, so a font size your own CSS gives the title, such as
|
|
140
|
+
`.hero .title`, now loses to it where it used to beat `is-4`. Beside a spread, which may carry
|
|
141
|
+
`as`, a size moves even where it names the default `<h1>`. A literal outside 1 to 7 keeps `size`
|
|
142
|
+
and gets a `prop:size` TODO.
|
|
143
|
+
|
|
121
144
|
## `href` follows `as`
|
|
122
145
|
|
|
123
146
|
bestax gives an element the attributes of the tag `as` names, so `href` exists only where that
|
|
@@ -156,13 +179,14 @@ becomes.
|
|
|
156
179
|
Beside a `ref` the element already has, a rename leaves `innerRef` in place with a `prop:innerRef`
|
|
157
180
|
TODO rather than write a second `ref`; keep whichever one you meant.
|
|
158
181
|
|
|
159
|
-
An existing `ref` is passed through untouched — which is safe only where the bestax target
|
|
160
|
-
|
|
161
|
-
`
|
|
162
|
-
`Loader`, `Menu.Item`, `Modal`, `Navbar`, `Navbar.Burger`, `Navbar.Dropdown`,
|
|
163
|
-
`Navbar.Link`, `
|
|
164
|
-
the `Field`, `Field.Label`,
|
|
165
|
-
forward nothing, and `Field` is a
|
|
182
|
+
An existing `ref` is passed through untouched — which is safe only where the bestax target forwards
|
|
183
|
+
one. rbx forwards a ref on every component; bestax does so on the form controls, plus `Avatar`,
|
|
184
|
+
`Button`, `Carousel`, `CarouselItem`, `Dialog`, `Dropdown`, `EmptyState`, `Kbd`, `Kbd.Group`,
|
|
185
|
+
`Link`, `LinkButton`, `Loader`, `Menu.Item`, `Modal`, `Navbar`, `Navbar.Burger`, `Navbar.Dropdown`,
|
|
186
|
+
`Navbar.Item`, `Navbar.Link`, `SegmentedControl`, `SegmentedControl.Segment`, `Sidebar`, `Toast` and
|
|
187
|
+
`ToggleButton`. "The form controls" there means the inputs themselves: the `Field`, `Field.Label`,
|
|
188
|
+
`Field.Body`, `Checkboxes` and `Radios` wrappers around them forward nothing, and `Field` is a
|
|
189
|
+
target this codemod emits.
|
|
166
190
|
|
|
167
191
|
Carry a `ref` onto anything else — `Card`, `Box`, `Section`, `Message`, `Tabs` and most of the
|
|
168
192
|
catalogue — and it is unsupported, but the two React majors fail differently. React 18 drops
|
|
@@ -171,22 +171,49 @@ converted — bestax has its own unrelated `responsive` prop (`'mobile' | 'narro
|
|
|
171
171
|
half-emptied rbx object behind would be a type error rather than a leftover. The TODO names
|
|
172
172
|
which breakpoints did not carry.
|
|
173
173
|
|
|
174
|
+
## A size bestax doesn't take (`prop:size`)
|
|
175
|
+
|
|
176
|
+
`Button.Group`, `Tag.Group` and `Message` sizes carry over as written when bestax's `Buttons`,
|
|
177
|
+
`Tags` or `Message` takes the value. Any other value, or one the codemod can't read, stays as
|
|
178
|
+
written with a TODO that lists the sizes that component takes: use one of them, or drop the
|
|
179
|
+
prop.
|
|
180
|
+
|
|
181
|
+
A dynamic `Image.Container` size gets the same rule, since the codemod can't turn it into
|
|
182
|
+
bestax's `NxN` form. Set `size` on the migrated `<Image>` by hand.
|
|
183
|
+
|
|
184
|
+
## `prop:size` on `Title`: a size the codemod cannot carry
|
|
185
|
+
|
|
186
|
+
rbx's `Title` rendered an `<h1>` at every size, subtitle or not. bestax's `Title` and `SubTitle`
|
|
187
|
+
render the heading their `size` names unless `as="p"`, so a literal size moves to `textSize` to
|
|
188
|
+
keep the level (see "Title sizes" in the prop map). A dynamic one cannot move, because
|
|
189
|
+
`textSize` takes a string, so it stays `size`. Pass it to `textSize` yourself:
|
|
190
|
+
|
|
191
|
+
```jsx
|
|
192
|
+
<Title size={compact ? 5 : 4}>Report</Title>
|
|
193
|
+
<Title textSize={compact ? '5' : '4'}>Report</Title>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
A literal outside 1 to 7 has no Bulma class, and bestax renders none for it either: drop it, or set
|
|
197
|
+
a `textSize` from `'1'` to `'7'`.
|
|
198
|
+
|
|
199
|
+
The same TODO marks a `Title` that sets `size` and `textSize` both: drop `size` and let
|
|
200
|
+
`textSize` set the font size.
|
|
201
|
+
|
|
174
202
|
## Props with no counterpart
|
|
175
203
|
|
|
176
|
-
| TODO
|
|
177
|
-
|
|
|
178
|
-
| `prop:closeOnBlur` on `Modal`
|
|
179
|
-
| `prop:selected`, `prop:text` on `Button`
|
|
180
|
-
| `prop:
|
|
181
|
-
| `prop:
|
|
182
|
-
| `
|
|
183
|
-
| `
|
|
184
|
-
| `prop:
|
|
185
|
-
| `prop:
|
|
186
|
-
| `prop:document` on `
|
|
187
|
-
| `
|
|
188
|
-
| `
|
|
189
|
-
| `tooltipResponsive` | bestax's `Tooltip` has one `position` for all viewports |
|
|
204
|
+
| TODO | What to do |
|
|
205
|
+
| -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
206
|
+
| `prop:closeOnBlur` on `Modal` | the migrated compound form renders `Modal.Background` as you wrote it; wire its `onClick` to your `onClose` |
|
|
207
|
+
| `prop:selected`, `prop:text` on `Button` | `className="is-selected"`; for `is-text` use `color="ghost"` or a link |
|
|
208
|
+
| `prop:gradient` on `Hero` | Bulma v1 removed `is-bold` gradients; use `bgColor` or a custom class |
|
|
209
|
+
| `prop:color`, `prop:vertical` on `Divider` | bestax's `Divider` takes only `bgColor` and renders an `<hr>` |
|
|
210
|
+
| `component:Divider` (a labelled divider) | rbx rendered `<Divider>OR</Divider>`'s children as a centred label via `data-content`; bestax's `Divider` is a bare `<hr>` and takes no children -- React rejects children on a void element at runtime. Put the label in surrounding markup, or drop it |
|
|
211
|
+
| `prop:direction` on `PageLoader` | no directional variant; drop it or add a class |
|
|
212
|
+
| `prop:managed` | bestax components are uncontrolled; drive the `Modal` with `active` and `onClose` |
|
|
213
|
+
| `prop:document` on `Modal` | bestax portals via `portal`, but it takes `true`, a selector or an element rather than a `Document` — see [Modal: what carries over](#modal-what-carries-over) |
|
|
214
|
+
| `prop:document` on `Navbar` | bestax's `Navbar` has no `document` prop; drop it |
|
|
215
|
+
| `badgeOutlined`, `badgeRounded`, `badgeSize` | bestax's `Badge` has no outline, pill or size variant |
|
|
216
|
+
| `tooltipResponsive` | bestax's `Tooltip` has one `position` for all viewports |
|
|
190
217
|
|
|
191
218
|
## Modal: what carries over
|
|
192
219
|
|
|
@@ -20,7 +20,7 @@ codemod converts it; **Flagged** = it leaves a `TODO(bestax-migrate)` comment (s
|
|
|
20
20
|
| `Element` | — | Flagged: no generic element; use a semantic component + helper props |
|
|
21
21
|
| `Footer` | `Footer` | Auto |
|
|
22
22
|
| `Form.*` | flat imports | See Form table below |
|
|
23
|
-
| `Heading` | `Title` / `SubTitle` / `<p class="heading">` | Auto for literal `subtitle`/`heading` (by value, not presence — `subtitle={false}` is `Title`); dynamic value flagged
|
|
23
|
+
| `Heading` | `Title` / `SubTitle` / `<p class="heading">` | Auto for literal `subtitle`/`heading` (by value, not presence — `subtitle={false}` is `Title`); dynamic value flagged; `size` may become `textSize` |
|
|
24
24
|
| `Hero` | `Hero` | Auto; `hasNavbar`→`fullheightWithNavbar`; `halfheight`/`gradient` flagged |
|
|
25
25
|
| `Icon` | `Icon` | `<i class="fas fa-x">` children → `name`/`library`/`variant` props; else flagged |
|
|
26
26
|
| `Image` | `Image` | Auto; numeric `size={128}` → `size="128x128"`, `rounded`→`isRounded` |
|
|
@@ -28,7 +28,7 @@ codemod converts it; **Flagged** = it leaves a `TODO(bestax-migrate)` comment (s
|
|
|
28
28
|
| `Loader` | plain `<div className="loader">` | Auto (Bulma v1 still ships the class); swap in bestax's `Loader` by hand for its progressbar role and accessible name |
|
|
29
29
|
| `Media` | `Media` | Auto |
|
|
30
30
|
| `Menu` | `Menu` | Auto |
|
|
31
|
-
| `Message` | `Message` | Auto; `size` flagged
|
|
31
|
+
| `Message` | `Message` | Auto; unknown or dynamic `size` flagged |
|
|
32
32
|
| `Modal` | `Modal` | `show`→`active`, `closeOnEsc`→`closeOnEscape`; `closeOnBlur`/`showClose` flagged (compound form renders neither) |
|
|
33
33
|
| `Navbar` | `Navbar` | Auto; see dropdown note below |
|
|
34
34
|
| `Notification` | `Notification` | Auto; `light`→`isLight` |
|
|
@@ -46,7 +46,7 @@ codemod converts it; **Flagged** = it leaves a `TODO(bestax-migrate)` comment (s
|
|
|
46
46
|
| RBC | bestax |
|
|
47
47
|
| ----------------------------------------------------------- | ------------------------------------------------------------------------ |
|
|
48
48
|
| `Breadcrumb.Item` | plain `<li><a href=…>` (`active` → `is-active`) |
|
|
49
|
-
| `Button.Group` | `Buttons` (`align="right"`→`isRight`)
|
|
49
|
+
| `Button.Group` | `Buttons` (`align="right"`→`isRight`); unknown or dynamic `size` flagged |
|
|
50
50
|
| `Card.Header` / `.Title` / `.Icon` | `Card.Header` / `.Header.Title` / `.Header.Icon` |
|
|
51
51
|
| `Card.Image` | `Card.Image` wrapping an inner `<Image>` |
|
|
52
52
|
| `Card.Content` | `Card.Content` |
|
|
@@ -46,6 +46,28 @@ href="/x">`) keeps the element and drops the `href`, with a `prop:href` TODO. RB
|
|
|
46
46
|
`<Button href="/x">` with no `renderAs` goes the same way: bestax's `Button` renders a
|
|
47
47
|
`<button>`. Set `as="a"` to make it a link.
|
|
48
48
|
|
|
49
|
+
## `Heading` sizes
|
|
50
|
+
|
|
51
|
+
RBC's `Heading` rendered an `<h1>` at every size, subtitle or not, or the element `renderAs`
|
|
52
|
+
named. bestax's `Title` and `SubTitle` render the heading their `size` names unless `as="p"`, so
|
|
53
|
+
the codemod keeps the element RBC rendered:
|
|
54
|
+
|
|
55
|
+
| RBC | bestax-bulma | renders |
|
|
56
|
+
| ------------------------------------------ | ------------------------------ | ------- |
|
|
57
|
+
| `<Heading size={4}>` | `<Title textSize="4">` | `<h1>` |
|
|
58
|
+
| `<Heading size={1}>` | `<Title size="1">` | `<h1>` |
|
|
59
|
+
| `<Heading subtitle size={6}>` | `<SubTitle textSize="6">` | `<h1>` |
|
|
60
|
+
| `<Heading renderAs="h2" size={5}>` | `<Title as="h2" textSize="5">` | `<h2>` |
|
|
61
|
+
| `<Heading renderAs="p" subtitle size={5}>` | `<SubTitle as="p" size="5">` | `<p>` |
|
|
62
|
+
|
|
63
|
+
`size` stays only where it renders the same element: a `<p>`, or the heading the size names.
|
|
64
|
+
Everywhere else the size moves to the `textSize` helper, and so does a 7, which bestax's `size`
|
|
65
|
+
does not take. The helper sets the same font size through Bulma's `is-size-4` class rather than the
|
|
66
|
+
title's own `is-4`, so a rule of your own that targets `.title.is-4` needs the new class too.
|
|
67
|
+
`is-size-4` is also `!important`, so a font size your own CSS gives the title, such as
|
|
68
|
+
`.hero .title`, now loses to it where it used to beat `is-4`. A literal outside 1 to 7 keeps `size`
|
|
69
|
+
and gets a `prop:size` TODO.
|
|
70
|
+
|
|
49
71
|
## Boolean modifier convention
|
|
50
72
|
|
|
51
73
|
RBC uses bare booleans (`loading`, `outlined`, `rounded`, `fullwidth`); bestax prefixes
|
|
@@ -129,22 +129,47 @@ bestax `Button` colors are the semantic set + `text`/`ghost`. For shades use
|
|
|
129
129
|
`bgColor`/`textColor` (they accept the full palette incl. shades), and replace
|
|
130
130
|
`isSelected` with `className="is-selected"` inside grouped buttons.
|
|
131
131
|
|
|
132
|
-
## `colorVariant` / Hero `gradient` / Hero `halfheight`
|
|
132
|
+
## `colorVariant` / Hero `gradient` / Hero `halfheight` (`prop:size`)
|
|
133
133
|
|
|
134
134
|
- `colorVariant="light"` → `isLight` where supported (Button, Notification), otherwise a
|
|
135
135
|
shade: `bgColor="primary-90"`.
|
|
136
136
|
- Bulma v1 removed `is-bold` hero gradients — delete `gradient` or restyle with CSS.
|
|
137
137
|
- `halfheight` has no bestax size; use `size="medium"` or a CSS height.
|
|
138
138
|
|
|
139
|
+
## A size bestax doesn't take (`prop:size` on `Button.Group` and `Message`)
|
|
140
|
+
|
|
141
|
+
`Button.Group` and `Message` sizes carry over as written when bestax's `Buttons` or `Message`
|
|
142
|
+
takes the value. Any other value, or one the codemod can't read, stays as written with a TODO
|
|
143
|
+
that lists the sizes that component takes: use one of them, or drop the prop.
|
|
144
|
+
|
|
145
|
+
## `prop:size` on `Heading`: a size the codemod cannot carry
|
|
146
|
+
|
|
147
|
+
RBC's `Heading` rendered an `<h1>` at every size, subtitle or not. bestax's `Title` and
|
|
148
|
+
`SubTitle` render the heading their `size` names unless `as="p"`, so a literal size moves to
|
|
149
|
+
`textSize` to keep the level (see "`Heading` sizes" in the prop map). A dynamic one cannot move,
|
|
150
|
+
because `textSize` takes a string, so it stays `size`. Pass it to `textSize` yourself:
|
|
151
|
+
|
|
152
|
+
```jsx
|
|
153
|
+
<Heading size={compact ? 5 : 4}>Report</Heading>
|
|
154
|
+
<Title textSize={compact ? '5' : '4'}>Report</Title>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
A literal outside 1 to 7 has no Bulma class, and bestax renders none for it either: drop it, or set
|
|
158
|
+
a `textSize` from `'1'` to `'7'`.
|
|
159
|
+
|
|
160
|
+
The same TODO marks a `Heading` that sets `size` and `textSize` both: drop `size` and let
|
|
161
|
+
`textSize` set the font size.
|
|
162
|
+
|
|
139
163
|
## `domRef`
|
|
140
164
|
|
|
141
|
-
bestax components don't take `domRef`, but many forward a plain `ref` — the form controls,
|
|
142
|
-
|
|
143
|
-
`LinkButton`, `Loader`, `Menu.Item`, `Modal`, `Navbar`, `Navbar.Burger`,
|
|
144
|
-
`Navbar.Item`, `Navbar.Link`, `
|
|
145
|
-
`
|
|
146
|
-
themselves: the `Field`, `Field.Label`,
|
|
147
|
-
around them forward nothing, and `Field` is a
|
|
165
|
+
bestax components don't take `domRef`, but many forward a plain `ref` — the form controls, plus
|
|
166
|
+
`Avatar`, `Button`, `Carousel`, `CarouselItem`, `Dialog`, `Dropdown`, `EmptyState`, `Kbd`,
|
|
167
|
+
`Kbd.Group`, `Link`, `LinkButton`, `Loader`, `Menu.Item`, `Modal`, `Navbar`, `Navbar.Burger`,
|
|
168
|
+
`Navbar.Dropdown`, `Navbar.Item`, `Navbar.Link`, `SegmentedControl`, `SegmentedControl.Segment`,
|
|
169
|
+
`Sidebar`, `Toast` and `ToggleButton`. On those, rename `domRef` to `ref` and it works; do not
|
|
170
|
+
restructure the markup. "The form controls" means the inputs themselves: the `Field`, `Field.Label`,
|
|
171
|
+
`Field.Body`, `Checkboxes` and `Radios` wrappers around them forward nothing, and `Field` is a
|
|
172
|
+
target this codemod emits.
|
|
148
173
|
|
|
149
174
|
Everywhere else the rename is not enough, and the two React majors differ: React 18 drops the
|
|
150
175
|
ref and logs "Function components cannot be given refs", while React 19 passes it through as
|
|
@@ -126,6 +126,8 @@ partial inventory, and a worked example are in `references/modular-build.md`.
|
|
|
126
126
|
`material-icons`, `material-symbols`) with their CSS imports in `src/main.*`, or Ionicons
|
|
127
127
|
CDN `<script>` tags in `index.html`. Icon fonts often outweigh Bulma itself — if no
|
|
128
128
|
`<Icon>` uses that library, delete the dependency/import/script. Pure win, no tooling.
|
|
129
|
+
When the app does render Material Symbols, its font can be made smaller instead of
|
|
130
|
+
removed: see [Making the font smaller](https://bestax.io/docs/guides/getting-started/alternative-icons#making-the-font-smaller).
|
|
129
131
|
|
|
130
132
|
## References
|
|
131
133
|
|
|
@@ -73,15 +73,15 @@ Every extras partial that exists (from the library's `src/scss/**/_index.scss`
|
|
|
73
73
|
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
|
-
`loading`, `collapse`, `tooltip`, `popover`, `
|
|
77
|
-
`tabs`, `reveal`, `avatar`, `avatars`, `badge`
|
|
76
|
+
`loading`, `collapse`, `tooltip`, `popover`, `hovercard`, `contextmenu`, `steps`, `sidebar`,
|
|
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`,
|
|
81
81
|
`picker-popover`, `dateinput`, `timeinput`, `datetimeinput`, `daterangeinput`
|
|
82
82
|
|
|
83
|
-
**Elements** (`@allxsmith/bestax-bulma/scss/elements/<name>`): `linkbutton`, `loader`,
|
|
84
|
-
`progress`, `skeleton`
|
|
83
|
+
**Elements** (`@allxsmith/bestax-bulma/scss/elements/<name>`): `kbd`, `linkbutton`, `loader`,
|
|
84
|
+
`notification`, `progress`, `skeleton`
|
|
85
85
|
|
|
86
86
|
**Helpers** (`@allxsmith/bestax-bulma/scss/helpers/<name>`): `cursor`, `sizing`
|
|
87
87
|
|
|
@@ -96,6 +96,8 @@ Notes:
|
|
|
96
96
|
`picker-popover` too.
|
|
97
97
|
- `Popover.Close` renders a Bulma button, so an app using it needs `bulma/sass/elements/button`
|
|
98
98
|
next to `scss/components/popover`.
|
|
99
|
+
- `ContextMenu`'s menu is Bulma's dropdown markup, so an app using it needs
|
|
100
|
+
`bulma/sass/components/dropdown` next to `scss/components/contextmenu`.
|
|
99
101
|
- `Loader` is stock Bulma styled by `bulma/sass/elements/loader`, and the `isLoading`
|
|
100
102
|
spinners on `Button`, `Control` and `Select` are Bulma's too. The `loader` extras partial
|
|
101
103
|
stops all of them under `prefers-reduced-motion: reduce`, so include it next to the Bulma
|
|
@@ -105,6 +107,10 @@ Notes:
|
|
|
105
107
|
`bulma/sass/base/skeleton`). The `progress` and `skeleton` extras partials stop the
|
|
106
108
|
indeterminate bar's sweep and the skeleton pulse (`Skeleton`, the `skeleton` prop,
|
|
107
109
|
`hasSkeleton`) under `prefers-reduced-motion: reduce`, the same way and in either order.
|
|
110
|
+
- `Notification` is stock Bulma too (`bulma/sass/elements/notification`). The `notification`
|
|
111
|
+
extras partial pads the end of one with a close button (`hasDelete`, or a `Delete` passed in)
|
|
112
|
+
so its text clears the button, so include it next to the Bulma module in any build that shows
|
|
113
|
+
a dismissible notification. It doesn't depend on the order of the two `@use` lines either.
|
|
108
114
|
- Stock-Bulma form controls still need their Bulma module (`bulma/sass/form/…`); the extras
|
|
109
115
|
form partials above style only the bestax-specific behavior.
|
|
110
116
|
- Bulma component modules pull their own internal sub-elements — e.g.
|
|
@@ -154,12 +160,13 @@ not `flexbox` — `flexbox` holds only the alignment props. Verified failure mod
|
|
|
154
160
|
|
|
155
161
|
The `npm create bestax` starter renders `Container`, `Section`, `Columns`/`Column`, `Image`,
|
|
156
162
|
`Title`/`SubTitle`, `Box`, `Card`, `Buttons`/`Button`, and `Notification` with its close
|
|
157
|
-
button: all stock Bulma,
|
|
158
|
-
`flexGrow` (flexbox), and `textAlign` (typography);
|
|
159
|
-
inventory compiles to the following, verified
|
|
160
|
-
flavor in headless Chromium (light and dark, phone
|
|
161
|
-
274 KB raw / 30 KB gzip vs 819 KB / 84 KB.
|
|
162
|
-
needs `bulma/sass/elements/icon` for its
|
|
163
|
+
button: all stock Bulma, plus the `notification` extras partial for that close button. Its
|
|
164
|
+
helper props are `display` (visibility), `flexGrow` (flexbox), and `textAlign` (typography);
|
|
165
|
+
it uses no spacing or color props. That inventory compiles to the following, verified
|
|
166
|
+
pixel-equivalent to the prebuilt `complete` flavor in headless Chromium (light and dark, phone
|
|
167
|
+
and desktop width, notification open), at 274 KB raw / 30 KB gzip vs 819 KB / 84 KB.
|
|
168
|
+
Scaffolded with an icon library, the starter also needs `bulma/sass/elements/icon` for its
|
|
169
|
+
`IconText` card titles:
|
|
163
170
|
|
|
164
171
|
```scss
|
|
165
172
|
// src/styles.scss
|
|
@@ -184,6 +191,8 @@ needs `bulma/sass/elements/icon` for its `IconText` card titles:
|
|
|
184
191
|
@use 'bulma/sass/helpers/visibility'; // display="flex"
|
|
185
192
|
@use 'bulma/sass/helpers/flexbox'; // flexGrow
|
|
186
193
|
@use 'bulma/sass/helpers/typography'; // textAlign
|
|
194
|
+
|
|
195
|
+
@use '@allxsmith/bestax-bulma/scss/elements/notification'; // text clears the close button
|
|
187
196
|
```
|
|
188
197
|
|
|
189
198
|
```tsx
|
|
@@ -20,7 +20,10 @@ Choose an override path:
|
|
|
20
20
|
- **`Theme` component (runtime, preferred).** Exported from the package. Pass named HSL props
|
|
21
21
|
(`primaryH`, `primaryS`, `primaryL`, …) and/or `bulmaVars={{ '--bulma-*': '…' }}` for everything
|
|
22
22
|
else. Add `isRoot` to inject the variables globally at `:root` (once, at the app root); omit it to
|
|
23
|
-
scope the variables to the wrapped subtree.
|
|
23
|
+
scope the variables to the wrapped subtree. A `Theme` only reaches variables the component
|
|
24
|
+
inherits: Bulma declares component variables such as `--bulma-card-radius` on the component's
|
|
25
|
+
own element, so a `Theme` value for one never applies (it warns in development). Set those on
|
|
26
|
+
the component with `className` or `style` instead (see `references/css-variables.md`).
|
|
24
27
|
- **Plain CSS.** Set `:root { --bulma-primary-h: …; }` (or any selector) directly.
|
|
25
28
|
- **Build-time Sass.** `@use 'bulma/sass' with ($primary: #1e6b99)` when compiling Bulma's Sass.
|
|
26
29
|
|