create-bestax 4.2.11 → 4.2.13
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/README.md +11 -2
- package/dist/cli.d.ts +2 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -2
- package/dist/constants.d.ts +7 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +19 -4
- package/dist/file-system.d.ts +7 -0
- package/dist/file-system.d.ts.map +1 -1
- package/dist/file-system.js +15 -0
- package/dist/project-creator.d.ts +21 -1
- package/dist/project-creator.d.ts.map +1 -1
- package/dist/project-creator.js +84 -51
- package/dist/prompts.d.ts +7 -2
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +8 -3
- package/dist/validators.d.ts +7 -0
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js +13 -1
- package/package.json +6 -3
- package/templates/skills/bestax-custom-component/SKILL.md +21 -4
- package/templates/skills/bestax-custom-component/examples/stat-card.tsx +1 -2
- package/templates/skills/bestax-custom-component/references/api.md +103 -11
- package/templates/skills/bestax-custom-component/references/component-catalog.md +12 -5
- package/templates/skills/bestax-custom-component/references/library-contributor.md +23 -0
- package/templates/skills/bestax-form/SKILL.md +28 -17
- package/templates/skills/bestax-form/references/api.md +83 -23
- package/templates/skills/bestax-form/references/patterns.md +19 -0
- package/templates/skills/bestax-layout-scaffold/SKILL.md +17 -4
- package/templates/skills/bestax-layout-scaffold/references/layout-components.md +22 -15
- package/templates/skills/bestax-migrate/SKILL.md +32 -14
- package/templates/skills/bestax-migrate/references/bloomer/prop-map.md +9 -9
- package/templates/skills/bestax-migrate/references/bloomer/unmappables.md +19 -2
- package/templates/skills/bestax-migrate/references/bulma-classes/component-map.md +337 -0
- package/templates/skills/bestax-migrate/references/bulma-classes/prop-map.md +230 -0
- package/templates/skills/bestax-migrate/references/bulma-classes/unmappables.md +348 -0
- package/templates/skills/bestax-migrate/references/css-migration.md +8 -1
- package/templates/skills/bestax-migrate/references/rbx/component-map.md +15 -15
- package/templates/skills/bestax-migrate/references/rbx/prop-map.md +17 -19
- package/templates/skills/bestax-migrate/references/rbx/unmappables.md +17 -0
- package/templates/skills/bestax-migrate/references/react-bulma-components/component-map.md +34 -34
- package/templates/skills/bestax-migrate/references/react-bulma-components/unmappables.md +34 -7
- package/templates/skills/bestax-optimize/SKILL.md +3 -2
- package/templates/skills/bestax-optimize/references/modular-build.md +25 -5
- package/templates/skills/bestax-theming/SKILL.md +4 -3
- package/templates/skills/bestax-theming/examples/dark-mode.tsx +4 -3
- package/templates/skills/bestax-theming/references/css-variables.md +49 -8
- package/templates/skills/bestax-theming/references/themeable-components.md +12 -10
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
# Bulma classes → bestax-bulma: what the codemod leaves for you
|
|
2
|
+
|
|
3
|
+
Every `TODO(bestax-migrate)` this source writes, by rule, with what to do about it. The markup
|
|
4
|
+
under a TODO is exactly as it was, so the app still renders the same while you work through
|
|
5
|
+
them. The rule after the colon names a Bulma class, a bestax component or prop, or an
|
|
6
|
+
attribute, never one of your own classes.
|
|
7
|
+
|
|
8
|
+
## An element it would not convert
|
|
9
|
+
|
|
10
|
+
### `spread:<Target>`
|
|
11
|
+
|
|
12
|
+
The element spreads props (`<div className="box" {...rest}>`). A spread can carry anything,
|
|
13
|
+
and bestax reads some names as its own props: a spread `className` merges with the component's
|
|
14
|
+
classes, where on the plain element it replaced them. Convert by hand once you know what the
|
|
15
|
+
spread carries, or leave it. A spread on the `<select>` inside a `.select` counts too, since what it
|
|
16
|
+
carries becomes `SelectBase`'s.
|
|
17
|
+
|
|
18
|
+
### `ref:<Target>`
|
|
19
|
+
|
|
20
|
+
The element has a `ref`, and the bestax component doesn't forward one, so the ref would stop
|
|
21
|
+
reaching the DOM node. Keep the element as markup.
|
|
22
|
+
|
|
23
|
+
### `tag:<Target>`
|
|
24
|
+
|
|
25
|
+
The codemod converts that class on a fixed tag, or a short list of them through `as` (see the
|
|
26
|
+
**Tags** column in [component-map.md](component-map.md)), and this element is on another one:
|
|
27
|
+
`<div className="section">`, `<p className="notification">`. Changing the tag changes the
|
|
28
|
+
markup, so decide whether you want it; if you do, change it and re-run. If the component's
|
|
29
|
+
own `as` takes the tag, writing it by hand keeps the markup instead.
|
|
30
|
+
|
|
31
|
+
### `attr:<prop>`
|
|
32
|
+
|
|
33
|
+
An attribute on the element is also a prop of the bestax component, which would read it
|
|
34
|
+
differently: `<div className="box" color="red">` would lose its `color` attribute to Box's text
|
|
35
|
+
color. Rename or drop the attribute, then re-run.
|
|
36
|
+
|
|
37
|
+
It also covers an attribute the component's props type rejects. `Delete` takes no `type`
|
|
38
|
+
(`type="button"` is the one value that converts, because `Delete` renders it anyway), and
|
|
39
|
+
`Progress` types `value` and `max` as numbers, so `value="half"` stays. Every component types
|
|
40
|
+
`tabIndex` as a number too, so `tabIndex="0"` converts as `tabIndex={0}`. A number converts only
|
|
41
|
+
when it is spelled the way it renders (`value="40"`, not `value="040"`).
|
|
42
|
+
|
|
43
|
+
`attr:dangerouslySetInnerHTML` is the same kind of refusal: the element sets its own content,
|
|
44
|
+
and some bestax components render content of their own beside `children`, which React
|
|
45
|
+
rejects. Keep the element as markup. `attr:children` is too: the codemod reads an element's
|
|
46
|
+
children from the JSX inside it, so children passed as an attribute are content it can't see.
|
|
47
|
+
Move them inside the element, then re-run.
|
|
48
|
+
|
|
49
|
+
On a `.select` or a `.breadcrumb` it's about the element inside, which the component renders
|
|
50
|
+
itself. `SelectBase` gives its `<select>` every attribute it's given and no class but
|
|
51
|
+
`is-hovered` or `is-focused`, so an attribute on the `.select` (an `attr` TODO) would move onto
|
|
52
|
+
the `<select>`, and another class on the `<select>` (`attr:className`) would be lost, as would
|
|
53
|
+
the `class=""` an empty `className` renders. Move the
|
|
54
|
+
attribute onto the `<select>` if that's where you want it, then re-run. A `multiple` `<select>`
|
|
55
|
+
converts only inside a `.select.is-multiple`, with `multiple` written bare, and its `size` only
|
|
56
|
+
beside it, as a number written out (`size={4}`): `SelectBase` writes it back only when it holds a
|
|
57
|
+
number, which the codemod can't tell of an expression. `Breadcrumb` renders its `<ul>` bare, so an attribute or class on the `<ul>` keeps
|
|
58
|
+
both as markup.
|
|
59
|
+
|
|
60
|
+
On a menu item it's where each attribute lands. `Menu.Item` puts `className`, `id`, `title`,
|
|
61
|
+
`role`, `tabIndex`, `style` and `data-testid` on the `<li>`, and everything else on the `<a>`, so
|
|
62
|
+
an item converts only when its attributes already sit that way: an `onClick` on the `<li>`, or a
|
|
63
|
+
`title` or a `key` on the `<a>`, keeps it as markup. A `ref` on the `<a>` converts, since
|
|
64
|
+
`Menu.Item` forwards it there, and one on the `<li>` doesn't. The `<a>` takes no class but
|
|
65
|
+
`is-active`, since the item's `className` goes on the `<li>`, so any other class on it, or an
|
|
66
|
+
empty one, keeps the item as markup too, and so does an empty `className` on the `<li>`, since
|
|
67
|
+
nothing is left to render its `class=""`. Move the attribute to where `Menu.Item` puts it if
|
|
68
|
+
that's what you want, then re-run.
|
|
69
|
+
|
|
70
|
+
### `defaults:<Target>`
|
|
71
|
+
|
|
72
|
+
The component renders attributes of its own when the element doesn't set them. `Delete`
|
|
73
|
+
renders `type="button"` and `aria-label="Close"`. On a bare `<button className="delete">`,
|
|
74
|
+
converting would add both, changing a submit button inside a form into a plain button. Add the
|
|
75
|
+
attributes you want (usually both, with a real label), then re-run. `Navbar` renders
|
|
76
|
+
`role="navigation"` and `aria-label="main navigation"`, which Bulma's own navbar markup carries;
|
|
77
|
+
give the `<nav>` both, with your own label if you like. `Breadcrumb` renders
|
|
78
|
+
`aria-label="breadcrumbs"`, so give its `<nav>` an `aria-label`, whatever it says.
|
|
79
|
+
`Icon` renders `aria-label="icon"`, so give a `.icon` an `aria-label` that says what the icon means.
|
|
80
|
+
`Pagination` renders Bulma's own `role="navigation"` and `aria-label="pagination"`, and
|
|
81
|
+
`Pagination.Previous`, `Pagination.Next` and `Pagination.Link` render `tabIndex={0}`, so give each
|
|
82
|
+
element the attribute it's missing.
|
|
83
|
+
`Card.FooterItem`, `Card.Header.Icon` and `Navbar.Item` render `type="button"` on a `<button>` that
|
|
84
|
+
sets none, and `Card.Header.Icon` renders `aria-label="more options"` too. One whose `type` isn't
|
|
85
|
+
`button`, `submit` or `reset` gets an `attr:type` TODO instead, since bestax writes `button` in its
|
|
86
|
+
place. Write the type you mean, then re-run.
|
|
87
|
+
|
|
88
|
+
### `drops:<Target>`
|
|
89
|
+
|
|
90
|
+
The component drops an attribute on this tag. Most of these do nothing there anyway: `Button`
|
|
91
|
+
drops `href`, `target` and `rel` on a `<button>`, and `Level.Item` keeps link attributes only
|
|
92
|
+
on an `<a>`. Remove the attribute, then re-run.
|
|
93
|
+
|
|
94
|
+
`disabled` is the exception. `Button` drops it on a tag with no disabled state
|
|
95
|
+
(`<a className="button" disabled>`), but Bulma greys out a disabled `.button` on any tag, so
|
|
96
|
+
dropping it would change how the element looks. Keep that element as markup.
|
|
97
|
+
|
|
98
|
+
So is `name` on an `<a>`, which `Card.FooterItem` drops: browsers still scroll a `#fragment` link
|
|
99
|
+
to it. Keep that element as markup, or move the target to an `id` (which it keeps), then re-run.
|
|
100
|
+
|
|
101
|
+
### `children:<Target>`
|
|
102
|
+
|
|
103
|
+
The component's props type requires children, and the element has none (`Buttons`). An empty
|
|
104
|
+
`.buttons` does nothing; delete it or give it buttons.
|
|
105
|
+
|
|
106
|
+
On `Card` and `Card.Header` it means the children decide. `Card` renders its children inside a
|
|
107
|
+
`.card-content` of its own unless one of them is one of its parts (`Card.Header`,
|
|
108
|
+
`Card.Header.Icon`, `Card.Image`, `Card.Content`, `Card.Footer`, `Card.FooterItem`), and
|
|
109
|
+
`Card.Header` renders a `.card-header-title` of its own unless one of its children is a
|
|
110
|
+
`Card.Header.Title`. None of this element's direct children converted to one, so converting it
|
|
111
|
+
would add that wrapper. Look at the TODOs on the children first: a title that stays markup keeps
|
|
112
|
+
its header as markup too. A card whose content sits straight inside it, with no
|
|
113
|
+
`.card-content`, has no part to find; wrap that content in `Card.Content` if the extra padding
|
|
114
|
+
is what you want, or keep the markup. A part inside an expression (`{open && <div className="card-content">}`)
|
|
115
|
+
doesn't count, because it may not render.
|
|
116
|
+
|
|
117
|
+
On a `.table-container` or `.fixed-grid` it's the wrapper case. `Table isResponsive` and
|
|
118
|
+
`Grid isFixed` render that wrapper themselves, around nothing but the table or grid, so the
|
|
119
|
+
wrapper folds into them only when it holds that one element and nothing else. A caption, a
|
|
120
|
+
comment or a second element beside it keeps the wrapper as markup; move it outside the wrapper,
|
|
121
|
+
then re-run. An attribute or an extra class on the wrapper keeps it too, because the component
|
|
122
|
+
renders the wrapper bare.
|
|
123
|
+
|
|
124
|
+
On a `.select`, a `.breadcrumb` or an `.image` it's the same shape from the other side. `SelectBase`
|
|
125
|
+
renders the `<select>` inside `.select` itself, `Breadcrumb` the `<ul>` inside `.breadcrumb` and
|
|
126
|
+
`Image` the `<img>` inside `.image`. So `SelectBase` and `Breadcrumb` convert only around that one
|
|
127
|
+
element, with nothing else beside it. `Image` renders anything else it's given as it is, so an
|
|
128
|
+
`.image` converts around HTML elements written out either way. It gets this TODO when it's empty,
|
|
129
|
+
or when what's inside is an expression or text, since `Image` renders an `<img>` of its own when
|
|
130
|
+
its children come out empty. Keep it as markup, or write the `Image` by hand if the expression
|
|
131
|
+
never is.
|
|
132
|
+
|
|
133
|
+
A menu item is the same from the `<li>`'s side: `Menu.Item` renders the `<a>` inside it, and a
|
|
134
|
+
`Menu.List` after that, so an item converts only when its `<li>` holds one `<a>` and at most one
|
|
135
|
+
`<ul>` after it, with nothing else beside them. Text or a comment beside the `<a>` keeps it as
|
|
136
|
+
markup, and so does a router link or a `<button>` in its place: write a router link by hand as
|
|
137
|
+
`<Menu.Item as={Link}>`. The nested `<ul>` converts only bare (no class, no attributes) and
|
|
138
|
+
holding its items, as Bulma nests one, and the `<a>` has to hold something, since `Menu.Item`
|
|
139
|
+
requires children.
|
|
140
|
+
|
|
141
|
+
On a `.pagination-ellipsis`, `Pagination.Ellipsis` renders its own `…` whatever it's given, so the
|
|
142
|
+
element converts only holding exactly that (`…` or the character), and closes itself.
|
|
143
|
+
|
|
144
|
+
On an `.icon-text`, `IconText` builds its icons from props and wraps each text in a `<span>` of
|
|
145
|
+
its own, so it converts only when its children are `.icon`s, each followed by at most one bare
|
|
146
|
+
`<span>` of static text. Each `.icon` has to convert to `Icon` on its own, so one with no
|
|
147
|
+
`aria-label` gets a `defaults:Icon` TODO of its own first: give it one that says what the icon
|
|
148
|
+
means, then re-run. Its `<i>` has to be bare and empty and name one Font Awesome or Material Design
|
|
149
|
+
Icons glyph, so an `aria-hidden` on the `<i>`, another icon font, or anything between the children
|
|
150
|
+
keeps it as markup, and the `.icon`s inside convert on their own. The markup renders the same as
|
|
151
|
+
it is; to use `IconText` anyway, write it by hand with `iconProps={{ name: ... }}` (the
|
|
152
|
+
`bestax-icons` skill covers `Icon`'s library and name props).
|
|
153
|
+
|
|
154
|
+
On a `.file`, `File` renders the whole tree from props, so it converts only when its tree is the one
|
|
155
|
+
`File` renders: one bare `.file-label` `<label>` holding a `.file-input` `<input type="file">`, a
|
|
156
|
+
bare `.file-cta` `<span>` with a bare `.file-label` `<span>` and at most one bare `.file-icon`
|
|
157
|
+
`<span>` on each side of it, and, with `has-name`, at most one bare `.file-name` `<span>` of
|
|
158
|
+
static text. A class or attribute on any part of the tree, text between the parts, or content
|
|
159
|
+
that isn't text and elements written out keeps it as markup. Rebuild it as one `File` by hand
|
|
160
|
+
(its API page lists the props for the button text, the file name and the icons), or keep the
|
|
161
|
+
markup, which renders the same.
|
|
162
|
+
|
|
163
|
+
On a `.skeleton-lines`, `Skeleton` renders the children itself: `lines` bare, empty `<div>`s. So
|
|
164
|
+
the element converts only when its children are just that, and a class, an attribute, text or a
|
|
165
|
+
comment in one of them, or anything else beside them, keeps it as markup. Keep it if the
|
|
166
|
+
children matter; otherwise make them bare `<div>`s, then re-run.
|
|
167
|
+
|
|
168
|
+
### `context:<Target>`
|
|
169
|
+
|
|
170
|
+
`Field` and `Control` tell bestax's form controls inside them to skip their own `.field` and
|
|
171
|
+
`.control` wrappers. A `.field` or `.control` that already holds a bestax component (an `Input`
|
|
172
|
+
from an earlier, partial migration) would change how that component renders once converted, so
|
|
173
|
+
it stays markup. Convert it by hand and check that the component inside still renders what you
|
|
174
|
+
want, or leave it.
|
|
175
|
+
|
|
176
|
+
On a `.file` it's the other way round: `File` renders a `.field` of its own unless it sits inside
|
|
177
|
+
a `Field`, so a `.file` converts only inside a bestax `Field` or a `.field` that converts in the
|
|
178
|
+
same run. Convert the `.field` around it (its own TODO says what keeps it), then re-run.
|
|
179
|
+
|
|
180
|
+
On an input or textarea it's the other direction: inside a bestax `Field` with a `label`,
|
|
181
|
+
`InputBase` and `TextAreaBase` take the Field's generated `id` when they have none, which the
|
|
182
|
+
element didn't have. Context follows what renders, not what the file says, so an input with no
|
|
183
|
+
`id` inside any other component of the app stays markup too, since that component could render
|
|
184
|
+
a labelled `Field` around it. Give the element its own `id`, then re-run.
|
|
185
|
+
|
|
186
|
+
The codemod reads one file at a time, so it can't see a component in another file that renders
|
|
187
|
+
a bestax `Field` or form control around this markup. If the app already uses them that way, give
|
|
188
|
+
its inputs ids before running the codemod, and check its forms afterwards.
|
|
189
|
+
|
|
190
|
+
On a `.tabs` it's the same shape as a `.field`: `Tabs` passes its active tab to the `Tabs.Tab`s
|
|
191
|
+
and `Tabs.Content.Item`s inside it, and renders differently around a `Tabs.Content`, so a `.tabs`
|
|
192
|
+
that already holds one of those stays markup. Only the ones written in the file count: a
|
|
193
|
+
component of the app inside the `.tabs` that renders one itself would start following the
|
|
194
|
+
active tab once the `.tabs` converts, so check tabs built from your own components after the run.
|
|
195
|
+
|
|
196
|
+
On a `.modal-background`, `.modal-content` or `.modal-card` it's about the `Modal` around it. A
|
|
197
|
+
bestax `Modal` already in the file picks what it renders from its children: with one of those
|
|
198
|
+
parts among them it renders them as given, and without one it adds its own background, wrapper
|
|
199
|
+
and close button. So converting the part would change the `Modal`, and the part stays markup.
|
|
200
|
+
Convert the `Modal` and its children together by hand.
|
|
201
|
+
|
|
202
|
+
On a `.menu-list` it's about nesting: `Menu.List` renders `.menu-list` only on the outermost list,
|
|
203
|
+
and drops it on one inside another. So a `.menu-list` inside another `.menu-list` (or a bestax
|
|
204
|
+
`Menu.List`) stays markup, keeping its class, and so does one around a bestax `Menu.List`, which would
|
|
205
|
+
lose the class once the outer one converts. Only the elements in the same file count:
|
|
206
|
+
a `.menu-list` another component renders inside a `Menu.List` would lose the class, so check a
|
|
207
|
+
menu split across components after the run.
|
|
208
|
+
|
|
209
|
+
On a `.pagination-link` or a `.pagination-ellipsis` it's the `<li>` around it: `Pagination.Link`
|
|
210
|
+
and `Pagination.Ellipsis` render a bare `<li>` of their own, so each converts only as the only
|
|
211
|
+
thing inside a bare `<li>`, which it takes the place of, `key` and all. A class or an attribute
|
|
212
|
+
on the `<li>`, or anything beside the element in it, keeps it as markup. A `.pagination-link`'s
|
|
213
|
+
`is-current` becomes `active` only beside an `aria-current` of its own, since `active` renders
|
|
214
|
+
`aria-current="page"` otherwise; without one it stays a class. And `Pagination.Ellipsis` writes
|
|
215
|
+
a `className` it's given in place of `.pagination-ellipsis`, so another class on it keeps it as
|
|
216
|
+
markup with `attr:className`.
|
|
217
|
+
|
|
218
|
+
A menu item with a nested list is the same rule from inside: its nested `<ul>` becomes a
|
|
219
|
+
`Menu.List`, which renders `.menu-list` unless another `Menu.List` is around it. So the item
|
|
220
|
+
converts only inside a list that is a `Menu.List` already or becomes one in the same run, and an
|
|
221
|
+
item inside a `.menu-list` that stays markup (one that spreads props, say) keeps its nested list,
|
|
222
|
+
and itself, as markup with a `context:Menu.Item` TODO. An item with no nested list renders the
|
|
223
|
+
same anywhere, so it converts either way.
|
|
224
|
+
|
|
225
|
+
### `only-child:<Target>`
|
|
226
|
+
|
|
227
|
+
The element is the only child of another component (`<Link href="/x"><a className="button">`),
|
|
228
|
+
which may reach into it with `cloneElement`: next/link's legacy behavior, a tooltip, a Radix
|
|
229
|
+
`asChild` trigger. A bestax component would not take those props or that ref the same way.
|
|
230
|
+
Convert it by hand if the parent only renders its children.
|
|
231
|
+
|
|
232
|
+
### `dynamic-class:<Target>`
|
|
233
|
+
|
|
234
|
+
The `className` is computed in a way the codemod can't read exactly, and with its classes
|
|
235
|
+
written out the element would become bestax `<Target>`.
|
|
236
|
+
|
|
237
|
+
What it can read is a `clsx` or `classnames` call made of class strings and classes added
|
|
238
|
+
under a condition: `busy && 'is-loading'`, `{ 'is-loading': busy }`, `busy ? 'is-loading' : ''`
|
|
239
|
+
(or `: null`). Those convert without a TODO. A condition on one of the component's flags
|
|
240
|
+
becomes that prop (`isLoading={busy}`, or `isLight={!quiet}` for `quiet ? '' : 'is-light'`),
|
|
241
|
+
anything else stays in the call, and the call goes once nothing is left in it. `Field`'s
|
|
242
|
+
`is-grouped` stays in the call too, since `grouped` renders it for `true` alone. A prop is
|
|
243
|
+
evaluated before the call, so a condition moves ahead of one left in the call only when neither
|
|
244
|
+
can have side effects (a call, an assignment); otherwise it stays. A condition that isn't a
|
|
245
|
+
boolean (`items.length && 'is-active'`) renders the same, but won't typecheck against the
|
|
246
|
+
boolean prop; wrap it in `Boolean(…)`.
|
|
247
|
+
|
|
248
|
+
So this TODO is a className built any other way: a ternary between two classes, a template
|
|
249
|
+
with expressions, a variable, another function (`classnames/bind`, an app's own `cn`), or the
|
|
250
|
+
component's class itself under a condition. Convert by hand with the [prop map](prop-map.md),
|
|
251
|
+
turning each condition into the prop:
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
// before
|
|
255
|
+
<button className={primary ? 'button is-primary' : 'button is-light'}>Save</button>
|
|
256
|
+
// after
|
|
257
|
+
<Button color={primary ? 'primary' : undefined} isLight={!primary}>Save</Button>
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
The classes in a computed `className` still count for every other rule: a `clsx('box')` on a
|
|
261
|
+
`<span>` gets `tag:Box`, and a `clsx('dropdown', …)` gets `family:dropdown`. A computed
|
|
262
|
+
`className` on the `<select>` inside a `.select`, the `<ul>` inside a `.breadcrumb` or the `<a>`
|
|
263
|
+
in a menu item gets this TODO too. For the `<a>`, a condition on `is-active` is `Menu.Item`'s
|
|
264
|
+
`active`: `<a className={on ? 'is-active' : undefined}>` becomes `<Menu.Item active={on}>`.
|
|
265
|
+
|
|
266
|
+
## A family it leaves as markup: `family:<class>`
|
|
267
|
+
|
|
268
|
+
The bestax component renders parts of its own, or adds attributes, so a one-element-at-a-time
|
|
269
|
+
conversion would change the markup. Convert the whole family by hand, and look at the result
|
|
270
|
+
in the browser:
|
|
271
|
+
|
|
272
|
+
- **`family:navbar-burger`**: `Navbar.Burger` is a `<button>` that renders the burger's spans
|
|
273
|
+
itself and sets `aria-expanded` from `active`. Replace the whole toggle with it, drive
|
|
274
|
+
`active` from the state the old click handler flipped, and pass the same state to
|
|
275
|
+
`Navbar.Menu`'s `active`. Don't give it spans of your own: Bulma positions every span in the
|
|
276
|
+
burger. Releases before 5.16.10 render three spans where Bulma v1 positions four, so upgrade
|
|
277
|
+
rather than adding one.
|
|
278
|
+
- **`family:navbar-link`**: inside a `Navbar.Dropdown`, `Navbar.Link` adds `aria-haspopup`,
|
|
279
|
+
`aria-expanded` and keyboard handling. The codemod turned the `.has-dropdown` item around it
|
|
280
|
+
into a `Navbar.Item` that keeps the class; to get the dropdown behavior, replace that item
|
|
281
|
+
with `Navbar.Dropdown` (`hoverable` for `is-hoverable`) and the link with `Navbar.Link`.
|
|
282
|
+
- **`family:checkbox`**, **`family:radio`**, **`family:checkboxes`**, **`family:radios`**:
|
|
283
|
+
bestax renders its own styled checkbox and radio markup, not Bulma's.
|
|
284
|
+
- **`family:modal`**: `Modal` writes a `data-testid` of its own and adds dialog attributes and
|
|
285
|
+
focus handling, so the `.modal` root stays markup while its background, content and card parts
|
|
286
|
+
convert on their own. Rebuild the root with `Modal` around them, and drive it with its open prop.
|
|
287
|
+
A `.modal-close` stays too, since `Modal.Close` renders `.delete` unless it's floating: write
|
|
288
|
+
`<Modal.Close variant="floating" />` in its place. When the
|
|
289
|
+
page has to look the same, keep `Modal` rather than `Dialog` or `Toast`: those render
|
|
290
|
+
bestax's own `.dialog` and `.toast` markup, which Bulma's stylesheet doesn't style.
|
|
291
|
+
- **`family:dropdown`**: `Dropdown` renders its own trigger and menu from props.
|
|
292
|
+
- **`family:menu-item`**: Bulma styles an item as `.menu-list a`, `.menu-list button` or
|
|
293
|
+
`.menu-list .menu-item`, the last for an item on any other tag. `Menu.Item` renders the element
|
|
294
|
+
inside its `<li>` with no class but `is-active`, and puts its `className` on the `<li>`, so the
|
|
295
|
+
class has nowhere to go. On an `<a>` inside a `.menu-list` it adds nothing, so drop it and
|
|
296
|
+
re-run, and the item can convert. On any other tag, keep the markup.
|
|
297
|
+
- **`family:message`**: `Message` always wraps its children in `.message-body`.
|
|
298
|
+
- **`family:panel-icon`**: `Panel.Icon` renders through `Icon`, which always writes an
|
|
299
|
+
`aria-label`, so write `<Panel.Icon>` by hand with the `<i>` inside. The rest of a panel converts,
|
|
300
|
+
but for a `<label>` or `<div>` `.panel-block`, which stays markup with no TODO: bestax renders
|
|
301
|
+
those as `Panel.CheckboxBlock`, `Panel.InputBlock` and `Panel.ButtonBlock`, which build their own
|
|
302
|
+
contents from props.
|
|
303
|
+
|
|
304
|
+
## A class Bulma v1 removed: `legacy:<class>`
|
|
305
|
+
|
|
306
|
+
`legacy:tile`: Bulma v1 has no tiles. Rebuild the layout with `Grid` and `Cell`; the Bulma
|
|
307
|
+
0.9 to 1 guide shows the translation. Until then the element has no styles at all under
|
|
308
|
+
Bulma v1.
|
|
309
|
+
|
|
310
|
+
## A whole file it left alone
|
|
311
|
+
|
|
312
|
+
These come only when the file has an element the codemod would convert (a computed className
|
|
313
|
+
counts), so a re-run after the fix has something to do. A non-React file gets `jsx-runtime`
|
|
314
|
+
alone: every other TODO names a React component to use.
|
|
315
|
+
|
|
316
|
+
- **`rsc`**: the file is in a Next.js App Router project (a package with `next` and an
|
|
317
|
+
`app/` directory) and has no `'use client'`, so it may render as a server component, and
|
|
318
|
+
bestax's components are client components. That covers files outside `app/` too: a
|
|
319
|
+
component under `components/` is a server component when a server page renders it. Files
|
|
320
|
+
under `pages/` are always client code and convert. Add `'use client'` if the file can be a
|
|
321
|
+
client module (no `async` component, no server-only calls), then re-run.
|
|
322
|
+
- **`styled-jsx`**: the component scopes its styles with `<style jsx>`, which adds its scoping
|
|
323
|
+
class to plain elements and not to an imported component, so a converted element would lose
|
|
324
|
+
its styles. Move those
|
|
325
|
+
styles out of `<style jsx>`, or scope them with `:global()`, then re-run.
|
|
326
|
+
- **`imports`**: the file is CommonJS (`require` or `module.exports`, no ES `import` or
|
|
327
|
+
`export`), and the codemod adds an ES `import`. Move the file to ES modules, then re-run.
|
|
328
|
+
- **`jsx-runtime`**: the file's JSX isn't React's: a `@jsx` pragma or `@jsxImportSource` naming
|
|
329
|
+
another runtime (Preact, Solid), or a package that sets one in its tsconfig or depends on one
|
|
330
|
+
instead of React. bestax-bulma components are React components.
|
|
331
|
+
|
|
332
|
+
## Things that get no TODO
|
|
333
|
+
|
|
334
|
+
- Helper classes on a `<div>` (`<div className="is-flex mt-4">`): bestax has no plain `<div>`
|
|
335
|
+
wrapper, and the classes are valid Bulma, so the element stays.
|
|
336
|
+
- `.help`, `.label`, `.loader` and the other classes in the component map's "left alone" list.
|
|
337
|
+
- A class with no bestax prop on a converted element: it stays in `className`.
|
|
338
|
+
|
|
339
|
+
## After the codemod
|
|
340
|
+
|
|
341
|
+
Class order changes on converted elements (bestax writes its own classes first), so snapshot
|
|
342
|
+
tests that compare class strings will churn while the rendered page stays the same. Update the
|
|
343
|
+
snapshots after reviewing the diff.
|
|
344
|
+
|
|
345
|
+
If the build runs PurgeCSS, the report says so: a converted element's classes now come from
|
|
346
|
+
bestax's code, some of them built from props at runtime (`mt="4"` renders `mt-4`), so the
|
|
347
|
+
PurgeCSS config has to scan bestax's dist and safelist those patterns. The docs' optimizing CSS
|
|
348
|
+
guide has the config.
|
|
@@ -8,7 +8,14 @@ stylesheet layer; this reference explains what it did and how to finish what it
|
|
|
8
8
|
Coming from rbx or bloomer you are crossing **two** Bulma majors rather than one, so expect more
|
|
9
9
|
visual drift than the 0.9 → 1 notes below describe on their own.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
An app that writes Bulma's classes directly (`bulma-classes`) keeps its stylesheet by
|
|
12
|
+
default: that source runs as `--css keep`, because the app's own Bulma already styles every
|
|
13
|
+
class a converted element renders, so its stylesheet imports, Sass and Bulma version stay as
|
|
14
|
+
they were. Moving to Bulma v1 is a separate step, taken with `--css bestax` or `--css bulma`.
|
|
15
|
+
From a 0.9.x it then follows these notes as written; on Bulma v1 already, only the bundle
|
|
16
|
+
choice below applies.
|
|
17
|
+
|
|
18
|
+
## What the codemod already did (`--css bestax`, the library sources' default)
|
|
12
19
|
|
|
13
20
|
- **CSS imports**: `bulma/css/bulma(.min).css` and v3-era
|
|
14
21
|
the source library's own CSS imports (`react-bulma-components/dist/*.css`,
|
|
@@ -142,21 +142,21 @@ test holds to rbx's own export surface in both directions.
|
|
|
142
142
|
|
|
143
143
|
## The renames worth memorising
|
|
144
144
|
|
|
145
|
-
| rbx | bestax-bulma
|
|
146
|
-
| ---------------------------------- |
|
|
147
|
-
| `Tag.Group` | `Tags`
|
|
148
|
-
| `Button.Group` | `Buttons`
|
|
149
|
-
| `Column.Group` | `Columns`
|
|
150
|
-
| `Card.Footer.Item` | `Card.FooterItem`
|
|
151
|
-
| `Table.Head` / `.Body` / `.Foot` | `Table.Thead` / `.Tbody` / `.Tfoot`
|
|
152
|
-
| `Table.Row` / `.Cell` / `.Heading` | `Table.Tr` / `.Td` / `.Th`
|
|
153
|
-
| `Textarea` | `TextArea`
|
|
154
|
-
| `PageLoader` | `Loading` with `isFullPage`
|
|
155
|
-
| `Loader` | a plain `<div className="loader">` — bestax's `Loading` is an overlay that renders nothing unless `active` |
|
|
156
|
-
| `Menu.List.Item` | `Menu.Item`
|
|
157
|
-
| `Tab` / `Tab.Group` | `Tabs.Item` / `Tabs`
|
|
158
|
-
| `Panel.Tab.Group` | `Panel.Tabs`
|
|
159
|
-
| `Title subtitle` | `SubTitle`
|
|
145
|
+
| rbx | bestax-bulma |
|
|
146
|
+
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
147
|
+
| `Tag.Group` | `Tags` |
|
|
148
|
+
| `Button.Group` | `Buttons` |
|
|
149
|
+
| `Column.Group` | `Columns` |
|
|
150
|
+
| `Card.Footer.Item` | `Card.FooterItem` |
|
|
151
|
+
| `Table.Head` / `.Body` / `.Foot` | `Table.Thead` / `.Tbody` / `.Tfoot` |
|
|
152
|
+
| `Table.Row` / `.Cell` / `.Heading` | `Table.Tr` / `.Td` / `.Th` |
|
|
153
|
+
| `Textarea` | `TextArea` |
|
|
154
|
+
| `PageLoader` | `Loading` with `isFullPage` |
|
|
155
|
+
| `Loader` | a plain `<div className="loader">` — bestax's `Loading` is an overlay that renders nothing unless `active`; bestax's `Loader` renders the same ring as a named progressbar, so swap it in by hand |
|
|
156
|
+
| `Menu.List.Item` | `Menu.Item` |
|
|
157
|
+
| `Tab` / `Tab.Group` | `Tabs.Item` / `Tabs` |
|
|
158
|
+
| `Panel.Tab.Group` | `Panel.Tabs` |
|
|
159
|
+
| `Title subtitle` | `SubTitle` |
|
|
160
160
|
|
|
161
161
|
## Value-chosen targets
|
|
162
162
|
|
|
@@ -140,26 +140,26 @@ that is what keeps the `href`. Dropping the `as` does not, on this component.
|
|
|
140
140
|
rbx reaches a component's rendered element with `innerRef`. bestax uses a plain forwarded
|
|
141
141
|
`ref` on the roots that support one, so the codemod renames the prop:
|
|
142
142
|
|
|
143
|
-
| rbx | bestax-bulma | note
|
|
144
|
-
| ----------------------------------------------------- | ------------ |
|
|
145
|
-
| `innerRef` on `Button`, `Dropdown`, `Modal`, `Navbar` | `ref` | same node — each root's own element
|
|
146
|
-
| `innerRef` on `Navbar.Burger`, `Navbar.Link` | `ref` | these two sub-components forward one too
|
|
147
|
-
| `innerRef` on `Navbar.Item`
|
|
148
|
-
| `innerRef` on `Modal.Container` | `ref` | that one becomes bestax's `Modal` root
|
|
143
|
+
| rbx | bestax-bulma | note |
|
|
144
|
+
| ----------------------------------------------------- | ------------ | -------------------------------------------- |
|
|
145
|
+
| `innerRef` on `Button`, `Dropdown`, `Modal`, `Navbar` | `ref` | same node — each root's own element |
|
|
146
|
+
| `innerRef` on `Navbar.Burger`, `Navbar.Link` | `ref` | these two sub-components forward one too |
|
|
147
|
+
| `innerRef` on `Navbar.Item` | `ref` | with `dropdown` it becomes `Navbar.Dropdown` |
|
|
148
|
+
| `innerRef` on `Modal.Container` | `ref` | that one becomes bestax's `Modal` root |
|
|
149
149
|
|
|
150
150
|
The third row is the `Navbar.Dropdown` collision, and it runs both ways. Your rbx
|
|
151
151
|
`Navbar.Dropdown` is the menu itself (`div.navbar-dropdown`), so it maps to bestax's
|
|
152
152
|
`Navbar.DropdownMenu`, which forwards no ref — `innerRef` there is left alone. bestax reserves
|
|
153
153
|
the name `Navbar.Dropdown` for the outer container, which is what `<Navbar.Item dropdown>`
|
|
154
|
-
becomes.
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
154
|
+
becomes.
|
|
155
|
+
|
|
156
|
+
Beside a `ref` the element already has, a rename leaves `innerRef` in place with a `prop:innerRef`
|
|
157
|
+
TODO rather than write a second `ref`; keep whichever one you meant.
|
|
158
158
|
|
|
159
159
|
An existing `ref` is passed through untouched — which is safe only where the bestax target
|
|
160
160
|
forwards one. rbx forwards a ref on every component; bestax does so on the form controls, plus
|
|
161
161
|
`Avatar`, `Button`, `Carousel`, `CarouselItem`, `Dialog`, `Dropdown`, `Link`, `LinkButton`,
|
|
162
|
-
`Menu.Item`, `Modal`, `Navbar`, `Navbar.Burger`, `Navbar.Dropdown`, `Navbar.Item`,
|
|
162
|
+
`Loader`, `Menu.Item`, `Modal`, `Navbar`, `Navbar.Burger`, `Navbar.Dropdown`, `Navbar.Item`,
|
|
163
163
|
`Navbar.Link`, `Sidebar` and `Toast`. "The form controls" there means the inputs themselves:
|
|
164
164
|
the `Field`, `Field.Label`, `Field.Body`, `Checkboxes` and `Radios` wrappers around them
|
|
165
165
|
forward nothing, and `Field` is a target this codemod emits.
|
|
@@ -174,11 +174,9 @@ outcome is one to build on: put the ref on an element you control.
|
|
|
174
174
|
**The codemod does not flag this**, because neither the universal prop table nor any
|
|
175
175
|
per-component table has a `ref` entry, so check every `ref` you carried over against the list
|
|
176
176
|
above rather than assuming the silent pass-through means it works. The renames above are for
|
|
177
|
-
`innerRef`, and apply only
|
|
178
|
-
|
|
179
|
-
Note the gap that leaves.
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
renames above do not reach, `innerRef` is flagged the same way — but on a target that forwards
|
|
184
|
-
nothing the answer is a wrapping element you control, not a rename.
|
|
177
|
+
`innerRef`, and apply only where the table says.
|
|
178
|
+
|
|
179
|
+
Note the gap that leaves. Where no row above reaches, `innerRef` stays in place and is flagged.
|
|
180
|
+
On a target that forwards a ref (the form controls, `Menu.Item`) the rename is yours to make and
|
|
181
|
+
the target will take it. On one that forwards nothing, the answer is a wrapping element you
|
|
182
|
+
control, not a rename.
|
|
@@ -95,6 +95,23 @@ these either. `Level.Item` is not narrower: it declares the anchor's whole attri
|
|
|
95
95
|
every `as` and forwards it only on the `<a>`, so all of these survive at `as="a"` and none of
|
|
96
96
|
them reaches a `<p>` or a `<div>`.
|
|
97
97
|
|
|
98
|
+
## `prop:type` — a `<button>` item that no longer submits its form
|
|
99
|
+
|
|
100
|
+
`Navbar.Item`, `Navbar.Link`, `Menu.Item` and `Dropdown.Item` write `type="button"` on the
|
|
101
|
+
`<button>` an `as` makes them render, whenever the element sets no `type` or one HTML doesn't
|
|
102
|
+
define. A plain `<button>` with neither submits the form around it, so an item you rendered as a
|
|
103
|
+
button with `as="button"` stops submitting once migrated. The codemod can't tell whether one sits
|
|
104
|
+
in a form, so each gets a TODO:
|
|
105
|
+
|
|
106
|
+
```jsx
|
|
107
|
+
<Navbar.Item as="button">Search</Navbar.Item>
|
|
108
|
+
<Navbar.Item as="button">Search</Navbar.Item>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Add `type="submit"` if it should still submit, or `type="button"` to say it shouldn't, then
|
|
112
|
+
delete the comment. An item whose `type` is written out as `button`, `submit` or `reset`, or
|
|
113
|
+
comes from a spread or an expression, gets no TODO.
|
|
114
|
+
|
|
98
115
|
## `component:Generic` — rbx's base element
|
|
99
116
|
|
|
100
117
|
`Generic` is rbx's untyped passthrough. Render the underlying tag, and move its helper props to
|
|
@@ -6,40 +6,40 @@ codemod converts it; **Flagged** = it leaves a `TODO(bestax-migrate)` comment (s
|
|
|
6
6
|
|
|
7
7
|
## Top-level components
|
|
8
8
|
|
|
9
|
-
| RBC | bestax | Notes
|
|
10
|
-
| -------------- | -------------------------------------------- |
|
|
11
|
-
| `Block` | `Block` | Auto
|
|
12
|
-
| `Box` | `Box` | Auto
|
|
13
|
-
| `Breadcrumb` | `Breadcrumb` | Auto; `align` → `alignment` (`center`→`centered`)
|
|
14
|
-
| `Button` | `Button` | Auto for literal `remove` (by value, not presence — truthy → `<Delete/>`, `remove={false}` stays `Button`); dynamic flagged
|
|
15
|
-
| `Card` | `Card` | Auto
|
|
16
|
-
| `Columns` | `Columns` | Auto; `breakpoint="mobile"`→`isMobile`, `multiline`→`isMultiline`, …
|
|
17
|
-
| `Container` | `Container` | Auto; `breakpoint="fluid"`→`fluid`, `max`→`isMax`
|
|
18
|
-
| `Content` | `Content` | Auto
|
|
19
|
-
| `Dropdown` | `Dropdown` | Structure auto; controlled `value`/`onChange` flagged
|
|
20
|
-
| `Element` | — | Flagged: no generic element; use a semantic component + helper props
|
|
21
|
-
| `Footer` | `Footer` | Auto
|
|
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
|
|
24
|
-
| `Hero` | `Hero` | Auto; `hasNavbar`→`fullheightWithNavbar`; `halfheight`/`gradient` flagged
|
|
25
|
-
| `Icon` | `Icon` | `<i class="fas fa-x">` children → `name`/`library`/`variant` props; else flagged
|
|
26
|
-
| `Image` | `Image` | Auto; numeric `size={128}` → `size="128x128"`, `rounded`→`isRounded`
|
|
27
|
-
| `Level` | `Level` | Auto; `breakpoint="mobile"`→`isMobile`
|
|
28
|
-
| `Loader` | plain `<div className="loader">` | Auto (Bulma v1 still ships the class)
|
|
29
|
-
| `Media` | `Media` | Auto
|
|
30
|
-
| `Menu` | `Menu` | Auto
|
|
31
|
-
| `Message` | `Message` | Auto; `size` flagged
|
|
32
|
-
| `Modal` | `Modal` | `show`→`active`, `closeOnEsc`→`closeOnEscape`; `closeOnBlur`/`showClose` flagged (compound form renders neither)
|
|
33
|
-
| `Navbar` | `Navbar` | Auto; see dropdown note below
|
|
34
|
-
| `Notification` | `Notification` | Auto; `light`→`isLight`
|
|
35
|
-
| `Pagination` | `Pagination` | `onChange`→`onPageChange`; `
|
|
36
|
-
| `Panel` | `Panel` | Auto
|
|
37
|
-
| `Progress` | `Progress` | Auto
|
|
38
|
-
| `Section` | `Section` | Auto
|
|
39
|
-
| `Table` | `Table` | Auto; `size="fullwidth"`→`isFullwidth`, `striped`→`isStriped`, …
|
|
40
|
-
| `Tabs` | `Tabs` | Auto; children wrapped in `Tabs.List`; `type="toggle-rounded"`→`toggle rounded`
|
|
41
|
-
| `Tag` | `Tag` | Auto; `remove`→`isDelete`, `rounded`→`isRounded`
|
|
42
|
-
| `Tile` | — | Flagged: Bulma v1 replaced tiles with `Grid`/`Cell`
|
|
9
|
+
| RBC | bestax | Notes |
|
|
10
|
+
| -------------- | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
11
|
+
| `Block` | `Block` | Auto |
|
|
12
|
+
| `Box` | `Box` | Auto |
|
|
13
|
+
| `Breadcrumb` | `Breadcrumb` | Auto; `align` → `alignment` (`center`→`centered`) |
|
|
14
|
+
| `Button` | `Button` | Auto for literal `remove` (by value, not presence — truthy → `<Delete/>`, `remove={false}` stays `Button`); dynamic flagged |
|
|
15
|
+
| `Card` | `Card` | Auto |
|
|
16
|
+
| `Columns` | `Columns` | Auto; `breakpoint="mobile"`→`isMobile`, `multiline`→`isMultiline`, … |
|
|
17
|
+
| `Container` | `Container` | Auto; `breakpoint="fluid"`→`fluid`, `max`→`isMax` |
|
|
18
|
+
| `Content` | `Content` | Auto |
|
|
19
|
+
| `Dropdown` | `Dropdown` | Structure auto; controlled `value`/`onChange` flagged |
|
|
20
|
+
| `Element` | — | Flagged: no generic element; use a semantic component + helper props |
|
|
21
|
+
| `Footer` | `Footer` | Auto |
|
|
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 |
|
|
24
|
+
| `Hero` | `Hero` | Auto; `hasNavbar`→`fullheightWithNavbar`; `halfheight`/`gradient` flagged |
|
|
25
|
+
| `Icon` | `Icon` | `<i class="fas fa-x">` children → `name`/`library`/`variant` props; else flagged |
|
|
26
|
+
| `Image` | `Image` | Auto; numeric `size={128}` → `size="128x128"`, `rounded`→`isRounded` |
|
|
27
|
+
| `Level` | `Level` | Auto; `breakpoint="mobile"`→`isMobile` |
|
|
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
|
+
| `Media` | `Media` | Auto |
|
|
30
|
+
| `Menu` | `Menu` | Auto |
|
|
31
|
+
| `Message` | `Message` | Auto; `size` flagged |
|
|
32
|
+
| `Modal` | `Modal` | `show`→`active`, `closeOnEsc`→`closeOnEscape`; `closeOnBlur`/`showClose` flagged (compound form renders neither) |
|
|
33
|
+
| `Navbar` | `Navbar` | Auto; see dropdown note below |
|
|
34
|
+
| `Notification` | `Notification` | Auto; `light`→`isLight` |
|
|
35
|
+
| `Pagination` | `Pagination` | `onChange`→`onPageChange`, `delta`→`siblingCount`, `next`/`previous`→`nextLabel`/`previousLabel`; `showFirstLast`/`showPrevNext`/`autoHide` flagged |
|
|
36
|
+
| `Panel` | `Panel` | Auto |
|
|
37
|
+
| `Progress` | `Progress` | Auto |
|
|
38
|
+
| `Section` | `Section` | Auto |
|
|
39
|
+
| `Table` | `Table` | Auto; `size="fullwidth"`→`isFullwidth`, `striped`→`isStriped`, … |
|
|
40
|
+
| `Tabs` | `Tabs` | Auto; children wrapped in `Tabs.List`; `type="toggle-rounded"`→`toggle rounded` |
|
|
41
|
+
| `Tag` | `Tag` | Auto; `remove`→`isDelete`, `rounded`→`isRounded` |
|
|
42
|
+
| `Tile` | — | Flagged: Bulma v1 replaced tiles with `Grid`/`Cell` |
|
|
43
43
|
|
|
44
44
|
## Compound sub-components
|
|
45
45
|
|