create-bestax 4.2.6 → 4.2.8
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 +1 -1
- package/package.json +3 -2
- package/templates/skills/bestax-custom-component/references/library-contributor.md +28 -0
- package/templates/skills/bestax-layout-scaffold/references/layout-components.md +2 -1
- package/templates/skills/bestax-migrate/SKILL.md +20 -8
- package/templates/skills/bestax-migrate/references/bloomer/component-map.md +159 -0
- package/templates/skills/bestax-migrate/references/bloomer/prop-map.md +135 -0
- package/templates/skills/bestax-migrate/references/bloomer/unmappables.md +240 -0
- package/templates/skills/bestax-migrate/references/css-migration.md +4 -3
- package/templates/skills/bestax-migrate/references/rbx/unmappables.md +3 -1
package/dist/constants.js
CHANGED
|
@@ -182,7 +182,7 @@ automatically when the task matches:
|
|
|
182
182
|
- **bestax-layout-scaffold** — scaffold full pages (app shell, landing, centered, card grid).
|
|
183
183
|
- **bestax-icons** — icons via \`Icon\`/\`IconText\`: library setup, name formats, variants, a11y.
|
|
184
184
|
- **bestax-optimize** — shrink the built CSS: measure raw+gzip, then flavor switch or a modular Sass build.
|
|
185
|
-
- **bestax-migrate** — migrate code off react-bulma-components (v4)
|
|
185
|
+
- **bestax-migrate** — migrate code off react-bulma-components (v4), rbx (v2) or bloomer (0.6): run the codemod, resolve its TODOs.
|
|
186
186
|
|
|
187
187
|
Prefer the library's components and these skills over hand-written Bulma markup or custom CSS.
|
|
188
188
|
Read skill \`references/\` files with absolute paths — the shell's cwd is not stable between commands.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-bestax",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.8",
|
|
4
4
|
"description": "Create a new bestax-bulma project",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -38,7 +38,8 @@
|
|
|
38
38
|
"commander": "^15.0.0",
|
|
39
39
|
"figures": "^6.1.0",
|
|
40
40
|
"fs-extra": "^11.4.0",
|
|
41
|
-
"prompts": "^2.4.2"
|
|
41
|
+
"prompts": "^2.4.2",
|
|
42
|
+
"@allxsmith/bestax-bulma": "^5.15.1"
|
|
42
43
|
},
|
|
43
44
|
"devDependencies": {
|
|
44
45
|
"@jest/globals": "^30.0.0",
|
|
@@ -97,6 +97,34 @@ Rules that keep components consistent:
|
|
|
97
97
|
- **Spread `rest`, not `props`**, onto the DOM node — `useBulmaClasses` has already stripped the
|
|
98
98
|
helper props out of `rest`, so they don't leak to the DOM as invalid attributes.
|
|
99
99
|
- **Set `displayName`** on `forwardRef` components (needed for tests and Storybook autodocs).
|
|
100
|
+
- **A polymorphic `as` means the props follow it, and usually the ref too.** If `as` accepts any
|
|
101
|
+
`React.ElementType`, do not pin the props to one element — split them into a
|
|
102
|
+
`FooOwnProps` interface and intersect it with `ComponentPropsWithoutRef<T>`, then cast
|
|
103
|
+
the `forwardRef` result to `PolymorphicComponent<FooOwnProps, 'default-tag'>`
|
|
104
|
+
(`src/helpers/polymorphic.ts`). `Button.tsx` is the reference.
|
|
105
|
+
**Write that intersection out in the alias; do not build it from
|
|
106
|
+
`PolymorphicProps<T, FooOwnProps>`.** The API-docs extractor walks heritage
|
|
107
|
+
syntactically, and it cannot see through a generic alias or a distributive
|
|
108
|
+
conditional — routing the alias through the helper drops most of the props
|
|
109
|
+
table without failing (#667). `PolymorphicProps` is for consumer and wrapper
|
|
110
|
+
types; `PolymorphicComponent<FooOwnProps, 'default-tag'>` is the cast target,
|
|
111
|
+
and `PolymorphicComponentWithoutRef` the one for a component that forwards no
|
|
112
|
+
ref. Add type-level checks in `src/__typetests__/` both ways — that the
|
|
113
|
+
default `as` accepts its element's props and a different `as` rejects them —
|
|
114
|
+
since nothing else in the repo type-checks this. Pinning the props instead
|
|
115
|
+
rejects correct code and accepts incorrect code at the same time, which is what #641 fixed
|
|
116
|
+
across eight components. A literal union (`Title.tsx`) escapes the generic only when its
|
|
117
|
+
members genuinely **share** a prop and ref surface — `h1`–`h6` and `p` all carry plain
|
|
118
|
+
`HTMLAttributes`, so one interface describes them all. It is not a general exemption:
|
|
119
|
+
`Dropdown.Item`'s `'a' | 'div' | 'button'` differ in `href`, `disabled`, `type` and their ref
|
|
120
|
+
element, and pinning them to one interface reproduces exactly this defect (#663). When the
|
|
121
|
+
members differ, constrain `T` to the union rather than dropping the generic.
|
|
122
|
+
Forward the ref unless the component owns the node it needs: `Reveal` observes
|
|
123
|
+
an element for scroll intersection and wraps a custom `as` in its own `div`,
|
|
124
|
+
so the element `as` names is not the one it holds — it uses
|
|
125
|
+
`PolymorphicComponentWithoutRef` and forwards none. That is the exception, not
|
|
126
|
+
a licence to skip refs; everything a consumer might focus or measure should
|
|
127
|
+
forward one.
|
|
100
128
|
- **Element sizing uses an inline `'small' | 'medium' | 'large'` union**, mapped to `is-small` /
|
|
101
129
|
`is-medium` / `is-large` (see `Tabs.tsx`, `Control.tsx`). Do **not** reach for the `validSizes`
|
|
102
130
|
constant — that one is `'0'…'6' | 'auto'` and exists for **spacing** helpers, not element size.
|
|
@@ -243,7 +243,8 @@ a navbar that mounts conditionally.
|
|
|
243
243
|
|
|
244
244
|
**Routing:** in a routed app, don't use `href="#"` — render items as the router's link
|
|
245
245
|
component. `Menu.Item as={Link} to="/x"` and `Navbar.Item as={Link} to="/x"` both compile
|
|
246
|
-
without casts (their props
|
|
246
|
+
without casts (their props follow `as`, so `to` is checked against the router's own link
|
|
247
|
+
type). Drive `active` from `useLocation().pathname`.
|
|
247
248
|
Full patterns (including Buttons that navigate and Next.js `href`): the docs guide at
|
|
248
249
|
https://bestax.io/docs/guides/features/routing.
|
|
249
250
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: bestax-migrate
|
|
3
|
-
description: Migrate an existing app from an unmaintained React Bulma library — react-bulma-components (v4)
|
|
3
|
+
description: Migrate an existing app from an unmaintained React Bulma library — react-bulma-components (v4), rbx (v2) or bloomer (0.6) — to @allxsmith/bestax-bulma on Bulma v1. Run the bestax-migrate codemod, then resolve every TODO(bestax-migrate) comment it leaves using the per-source mapping references. Use when a repo imports react-bulma-components, rbx or bloomer and wants to move to bestax-bulma, when TODO(bestax-migrate) comments are present in a codebase, or when asked to migrate off an unmaintained React Bulma library.
|
|
4
4
|
license: MIT
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -15,10 +15,11 @@ this skill drives the codemod and finishes what it flags.
|
|
|
15
15
|
The codemod's first argument names the library you are migrating _from_. Check the app's
|
|
16
16
|
`package.json` and imports:
|
|
17
17
|
|
|
18
|
-
| Source
|
|
19
|
-
|
|
|
20
|
-
| `react-bulma-components` v4 (unmaintained since 2022, Bulma 0.9.x)
|
|
21
|
-
| `rbx` v2 (abandoned 2019, pins Bulma **0.7.5** plus four extensions)
|
|
18
|
+
| Source | Argument | References |
|
|
19
|
+
| ----------------------------------------------------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------ |
|
|
20
|
+
| `react-bulma-components` v4 (unmaintained since 2022, Bulma 0.9.x) | `react-bulma-components` | [`references/react-bulma-components/`](references/react-bulma-components/component-map.md) |
|
|
21
|
+
| `rbx` v2 (abandoned 2019, pins Bulma **0.7.5** plus four extensions) | `rbx` | [`references/rbx/`](references/rbx/component-map.md) |
|
|
22
|
+
| `bloomer` 0.6 (archived 2018, Bulma 0.6 era, React 16 + `create-react-class`) | `bloomer` | [`references/bloomer/`](references/bloomer/component-map.md) |
|
|
22
23
|
|
|
23
24
|
Everything below is written as `<source>`; substitute the argument from that table. The
|
|
24
25
|
reference paths follow the same split — `references/<source>/component-map.md`,
|
|
@@ -44,7 +45,10 @@ Run these steps in order. Don't hand-convert what the codemod converts automatic
|
|
|
44
45
|
Flags: `--css bulma|keep` for other stylesheet targets, `--no-deps` to leave
|
|
45
46
|
package.json alone.
|
|
46
47
|
|
|
47
|
-
3. **Install** — the codemod edits package.json but never runs a package manager
|
|
48
|
+
3. **Install** — the codemod edits package.json but never runs a package manager. Resolve the
|
|
49
|
+
retained imports first: a component with no bestax equivalent keeps a trimmed,
|
|
50
|
+
TODO-annotated import of the source library, which the manifest step has just removed — so a
|
|
51
|
+
clean install leaves those unresolvable. The report names them in a `deps` entry.
|
|
48
52
|
|
|
49
53
|
```sh
|
|
50
54
|
npm install # or pnpm/yarn
|
|
@@ -59,8 +63,8 @@ Run these steps in order. Don't hand-convert what the codemod converts automatic
|
|
|
59
63
|
documented in the per-source `references/` pages.
|
|
60
64
|
|
|
61
65
|
The report's `peer-deps` entries predict install failures: bestax-bulma needs
|
|
62
|
-
**React 18/19** (react-bulma-components also ran on 17,
|
|
63
|
-
**React 16** — upgrade react/react-dom first) and its optional Font Awesome peer wants
|
|
66
|
+
**React 18/19** (react-bulma-components also ran on 17, while rbx and bloomer peer-depended
|
|
67
|
+
on **React 16** — upgrade react/react-dom first) and its optional Font Awesome peer wants
|
|
64
68
|
**FA ≥ 6.7** (an app pinned to FA 5 either upgrades or installs with
|
|
65
69
|
`npm install --legacy-peer-deps`).
|
|
66
70
|
|
|
@@ -101,6 +105,14 @@ code per the references, or deliberately keep the old markup with `className` st
|
|
|
101
105
|
become real wrapping `<Badge>` / `<Tooltip>` components. Its `as` is universal, bestax's is
|
|
102
106
|
not. Because rbx pinned Bulma 0.7.5, you cross **two** Bulma majors — expect more visual
|
|
103
107
|
drift than the 0.9 → 1 guide alone describes.
|
|
108
|
+
- **bloomer**: every export is a flat name and most become dotted bestax compounds
|
|
109
|
+
(`CardHeaderTitle` → `Card.Header.Title`). Most of its `is*` booleans already are bestax's
|
|
110
|
+
(`isActive` becomes `active` where bestax names it so; `isFullWidth` survives only on
|
|
111
|
+
Button, Select, Table and Tabs); the work is in `isSize`/`isColor`/`isAlign` (renamed per component), the `isDisplay`/`isHidden`
|
|
112
|
+
helpers (flattened, arrays and objects included), `tag` (→ `as` where bestax has one) and
|
|
113
|
+
`render` (always a TODO). Its icons are className-based and Font Awesome 4 — the biggest
|
|
114
|
+
visual risk, see `references/bloomer/unmappables.md`. The app declared its own Bulma 0.6,
|
|
115
|
+
which the codemod bumps; there is no pinned Bulma to free.
|
|
104
116
|
|
|
105
117
|
## Rules
|
|
106
118
|
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# bloomer → bestax-bulma component map
|
|
2
|
+
|
|
3
|
+
Every bloomer export. bloomer's exports are all _flat_ names, while bestax groups the same
|
|
4
|
+
components into dotted compounds — so most rows here rename a flat identifier onto a
|
|
5
|
+
`Parent.Child` target, and the codemod imports the parent. `structural` means the codemod
|
|
6
|
+
rewrites the element's shape rather than renaming it (see [unmappables.md](unmappables.md) for
|
|
7
|
+
what each one produces). A `todo` row has no bestax counterpart — the codemod keeps the bloomer
|
|
8
|
+
import, annotated, so the app still runs while you convert it.
|
|
9
|
+
|
|
10
|
+
This table mirrors `MAPPING` in `bestax-migrate/src/sources/bloomer/mapping.ts`, which a
|
|
11
|
+
coverage test holds to bloomer's own export surface (108 exports, vendored from its
|
|
12
|
+
`src/index.ts`) in both directions.
|
|
13
|
+
|
|
14
|
+
| bloomer | bestax-bulma | status |
|
|
15
|
+
| ---------------------- | --------------------- | ------- |
|
|
16
|
+
| `Box` | `Box` | mapped |
|
|
17
|
+
| `Breadcrumb` | `Breadcrumb` | mapped |
|
|
18
|
+
| `BreadcrumbItem` | _structural_ | mapped |
|
|
19
|
+
| `Button` | `Button` | mapped |
|
|
20
|
+
| `Card` | `Card` | mapped |
|
|
21
|
+
| `CardContent` | `Card.Content` | mapped |
|
|
22
|
+
| `CardFooter` | `Card.Footer` | mapped |
|
|
23
|
+
| `CardFooterItem` | `Card.FooterItem` | mapped |
|
|
24
|
+
| `CardHeader` | `Card.Header` | mapped |
|
|
25
|
+
| `CardHeaderIcon` | `Card.Header.Icon` | mapped |
|
|
26
|
+
| `CardHeaderTitle` | `Card.Header.Title` | mapped |
|
|
27
|
+
| `CardImage` | `Card.Image` | mapped |
|
|
28
|
+
| `Checkbox` | `Checkbox` | mapped |
|
|
29
|
+
| `Column` | `Column` | mapped |
|
|
30
|
+
| `Columns` | `Columns` | mapped |
|
|
31
|
+
| `Container` | `Container` | mapped |
|
|
32
|
+
| `Content` | `Content` | mapped |
|
|
33
|
+
| `Control` | `Control` | mapped |
|
|
34
|
+
| `Delete` | `Delete` | mapped |
|
|
35
|
+
| `Dropdown` | `Dropdown` | partial |
|
|
36
|
+
| `DropdownContent` | — _(see unmappables)_ | todo |
|
|
37
|
+
| `DropdownDivider` | `Dropdown.Divider` | mapped |
|
|
38
|
+
| `DropdownItem` | `Dropdown.Item` | mapped |
|
|
39
|
+
| `DropdownMenu` | — _(see unmappables)_ | todo |
|
|
40
|
+
| `DropdownTrigger` | — _(see unmappables)_ | todo |
|
|
41
|
+
| `Field` | `Field` | mapped |
|
|
42
|
+
| `FieldBody` | `Field.Body` | mapped |
|
|
43
|
+
| `FieldLabel` | `Field.Label` | mapped |
|
|
44
|
+
| `Footer` | `Footer` | mapped |
|
|
45
|
+
| `Heading` | _structural_ | partial |
|
|
46
|
+
| `Help` | _structural_ | mapped |
|
|
47
|
+
| `Hero` | `Hero` | mapped |
|
|
48
|
+
| `HeroBody` | `Hero.Body` | mapped |
|
|
49
|
+
| `HeroFooter` | `Hero.Foot` | mapped |
|
|
50
|
+
| `HeroHeader` | `Hero.Head` | mapped |
|
|
51
|
+
| `HeroVideo` | _structural_ | mapped |
|
|
52
|
+
| `Icon` | `Icon` | partial |
|
|
53
|
+
| `Image` | `Image` | mapped |
|
|
54
|
+
| `Input` | `InputBase` | mapped |
|
|
55
|
+
| `Label` | _structural_ | mapped |
|
|
56
|
+
| `Level` | `Level` | mapped |
|
|
57
|
+
| `LevelItem` | `Level.Item` | mapped |
|
|
58
|
+
| `LevelLeft` | `Level.Left` | mapped |
|
|
59
|
+
| `LevelRight` | `Level.Right` | mapped |
|
|
60
|
+
| `Media` | `Media` | mapped |
|
|
61
|
+
| `MediaContent` | `Media.Content` | mapped |
|
|
62
|
+
| `MediaLeft` | `Media.Left` | mapped |
|
|
63
|
+
| `MediaRight` | `Media.Right` | mapped |
|
|
64
|
+
| `Menu` | `Menu` | mapped |
|
|
65
|
+
| `MenuLabel` | `Menu.Label` | mapped |
|
|
66
|
+
| `MenuLink` | `Menu.Item` | mapped |
|
|
67
|
+
| `MenuList` | `Menu.List` | mapped |
|
|
68
|
+
| `Message` | `Message` | mapped |
|
|
69
|
+
| `MessageBody` | `Message.Body` | mapped |
|
|
70
|
+
| `MessageHeader` | `Message.Header` | mapped |
|
|
71
|
+
| `Modal` | `Modal` | partial |
|
|
72
|
+
| `ModalBackground` | `Modal.Background` | mapped |
|
|
73
|
+
| `ModalCard` | `Modal.Card` | mapped |
|
|
74
|
+
| `ModalCardBody` | `Modal.Card.Body` | mapped |
|
|
75
|
+
| `ModalCardFooter` | `Modal.Card.Foot` | mapped |
|
|
76
|
+
| `ModalCardHeader` | `Modal.Card.Head` | mapped |
|
|
77
|
+
| `ModalCardTitle` | `Modal.Card.Title` | mapped |
|
|
78
|
+
| `ModalClose` | `Modal.Close` | mapped |
|
|
79
|
+
| `ModalContent` | `Modal.Content` | mapped |
|
|
80
|
+
| `Nav` | — _(see unmappables)_ | todo |
|
|
81
|
+
| `NavCenter` | — _(see unmappables)_ | todo |
|
|
82
|
+
| `NavItem` | — _(see unmappables)_ | todo |
|
|
83
|
+
| `NavLeft` | — _(see unmappables)_ | todo |
|
|
84
|
+
| `NavRight` | — _(see unmappables)_ | todo |
|
|
85
|
+
| `NavToggle` | — _(see unmappables)_ | todo |
|
|
86
|
+
| `Navbar` | `Navbar` | mapped |
|
|
87
|
+
| `NavbarBrand` | `Navbar.Brand` | mapped |
|
|
88
|
+
| `NavbarBurger` | `Navbar.Burger` | mapped |
|
|
89
|
+
| `NavbarDivider` | `Navbar.Divider` | mapped |
|
|
90
|
+
| `NavbarDropdown` | _structural_ | mapped |
|
|
91
|
+
| `NavbarEnd` | `Navbar.End` | mapped |
|
|
92
|
+
| `NavbarItem` | _structural_ | mapped |
|
|
93
|
+
| `NavbarLink` | `Navbar.Link` | mapped |
|
|
94
|
+
| `NavbarMenu` | `Navbar.Menu` | mapped |
|
|
95
|
+
| `NavbarStart` | `Navbar.Start` | mapped |
|
|
96
|
+
| `Notification` | `Notification` | mapped |
|
|
97
|
+
| `Page` | _structural_ | mapped |
|
|
98
|
+
| `PageControl` | _structural_ | mapped |
|
|
99
|
+
| `PageEllipsis` | `Pagination.Ellipsis` | mapped |
|
|
100
|
+
| `PageLink` | `Pagination.Link` | mapped |
|
|
101
|
+
| `PageList` | `Pagination.List` | mapped |
|
|
102
|
+
| `Pagination` | `Pagination` | mapped |
|
|
103
|
+
| `Panel` | `Panel` | mapped |
|
|
104
|
+
| `PanelBlock` | `Panel.Block` | mapped |
|
|
105
|
+
| `PanelHeading` | `Panel.Heading` | mapped |
|
|
106
|
+
| `PanelIcon` | `Panel.Icon` | partial |
|
|
107
|
+
| `PanelTab` | _structural_ | mapped |
|
|
108
|
+
| `PanelTabs` | `Panel.Tabs` | mapped |
|
|
109
|
+
| `Progress` | `Progress` | mapped |
|
|
110
|
+
| `Radio` | `Radio` | mapped |
|
|
111
|
+
| `Section` | `Section` | mapped |
|
|
112
|
+
| `Select` | `SelectBase` | mapped |
|
|
113
|
+
| `Subtitle` | `SubTitle` | mapped |
|
|
114
|
+
| `Tab` | `Tabs.Item` | mapped |
|
|
115
|
+
| `TabLink` | _structural_ | mapped |
|
|
116
|
+
| `TabList` | `Tabs.List` | mapped |
|
|
117
|
+
| `Table` | `Table` | mapped |
|
|
118
|
+
| `Tabs` | `Tabs` | mapped |
|
|
119
|
+
| `Tag` | `Tag` | mapped |
|
|
120
|
+
| `TextArea` | `TextAreaBase` | mapped |
|
|
121
|
+
| `Tile` | — _(see unmappables)_ | todo |
|
|
122
|
+
| `Title` | `Title` | mapped |
|
|
123
|
+
| `withHelpersModifiers` | — _(see unmappables)_ | todo |
|
|
124
|
+
|
|
125
|
+
## The renames worth memorising
|
|
126
|
+
|
|
127
|
+
The flat-to-dotted pattern is regular — `CardHeaderTitle` → `Card.Header.Title`,
|
|
128
|
+
`ModalCardBody` → `Modal.Card.Body`, `NavbarBurger` → `Navbar.Burger` — with a handful of names
|
|
129
|
+
that change along the way:
|
|
130
|
+
|
|
131
|
+
| bloomer | bestax-bulma | why |
|
|
132
|
+
| ----------------- | --------------------- | ----------------------------------------------------------- |
|
|
133
|
+
| `Subtitle` | `SubTitle` | bestax's casing |
|
|
134
|
+
| `HeroHeader` | `Hero.Head` | bestax follows Bulma's `hero-head` / `hero-foot` |
|
|
135
|
+
| `HeroFooter` | `Hero.Foot` | |
|
|
136
|
+
| `ModalCardHeader` | `Modal.Card.Head` | same, for `modal-card-head` / `modal-card-foot` |
|
|
137
|
+
| `ModalCardFooter` | `Modal.Card.Foot` | |
|
|
138
|
+
| `CardFooterItem` | `Card.FooterItem` | one component in bestax, not a child of `Card.Footer` |
|
|
139
|
+
| `MenuLink` | `Menu.Item` | bestax's item renders the `<a>` |
|
|
140
|
+
| `FieldLabel` | `Field.Label` | and `FieldBody` → `Field.Body` |
|
|
141
|
+
| `Tab` | `Tabs.Item` | the plain `<li>`; bestax's `Tabs.Tab` is the controlled API |
|
|
142
|
+
| `PageLink` | `Pagination.Link` | `isCurrent` becomes `active` |
|
|
143
|
+
| `NavbarDropdown` | `Navbar.DropdownMenu` | bestax's `Navbar.Dropdown` is the container — see below |
|
|
144
|
+
|
|
145
|
+
## Value-chosen targets
|
|
146
|
+
|
|
147
|
+
Some targets depend on a prop or a child, so the codemod picks them element by element:
|
|
148
|
+
|
|
149
|
+
| bloomer | becomes | decided by |
|
|
150
|
+
| ---------------------------------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
|
|
151
|
+
| `PageControl` | `Pagination.Previous` / `Pagination.Next` | `isNext` (bloomer's default is previous) |
|
|
152
|
+
| `NavbarItem` | `Navbar.Item` / `Navbar.Dropdown` | `hasDropdown` |
|
|
153
|
+
| `Page` | _folded into its child_ / `<li>` | whether the child is a `PageLink`/`PageEllipsis`; attributes on the Page move onto the link, with a `component:Page` note |
|
|
154
|
+
| `PanelBlock` | `Panel.Block` / `<div class="panel-block">` | `href` — bestax's block is always an `<a>` |
|
|
155
|
+
| `MenuLink` in a literal `<li>` | `Menu.Item`, the `<li>` folded away | bestax's item renders its own `<li>` |
|
|
156
|
+
| `Breadcrumb` around a literal `<ul>` | `Breadcrumb`, the `<ul>` folded away | bestax's breadcrumb renders its own `<ul>` |
|
|
157
|
+
| `Icon`, `PanelIcon` | `name`/`library`/`variant` / an `<i>` child | whether the icon classes are FA5/6 or MDI |
|
|
158
|
+
| `Help`, `Label`, `Heading` | `<p class="help">`, `<label class="label">`, `<p class="heading">` | always plain markup |
|
|
159
|
+
| `BreadcrumbItem`, `PanelTab`, `TabLink`, `HeroVideo` | `<li>`, `<a>`, `<a>`, `<div class="hero-video">` | always plain markup |
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# bloomer → bestax-bulma prop map
|
|
2
|
+
|
|
3
|
+
Most of bloomer's boolean modifiers are already bestax's names — `isLoading`, `isOutlined`,
|
|
4
|
+
`isInverted`, `isStatic`, `isHovered`, `isFocused`, `isBordered`, `isStriped`, `isNarrow`,
|
|
5
|
+
`isMultiline`, `isVCentered`, `isMobile`, … pass through untouched. The exceptions are in
|
|
6
|
+
the tables below: `isActive` becomes `active` on the components whose bestax counterpart
|
|
7
|
+
names it that way, `isFullWidth` survives only where bestax declares it, and a few
|
|
8
|
+
(`Input isActive`, `NavbarLink isActive`, `PageLink isActive`) have no counterpart and become
|
|
9
|
+
the Bulma class in `className` instead (see the end of this page). What else changes is the value-carrying props, the helper props every component
|
|
10
|
+
inherited from `withHelpersModifiers`, and the two props bestax spells differently on every
|
|
11
|
+
component.
|
|
12
|
+
|
|
13
|
+
## Universal helper props
|
|
14
|
+
|
|
15
|
+
bloomer's `withHelpersModifiers` mixed these into every component.
|
|
16
|
+
|
|
17
|
+
| bloomer | bestax-bulma | note |
|
|
18
|
+
| --------------------------- | -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
19
|
+
| `hasTextAlign="centered"` | `textAlign="centered"` | `left` / `right` / `centered` — same union |
|
|
20
|
+
| `hasTextColor="grey-light"` | `textColor="grey-light"`, or `className="has-text-grey-light"` | `textColor` is declared per component, not by the helper hook, so it carries over on the ~48 targets that have it and becomes the Bulma class on the rest (`Tag`, `Table`, `Hero`, `Menu`, `Breadcrumb`, `Panel`, `Icon`, `Progress`, the form controls); every Bulma 0.6 colour and shade works but `white-ter`/`white-bis` |
|
|
21
|
+
| `isPulled="right"` | `float="right"` | |
|
|
22
|
+
| `isClearfix` | `clearfix` | |
|
|
23
|
+
| `isOverlay` | `overlay` | |
|
|
24
|
+
| `isUnselectable` | `interaction="unselectable"` | |
|
|
25
|
+
| `isMarginless` | `m="0"` | bestax expresses the `is-*less` helpers as spacing |
|
|
26
|
+
| `isPaddingless` | `p="0"` | |
|
|
27
|
+
| `isFullWidth` | `isFullWidth` | on Button, Select, Table, Tabs; a TODO elsewhere |
|
|
28
|
+
| `isDisplay`, `isHidden` | `display*`, `visibility*` | flattened — see below |
|
|
29
|
+
| `tag` | `as` | where bestax declares one — see below |
|
|
30
|
+
| `render` | — | always a TODO |
|
|
31
|
+
|
|
32
|
+
## `isDisplay` and `isHidden`
|
|
33
|
+
|
|
34
|
+
Both take three shapes in bloomer; all three flatten onto bestax's per-viewport props. bestax
|
|
35
|
+
declares every Bulma viewport, including `touch` and the `-only` ones, so nothing is lost:
|
|
36
|
+
|
|
37
|
+
| bloomer | bestax-bulma |
|
|
38
|
+
| -------------------------------------------------------------- | ------------------------------------------------------------- |
|
|
39
|
+
| `isDisplay="flex"` | `display="flex"` |
|
|
40
|
+
| `isDisplay="flex-tablet-only"` | `displayTabletOnly="flex"` |
|
|
41
|
+
| `isDisplay={['inline-block', 'flex-desktop']}` | `display="inline-block" displayDesktop="flex"` |
|
|
42
|
+
| `isDisplay={{ flex: ['default', 'tablet'], block: 'mobile' }}` | `display="flex" displayTablet="flex" displayMobile="block"` |
|
|
43
|
+
| `isHidden` | `visibility="hidden"` |
|
|
44
|
+
| `isHidden="touch"` | `visibilityTouch="hidden"` |
|
|
45
|
+
| `isHidden={['mobile', 'widescreen-only']}` | `visibilityMobile="hidden" visibilityWidescreenOnly="hidden"` |
|
|
46
|
+
|
|
47
|
+
Two entries that land on the same prop, a dynamic value, or a viewport bestax does not know get
|
|
48
|
+
a TODO; the bloomer prop is always removed, because bestax has no `isDisplay`/`isHidden` and a
|
|
49
|
+
leftover would be a type error rather than a no-op.
|
|
50
|
+
|
|
51
|
+
## Value props
|
|
52
|
+
|
|
53
|
+
| bloomer | bestax-bulma |
|
|
54
|
+
| ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
55
|
+
| `isColor="primary"` | `color="primary"` (every component that had it) |
|
|
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}` | `size={3}` — bestax accepts the numbers 1–6 |
|
|
58
|
+
| `Subtitle isSize={4}` | `SubTitle size={4} as="h2"` — bloomer's default was an `<h2>`, bestax's is an `<h1>`, so the level is kept |
|
|
59
|
+
| `Image isSize="128x128"` | `size="128x128"` |
|
|
60
|
+
| `Image isRatio="16:9"` | `size="16by9"` (`square`→`square`, `1:1`→`1by1`, `4:3`→`4by3`, `3:2`→`3by2`, `2:1`→`2by1`) |
|
|
61
|
+
| `Breadcrumb isAlign` | `alignment` |
|
|
62
|
+
| `Breadcrumb hasSeparator` | `separator` |
|
|
63
|
+
| `Tabs isAlign` | `align`; `isBoxed` → `boxed`, `isToggle` → `toggle` |
|
|
64
|
+
| `Pagination isAlign` | `align` (`"left"` is the default and is dropped) |
|
|
65
|
+
| `Dropdown isAlign="right"` | `right`; `isHoverable` → `hoverable` |
|
|
66
|
+
| `Icon isAlign="left"` | `className="is-left"` (bestax's Icon has no align prop) |
|
|
67
|
+
| `Icon className="fas fa-spinner fa-spin"` | `name="spinner" library="fa" variant="solid" features="fa-spin"` — modifier classes become `features` |
|
|
68
|
+
| `PanelIcon className="fas fa-book"` | `Panel.Icon name="book" library="fa" variant="solid"` — same className API as `Icon` |
|
|
69
|
+
| `Button isLink` | `color="link"` (a TODO if `isColor` is also set) |
|
|
70
|
+
| `Hero isFullHeight` | `size="fullheight"` |
|
|
71
|
+
| `Container isFluid` | `fluid` |
|
|
72
|
+
| `Navbar isTransparent` | `transparent` |
|
|
73
|
+
| `Field isGrouped`, `isHorizontal` | `grouped` (same `boolean \| 'centered' \| 'right'`), `horizontal` |
|
|
74
|
+
| `FieldLabel isNormal` | `size="normal"` |
|
|
75
|
+
| `Control hasIcons` | `hasIconsLeft` / `hasIconsRight` (`true` sets both; an array sets each) |
|
|
76
|
+
| `PageLink isCurrent` | `active` |
|
|
77
|
+
| `isActive` on Dropdown, DropdownItem, MenuLink, Modal, NavbarBurger, NavbarMenu, NavbarItem, PanelBlock, Tab | `active` |
|
|
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
|
+
|
|
80
|
+
## Column sizes
|
|
81
|
+
|
|
82
|
+
| bloomer | bestax-bulma |
|
|
83
|
+
| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
84
|
+
| `isSize={4} isOffset={2}` | `size={4} offset={2}` |
|
|
85
|
+
| `isSize="1/2"` | `size="half"` (`1/3`→`one-third`, `1/4`→`one-quarter`, `2/3`→`two-thirds`, `3/4`→`three-quarters`, `full`→`full`) |
|
|
86
|
+
| `isSize="narrow"` | `isNarrow` |
|
|
87
|
+
| `isSize={{ default: 'full', mobile: 8, tablet: '2/3' }}` | `size="full" sizeMobile={8} sizeTablet="two-thirds"` |
|
|
88
|
+
| `isSize={{ touch: 'narrow' }}` | `isNarrowTouch` — bestax has `isNarrowTouch` but no `sizeTouch`/`offsetTouch`, which become TODOs |
|
|
89
|
+
|
|
90
|
+
## `tag` → `as`
|
|
91
|
+
|
|
92
|
+
bloomer put `tag` on nearly every component; bestax declares `as` on a subset, several of them
|
|
93
|
+
narrowed to a literal union, so a value outside the union is a type error you can see rather
|
|
94
|
+
than a silent rewrite. The components whose `tag` becomes `as`:
|
|
95
|
+
|
|
96
|
+
`Button`, `Image`, `Title`, `Subtitle`, `Footer`, `Media`, `MediaLeft`, `LevelItem`, `Control`,
|
|
97
|
+
`DropdownItem`,
|
|
98
|
+
`MenuLink`, `NavbarItem`, `NavbarLink`.
|
|
99
|
+
|
|
100
|
+
Everywhere else `tag` is left in place with a TODO. On the components that become plain markup
|
|
101
|
+
(`Help`, `Label`, `Heading`, `BreadcrumbItem`, `PanelTab`, `TabLink`, `Page`, `HeroVideo`) a
|
|
102
|
+
literal `tag` is honoured — `<Help tag="span">` becomes `<span className="help">`.
|
|
103
|
+
|
|
104
|
+
bloomer's `Button` and `Image` never took `tag` at all. Seven bloomer components — `Button`,
|
|
105
|
+
`Delete`, `LevelItem`, `DropdownItem`, `NavbarItem`, `PanelBlock`, `CardFooterItem` — rendered
|
|
106
|
+
an `<a>` whenever `href` was set, whatever `tag` said, and a `<div>` (or their default tag)
|
|
107
|
+
otherwise; the rest (`MenuLink`, `PageControl`, `Dropdown`, …) rendered their `tag` regardless.
|
|
108
|
+
The codemod keeps that: `Button` and `LevelItem` gain `as="a"` beside a literal `href`; a `tag`
|
|
109
|
+
next to a literal `href` is dropped on the switching targets that already render an anchor
|
|
110
|
+
(`Navbar.Item`, `Dropdown.Item`, `Panel.Block`); a `NavbarItem` or `DropdownItem` with neither
|
|
111
|
+
`href` nor `tag` gains `as="div"`, because bestax's `Navbar.Item` and `Dropdown.Item` default
|
|
112
|
+
to an `<a>`. A dynamic `href={expr}` was a runtime decision bloomer made and bestax cannot, so it
|
|
113
|
+
is flagged (`prop:href`) rather than guessed. bestax's `Panel.Block` is always an `<a>`, so only
|
|
114
|
+
a `PanelBlock` with `href` becomes one — the rest stay the plain `<div class="panel-block">` (or
|
|
115
|
+
the `tag` you gave) that bloomer rendered.
|
|
116
|
+
|
|
117
|
+
## Helper props on parts that take none
|
|
118
|
+
|
|
119
|
+
A few bestax parts extend only React's HTML attributes and take no Bulma helper props at all:
|
|
120
|
+
`Pagination.Previous`/`Next`/`Ellipsis`, `Navbar.Dropdown`/`DropdownMenu`/`Divider`,
|
|
121
|
+
`Panel.Heading`/`Tabs`/`Block`, `Tabs.List`/`Item`, `Message.Header`/`Body` and the `Modal`
|
|
122
|
+
parts. A bloomer helper on one of those becomes the Bulma class in `className` — except on
|
|
123
|
+
`Navbar.Divider`, `Pagination.Ellipsis` and `Dropdown.Divider`, which write their own className
|
|
124
|
+
last or take no props at all: there the helper is named in a TODO instead, and an element
|
|
125
|
+
carrying a spread is left as bloomer's. Otherwise it is the Bulma class in `className` (`is-pulled-right`,
|
|
126
|
+
`m-0`, `is-hidden-mobile`, …), since Bulma v1 still ships every one of them; only a dynamic
|
|
127
|
+
value is flagged. The same conversion covers the modifiers bestax has no prop for anywhere —
|
|
128
|
+
`Hero isBold`, `Media isSize`, `Subtitle isSpaced`, `Input isActive`, `PanelBlock isWrapped`,
|
|
129
|
+
`LevelItem isFlexible`, `NavbarDivider isBoxed`, the pagination parts' `isActive`/`isFocused`.
|
|
130
|
+
|
|
131
|
+
## Refs
|
|
132
|
+
|
|
133
|
+
bloomer forwarded no refs. bestax forwards a ref from the form controls and from `Button`,
|
|
134
|
+
`LinkButton`, `Modal`, `Dropdown`, `Navbar` (plus `Navbar.Burger` and `Navbar.Link`), `Dialog`,
|
|
135
|
+
`Sidebar`, `Toast` and `Carousel` — pass `ref` directly on those.
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# Recipes for every TODO(bestax-migrate) the bloomer codemod leaves
|
|
2
|
+
|
|
3
|
+
Ordered by how often they appear when the codemod runs over bloomer's own documentation.
|
|
4
|
+
Resolve the comment, then delete it. Never silence a TODO without converting the code.
|
|
5
|
+
|
|
6
|
+
## `component:Icon`, `component:PanelIcon` — Font Awesome 4 classes
|
|
7
|
+
|
|
8
|
+
bloomer's `Icon` put the icon-font classes on its own `className`, and its era was Font Awesome 4. Classes the parser can read — Font Awesome 5/6 (`fas fa-home`, `fa-solid fa-home`) and MDI
|
|
9
|
+
(`mdi mdi-account`) — become bestax's props automatically:
|
|
10
|
+
|
|
11
|
+
```jsx
|
|
12
|
+
<Icon className="fas fa-home" isSize="large" />
|
|
13
|
+
<Icon name="home" library="fa" variant="solid" size="large" />
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Modifier classes the library documents (`fa-spin`, `fa-lg`, `mdi-24px`) become bestax's
|
|
17
|
+
`features`. Anything else — FA4's `fa fa-home` above all, or an app's own class beside the icon
|
|
18
|
+
— is moved onto an `<i>` child, which renders exactly what bloomer rendered, and flagged: bestax's optional Font Awesome peer is **6.7+**, where
|
|
19
|
+
many v4 names changed and brand icons moved to `variant="brands"`. Either keep FA4 loaded, or
|
|
20
|
+
convert to the prop form:
|
|
21
|
+
|
|
22
|
+
```jsx
|
|
23
|
+
<Icon><i className="fa fa-github" aria-hidden="true" /></Icon>
|
|
24
|
+
<Icon name="github" library="fa" variant="brands" />
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`library` is `fa` | `mdi` | `ion` | `material-icons` | `material-symbols`. `PanelIcon` has the
|
|
28
|
+
same `className` API and converts the same way. An `Icon` with no `className` and no children
|
|
29
|
+
is flagged too — it gets an empty `<i>` child so it compiles until you set a `name` or a child —
|
|
30
|
+
and so is a `className` that is not a string (`prop:className`). An `Icon` written with children
|
|
31
|
+
is flagged as well: bloomer never rendered them — beside a `className` they are removed (the
|
|
32
|
+
classes win), without one they are kept and bestax will render them.
|
|
33
|
+
|
|
34
|
+
## `component:Nav` — Bulma 0.4's nav
|
|
35
|
+
|
|
36
|
+
`Nav`, `NavLeft`, `NavCenter`, `NavRight`, `NavToggle` and `NavItem` (`component:NavLeft`,
|
|
37
|
+
`component:NavCenter`, `component:NavRight`, `component:NavToggle`, `component:NavItem`) are
|
|
38
|
+
Bulma 0.4's `.nav`, which Bulma removed in 0.5 — bloomer kept the components, but no stylesheet
|
|
39
|
+
you can install today styles them. Rebuild on `Navbar`:
|
|
40
|
+
|
|
41
|
+
```jsx
|
|
42
|
+
<Nav><NavLeft><NavItem isActive>Home</NavItem></NavLeft><NavToggle /></Nav>
|
|
43
|
+
|
|
44
|
+
<Navbar>
|
|
45
|
+
<Navbar.Brand><Navbar.Burger /></Navbar.Brand>
|
|
46
|
+
<Navbar.Menu><Navbar.Start><Navbar.Item active>Home</Navbar.Item></Navbar.Start></Navbar.Menu>
|
|
47
|
+
</Navbar>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## `component:Tile` — Bulma v1 removed tiles
|
|
51
|
+
|
|
52
|
+
Use Grid and Cell. `Tile isAncestor` becomes `<Grid>`, `isParent`/`isChild` become `<Cell>`,
|
|
53
|
+
and `isSize={n}` becomes a column span:
|
|
54
|
+
|
|
55
|
+
```jsx
|
|
56
|
+
<Tile isAncestor><Tile isParent isSize={4}><Tile isChild>x</Tile></Tile></Tile>
|
|
57
|
+
<Grid><Cell colSpan={4}>x</Cell></Grid>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## `component:Modal` — what carries over
|
|
61
|
+
|
|
62
|
+
bloomer's `Modal` was an inert shell: `isActive` toggled the class and nothing else. bestax's
|
|
63
|
+
`Modal` closes on Escape (calling `onClose`), locks body scroll, and traps focus **by default**,
|
|
64
|
+
and renders inline unless `portal` is set. So every conversion changes behaviour, and every one
|
|
65
|
+
is flagged. Pass `onClose` to get the close-on-Escape and background behaviour:
|
|
66
|
+
|
|
67
|
+
```jsx
|
|
68
|
+
<Modal active={open} onClose={() => setOpen(false)}>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
or keep bloomer's inert behaviour with `closeOnEscape={false} lockScroll={false}`. Add
|
|
72
|
+
`portal` if the modal must escape a transformed ancestor.
|
|
73
|
+
|
|
74
|
+
## `component:Dropdown` and its parts
|
|
75
|
+
|
|
76
|
+
bestax's `Dropdown` takes a `label` and renders its own trigger and menu, so bloomer's
|
|
77
|
+
`DropdownTrigger`, `DropdownMenu` and `DropdownContent` have nothing to become
|
|
78
|
+
(`component:DropdownTrigger`, `component:DropdownMenu`, `component:DropdownContent`). Keep the
|
|
79
|
+
`<DropdownItem>`s, which become `<Dropdown.Item>`:
|
|
80
|
+
|
|
81
|
+
```jsx
|
|
82
|
+
<Dropdown isActive isAlign="right">
|
|
83
|
+
<DropdownTrigger><Button>Open</Button></DropdownTrigger>
|
|
84
|
+
<DropdownMenu><DropdownContent>
|
|
85
|
+
<DropdownItem href="/a">A</DropdownItem>
|
|
86
|
+
</DropdownContent></DropdownMenu>
|
|
87
|
+
</Dropdown>
|
|
88
|
+
|
|
89
|
+
<Dropdown label="Open" active right>
|
|
90
|
+
<Dropdown.Item onClick={() => navigate('/a')}>A</Dropdown.Item>
|
|
91
|
+
</Dropdown>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
bestax's `Dropdown.Item` declares no `href` (`prop:href` on a `DropdownItem`): navigate in
|
|
95
|
+
`onClick`, or put an `<a>` inside the item.
|
|
96
|
+
`isHoverable` → `hoverable`, `isActive` → `active` carry over on the `Dropdown` itself.
|
|
97
|
+
|
|
98
|
+
## `prop:tag` — polymorphism
|
|
99
|
+
|
|
100
|
+
bestax declares `as` on only some components (the list is in [prop-map.md](prop-map.md)).
|
|
101
|
+
Elsewhere, render the element you wanted directly, or move the bestax component inside it:
|
|
102
|
+
|
|
103
|
+
```jsx
|
|
104
|
+
<Box tag="section">…</Box>
|
|
105
|
+
<section><Box>…</Box></section>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
A dynamic `tag` on a component that becomes plain markup is flagged the same way — the plain
|
|
109
|
+
element takes bloomer's default tag.
|
|
110
|
+
|
|
111
|
+
## `prop:render` — the render prop
|
|
112
|
+
|
|
113
|
+
bloomer's `render` handed the computed props (`className` included) to your own renderer:
|
|
114
|
+
|
|
115
|
+
```jsx
|
|
116
|
+
<Button isColor="info" render={props => <MyButton {...props} />} />
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
bestax has no render-prop escape hatch. Render the bestax component and put your element inside
|
|
120
|
+
it, or — if you need the classes on your own element — call `useBulmaClasses` in it:
|
|
121
|
+
|
|
122
|
+
```jsx
|
|
123
|
+
<Button color="info" as={MyButton} />
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
`Button`, `Navbar.Item`, `Navbar.Link` and `Menu.Item` take `as` as a custom component, which
|
|
127
|
+
covers the common "render as a router link" case.
|
|
128
|
+
|
|
129
|
+
## `component:Heading` — Bulma v1 dropped `.heading`
|
|
130
|
+
|
|
131
|
+
bloomer's `Heading` is Bulma's small-caps label. It becomes the plain `<p className="heading">`
|
|
132
|
+
bloomer rendered, but Bulma v1 no longer ships styles for that class, so restyle it:
|
|
133
|
+
|
|
134
|
+
```jsx
|
|
135
|
+
<Heading>Label</Heading>
|
|
136
|
+
<Title as="p" size={6} textTransform="uppercase" textWeight="semibold">Label</Title>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## `prop:isFullWidth` — not a universal helper in bestax
|
|
140
|
+
|
|
141
|
+
bloomer accepted `isFullWidth` on everything; Bulma's `is-fullwidth` only means something on a
|
|
142
|
+
few elements, and bestax declares `isFullWidth` on exactly those — `Button`, `Select`, `Table`,
|
|
143
|
+
`Tabs` — where it passes through. Elsewhere, drop it, or add `className="is-fullwidth"` if your
|
|
144
|
+
own CSS styled the class.
|
|
145
|
+
|
|
146
|
+
## Modifiers bestax has no prop for — converted to classes
|
|
147
|
+
|
|
148
|
+
Bulma v1 still ships every one of these, so the codemod writes the class into `className`
|
|
149
|
+
instead of leaving a TODO: `Hero isBold` → `className="is-bold"`, `isHalfHeight` →
|
|
150
|
+
`is-halfheight`, `Media isSize="large"` → `is-large`, `Subtitle isSpaced` → `is-spaced`,
|
|
151
|
+
`Input isActive` → `is-active`, `NavbarLink isActive` → `is-active`, `PageLink`/`PageControl`/
|
|
152
|
+
`PageEllipsis` `isActive`/`isFocused`, `PanelBlock isWrapped` → `is-wrapped`, `LevelItem
|
|
153
|
+
isFlexible` → `is-flexible`, `NavbarDropdown`/`NavbarDivider` `isBoxed` → `is-boxed`. The same
|
|
154
|
+
goes for a universal helper on a part that takes no helper props (`Pagination.Previous`/`Next`/
|
|
155
|
+
`Ellipsis`, `Navbar.Dropdown`/`DropdownMenu`/`Divider`, `Panel.Heading`/`Tabs`/`Block`,
|
|
156
|
+
`Tabs.List`/`Item`, `Message.Header`/`Body`, the `Modal` parts): `isPulled="right"` →
|
|
157
|
+
`is-pulled-right`, `isMarginless` → `m-0`, `isHidden="mobile"` → `is-hidden-mobile`. A dynamic
|
|
158
|
+
value, or a dynamic `className` the class cannot be spliced into, is flagged with the class to add.
|
|
159
|
+
|
|
160
|
+
## Props with no counterpart
|
|
161
|
+
|
|
162
|
+
Each of these is left in place with a TODO:
|
|
163
|
+
|
|
164
|
+
| prop | on | what to do |
|
|
165
|
+
| ------------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
|
|
166
|
+
| `isHoverable` | `NavbarItem` without `hasDropdown` | move to the `Navbar.Dropdown`, or `className="is-hoverable"` |
|
|
167
|
+
| `hasAddons="fullwidth"` | `Field` | `hasAddons` plus `className="has-addons-fullwidth"` |
|
|
168
|
+
| `isAlign` | `TabList` | set `align` on the `<Tabs>` — Bulma aligns the container |
|
|
169
|
+
| `isGrid` | `Columns` | Bulma removed `columns.is-grid` in 0.5; use `isMultiline` with sized columns, or `Grid` |
|
|
170
|
+
| `href` | `CardFooterItem`, `CardHeaderIcon`, `Delete`, `DropdownItem` | put an `<a>` inside, or handle it in `onClick` |
|
|
171
|
+
| `href={expr}` (dynamic) | `Button`, `LevelItem` and the other components that switched to an `<a>` on `href` | bloomer decided the element at runtime; set `as` conditionally by hand |
|
|
172
|
+
| `href` | `NavbarItem hasDropdown` | bestax's `Navbar.Dropdown` is the container; put the `href` on the `Navbar.Link` inside |
|
|
173
|
+
| `isRatio` beside `isSize` | `Image` | bestax's one `size` took the fixed size; restore the ratio if that was the point |
|
|
174
|
+
|
|
175
|
+
## `component:MenuLink`, `component:Breadcrumb`, `component:Page` — lists bestax renders itself
|
|
176
|
+
|
|
177
|
+
bestax's `Menu.Item` renders its own `<li><a>`, its `Breadcrumb` its own `<ul>`, and its
|
|
178
|
+
`Pagination.Link`/`Pagination.Ellipsis` their own `<li>`. bloomer's docs wrote those elements by
|
|
179
|
+
hand, so the codemod folds a literal `<li>` around a `MenuLink`, a literal `<ul>` inside a
|
|
180
|
+
`Breadcrumb`, and a `Page` around a single link away — carrying their attributes. It flags the
|
|
181
|
+
shapes it cannot fold: a `MenuLink` sharing its `<li>` with other content, a `<ul>` carrying
|
|
182
|
+
attributes, and a `Page` whose link sits in an expression or beside siblings — remove the wrapper
|
|
183
|
+
by hand, or the lists nest.
|
|
184
|
+
|
|
185
|
+
## `prop:isLink` — beside `isColor`
|
|
186
|
+
|
|
187
|
+
`isLink` is Bulma's `is-link` colour. Alone it becomes `color="link"`; beside an `isColor` there
|
|
188
|
+
are two colours for bestax's one `color` prop — pick one.
|
|
189
|
+
|
|
190
|
+
## `prop:isDisplay`, `prop:isHidden`, `prop:isSize`, `prop:isOffset` — dynamic helper values
|
|
191
|
+
|
|
192
|
+
The three-shape helpers flatten only from literals. A dynamic value is dropped (bestax has no
|
|
193
|
+
prop of that name, so leaving it would be a type error) and flagged; set the matching bestax
|
|
194
|
+
prop conditionally:
|
|
195
|
+
|
|
196
|
+
```jsx
|
|
197
|
+
<Box isHidden={collapsed} />
|
|
198
|
+
<Box visibility={collapsed ? 'hidden' : undefined} />
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
`Column`'s `isSize`/`isOffset` follow the same rule, and a `touch` key has no `sizeTouch`
|
|
202
|
+
counterpart in bestax (only `isNarrowTouch`) — Bulma keeps the `is-*-touch` classes, so use
|
|
203
|
+
`className`.
|
|
204
|
+
|
|
205
|
+
## `prop:hasTextColor="white-ter"` / `"white-bis"`
|
|
206
|
+
|
|
207
|
+
Two Bulma 0.6 shades bestax has no colour for. Use `white`, or a custom class. Every other colour
|
|
208
|
+
and shade of that era exists in bestax verbatim.
|
|
209
|
+
|
|
210
|
+
## `value-reference` — a component used as a value
|
|
211
|
+
|
|
212
|
+
`const Wrapped = Box` and `{ Subtitle }` are rewritten to the bestax binding (`Hero.Foot`,
|
|
213
|
+
`SubTitle`) when the target is a plain rename, and `export { Subtitle }` becomes
|
|
214
|
+
`export { SubTitle as Subtitle }` so the public name survives. A re-export of a component whose
|
|
215
|
+
bestax counterpart is a member of a compound (`export { CardHeader }` → `Card.Header`) cannot be
|
|
216
|
+
expressed and is flagged; so is a barrel `export { X } from 'bloomer'` (`imports`) and a
|
|
217
|
+
namespace import used as a plain value (`const { Box } = B`), through which nothing was
|
|
218
|
+
migrated. A retained component (`Tile`, the `Nav` family,
|
|
219
|
+
`withHelpersModifiers`) used as a value keeps the bloomer import with this flag: migrate the
|
|
220
|
+
usage by hand. `withHelpersModifiers` in particular has nothing to become — every bestax
|
|
221
|
+
component already takes the helper props, and a custom component gets them from
|
|
222
|
+
`useBulmaClasses`.
|
|
223
|
+
|
|
224
|
+
## `imports` — a bloomer import the codemod left alone
|
|
225
|
+
|
|
226
|
+
A default import (`import Bloomer from 'bloomer'`) never worked — bloomer has no default
|
|
227
|
+
export — and a deep import (`bloomer/lib/elements/Box`) reaches compiled internals the mapping
|
|
228
|
+
does not know. Convert either to a named import from `'bloomer'` and re-run the codemod.
|
|
229
|
+
|
|
230
|
+
## `plain-element` — helper props on markup that became plain HTML
|
|
231
|
+
|
|
232
|
+
When a component becomes plain markup (`Help`, `Label`, `PanelTab`, …), bloomer's helper props
|
|
233
|
+
on it have no home and are dropped with this flag. Re-apply them as classes
|
|
234
|
+
(`className="is-pulled-right"`), or wrap the element in a bestax `Box`/`Block` that takes them.
|
|
235
|
+
|
|
236
|
+
## Dynamic values
|
|
237
|
+
|
|
238
|
+
Any prop whose value the codemod cannot read — `isColor={c}`, `isNext={n}`, `hasIcons={sides}`,
|
|
239
|
+
`tag={t}`, `isTransparent={t}`, `isFullHeight={f}`, `isNormal={n}` — is either renamed as-is (when the rename is unconditional) or flagged with the
|
|
240
|
+
specific prop to set. The comment names it.
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# Stylesheets: pre-1 Bulma → Bulma v1 + bestax
|
|
2
2
|
|
|
3
3
|
Every library `bestax-migrate` migrates from is pinned to a pre-1 Bulma: react-bulma-components
|
|
4
|
-
to 0.9.x, rbx to 0.7.5
|
|
4
|
+
to 0.9.x, rbx to 0.7.5, and a bloomer app to whichever 0.6 it installed itself. bestax-bulma
|
|
5
|
+
targets Bulma v1. The codemod automates most of that
|
|
5
6
|
stylesheet layer; this reference explains what it did and how to finish what it flagged.
|
|
6
7
|
|
|
7
|
-
Coming from rbx you are crossing **two** Bulma majors rather than one, so expect more
|
|
8
|
-
drift than the 0.9 → 1 notes below describe on their own.
|
|
8
|
+
Coming from rbx or bloomer you are crossing **two** Bulma majors rather than one, so expect more
|
|
9
|
+
visual drift than the 0.9 → 1 notes below describe on their own.
|
|
9
10
|
|
|
10
11
|
## What the codemod already did (default `--css bestax`)
|
|
11
12
|
|
|
@@ -15,7 +15,9 @@ FontAwesome component form, which carries no readable name.
|
|
|
15
15
|
|
|
16
16
|
`library` is `fa` | `mdi` | `ion` | `material-icons` | `material-symbols`; `variant` is the style
|
|
17
17
|
(`solid`, `regular`, `brands`, …). Icon-font children the parser _can_ read
|
|
18
|
-
(`<i className="fas fa-home" />`) are converted automatically
|
|
18
|
+
(`<i className="fas fa-home" />`) are converted automatically, with modifier classes such as
|
|
19
|
+
`fa-spin` carried as bestax's `features`; a child that also carries an app class of its own is
|
|
20
|
+
kept and flagged instead.
|
|
19
21
|
|
|
20
22
|
## `component:Tile` — Bulma v1 removed tiles
|
|
21
23
|
|