create-bestax 4.2.5 → 4.2.7
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-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/prop-map.md +37 -0
- package/templates/skills/bestax-migrate/references/rbx/unmappables.md +23 -21
- package/templates/skills/bestax-migrate/references/react-bulma-components/component-map.md +1 -1
- package/templates/skills/bestax-migrate/references/react-bulma-components/prop-map.md +1 -1
- package/templates/skills/bestax-migrate/references/react-bulma-components/unmappables.md +36 -6
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.7",
|
|
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.0"
|
|
42
43
|
},
|
|
43
44
|
"devDependencies": {
|
|
44
45
|
"@jest/globals": "^30.0.0",
|
|
@@ -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
|
|
|
@@ -114,3 +114,40 @@ wrong:
|
|
|
114
114
|
- Several of the accepted props are **narrow literal unions**, so `as={SomeComponent}` still
|
|
115
115
|
fails to typecheck even where `as` is allowed — which is deliberate: a visible type error
|
|
116
116
|
beats a silent rewrite.
|
|
117
|
+
|
|
118
|
+
## Refs
|
|
119
|
+
|
|
120
|
+
rbx reaches a component's rendered element with `innerRef`. bestax uses a plain forwarded
|
|
121
|
+
`ref` on the roots that support one, so the codemod renames the prop:
|
|
122
|
+
|
|
123
|
+
| rbx | bestax-bulma | note |
|
|
124
|
+
| ----------------------------------------------------- | ------------ | ------------------------------------------- |
|
|
125
|
+
| `innerRef` on `Button`, `Dropdown`, `Modal`, `Navbar` | `ref` | same node — each root's own element |
|
|
126
|
+
| `innerRef` on `Navbar.Burger`, `Navbar.Link` | `ref` | these two sub-components forward one too |
|
|
127
|
+
| `innerRef` on `Navbar.Item` **with `dropdown`** | `ref` | that one becomes bestax's `Navbar.Dropdown` |
|
|
128
|
+
| `innerRef` on `Modal.Container` | `ref` | that one becomes bestax's `Modal` root |
|
|
129
|
+
|
|
130
|
+
The third row is the `Navbar.Dropdown` collision, and it runs both ways. Your rbx
|
|
131
|
+
`Navbar.Dropdown` is the menu itself (`div.navbar-dropdown`), so it maps to bestax's
|
|
132
|
+
`Navbar.DropdownMenu`, which forwards no ref — `innerRef` there is left alone. bestax reserves
|
|
133
|
+
the name `Navbar.Dropdown` for the outer container, which is what `<Navbar.Item dropdown>`
|
|
134
|
+
becomes, and that one does forward a ref. A plain `<Navbar.Item>` does not, so the rename is
|
|
135
|
+
conditional on the `dropdown` prop.
|
|
136
|
+
|
|
137
|
+
An existing `ref` is passed through untouched — which is safe only where the bestax target
|
|
138
|
+
forwards one. rbx forwards a ref on every component; bestax does so on the form controls plus
|
|
139
|
+
`Button`, `LinkButton`, `Modal`, `Dropdown`, `Navbar`, `Navbar.Burger`, `Navbar.Link`,
|
|
140
|
+
`Navbar.Dropdown`, `Dialog`, `Sidebar`, `Toast` and `Carousel`. Carry a `ref` onto anything
|
|
141
|
+
else — `Card`, `Box`, `Section`, `Message`, `Tabs` and most of the catalogue — and it resolves
|
|
142
|
+
to `null` at runtime, with React logging "Function components cannot be given refs" and
|
|
143
|
+
continuing.
|
|
144
|
+
|
|
145
|
+
**The codemod does not flag this**, because neither the universal prop table nor any
|
|
146
|
+
per-component table has a `ref` entry, so check every `ref` you carried over against the list
|
|
147
|
+
above rather than assuming the silent pass-through means it works. The renames above are for
|
|
148
|
+
`innerRef`, and apply only on those eight entries. Anywhere else it leaves `innerRef` alone — move the ref onto a wrapping
|
|
149
|
+
element you control.
|
|
150
|
+
|
|
151
|
+
Note the gap that leaves: other bestax components do forward a ref (the form controls,
|
|
152
|
+
`LinkButton`, `Dialog`, `Sidebar`, `Toast`, `Carousel`), but their rbx `innerRef` is not mapped
|
|
153
|
+
yet, so it passes through untouched rather than being renamed for you.
|
|
@@ -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
|
|
|
@@ -112,7 +114,6 @@ which breakpoints did not carry.
|
|
|
112
114
|
|
|
113
115
|
| TODO | What to do |
|
|
114
116
|
| -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
115
|
-
| `prop:closeOnEsc` on `Modal` | bestax implements no Escape handling at all; add your own keydown listener, or drop the prop |
|
|
116
117
|
| `prop:closeOnBlur` on `Modal` | the migrated compound form renders `Modal.Background` as you wrote it; wire its `onClick` to your `onClose` |
|
|
117
118
|
| `prop:selected`, `prop:text` on `Button` | `className="is-selected"`; for `is-text` use `color="ghost"` or a link |
|
|
118
119
|
| `prop:size` on `Button.Group` / `Tags` / `Message` | set `size` on each child instead |
|
|
@@ -120,38 +121,39 @@ which breakpoints did not carry.
|
|
|
120
121
|
| `prop:color`, `prop:vertical` on `Divider` | bestax's `Divider` takes only `bgColor` and renders an `<hr>` |
|
|
121
122
|
| `component:Divider` (a labelled divider) | rbx rendered `<Divider>OR</Divider>`'s children as a centred label via `data-content`; bestax's `Divider` is a bare `<hr>` and takes no children -- React rejects children on a void element at runtime. Put the label in surrounding markup, or drop it |
|
|
122
123
|
| `prop:direction` on `PageLoader` | no directional variant; drop it or add a class |
|
|
123
|
-
| `prop:innerRef` | the affected roots (`Dropdown`, `Modal`, `Navbar`) are plain function components and forward no ref — drop it, or put the ref on a wrapping element you control |
|
|
124
124
|
| `prop:managed` | bestax components are uncontrolled; drive the `Modal` with `active` and `onClose` |
|
|
125
|
-
| `prop:document` on `Modal` | bestax
|
|
125
|
+
| `prop:document` on `Modal` | bestax portals via `portal`, but it takes `true`, a selector or an element rather than a `Document` — see [Modal: what carries over](#modal-what-carries-over) |
|
|
126
126
|
| `prop:document` on `Navbar` | bestax's `Navbar` has no `document` prop; drop it |
|
|
127
127
|
| `badgeOutlined`, `badgeRounded`, `badgeSize` | bestax's `Badge` has no outline, pill or size variant |
|
|
128
128
|
| `tooltipResponsive` | bestax's `Tooltip` has one `position` for all viewports |
|
|
129
129
|
|
|
130
|
-
## Modal
|
|
130
|
+
## Modal: what carries over
|
|
131
131
|
|
|
132
132
|
`component:Modal` — emitted on **every** Modal the codemod converts, whether or not you passed
|
|
133
133
|
any of the props above.
|
|
134
134
|
|
|
135
|
-
rbx's Modal did three things by default
|
|
135
|
+
rbx's Modal did three things by default. bestax now does two of them the same way, and the
|
|
136
|
+
third is one prop away:
|
|
136
137
|
|
|
137
|
-
| rbx default | bestax
|
|
138
|
-
| -------------------------------- |
|
|
139
|
-
|
|
|
140
|
-
|
|
|
141
|
-
|
|
|
138
|
+
| rbx default | bestax |
|
|
139
|
+
| -------------------------------- | ------------------------------------------------------------------ |
|
|
140
|
+
| closes on Escape | same, `closeOnEscape` defaults to `true` |
|
|
141
|
+
| clips document scroll while open | same, `lockScroll` defaults to `true` |
|
|
142
|
+
| portals into `document.body` | renders inline unless you set `portal` (`true`, selector, element) |
|
|
142
143
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
144
|
+
So the only one that needs an edit is the portal, and it matters most when an ancestor has
|
|
145
|
+
`overflow: hidden`, `filter` or a `transform` — any of which will clip or re-parent a modal that
|
|
146
|
+
used to escape them. `portal` renders inline on the server and during hydration, then moves once
|
|
147
|
+
the client takes over, so it is safe under SSR.
|
|
146
148
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
re-parent the modal that used to escape them.
|
|
150
|
-
- **Escape** — add a `keydown` listener while the modal is open and call your `onClose`.
|
|
151
|
-
- **Scroll lock** — Bulma still ships `.is-clipped`; put it on `<html>` while the modal is open.
|
|
149
|
+
The codemod maps `closeOnEsc` to `closeOnEscape` for you, so `closeOnEsc={false}` keeps
|
|
150
|
+
suppressing Escape rather than silently inheriting the new default.
|
|
152
151
|
|
|
153
|
-
Background click
|
|
154
|
-
|
|
152
|
+
Background click depends on which form you land in. bestax's `Modal` has a legacy form — bare
|
|
153
|
+
children — where it renders its own background and close button, both wired to `onClose`, so
|
|
154
|
+
`closeOnBlur` carries over for free. A `Modal.Content` or `Modal.Card` child selects the compound
|
|
155
|
+
form instead, which renders only what you wrote; there, wire your own `Modal.Background`'s
|
|
156
|
+
`onClick` to the same `onClose`.
|
|
155
157
|
|
|
156
158
|
## `prop:textColor="white-ter"` / `"white-bis"`
|
|
157
159
|
|
|
@@ -29,7 +29,7 @@ codemod converts it; **Flagged** = it leaves a `TODO(bestax-migrate)` comment (s
|
|
|
29
29
|
| `Media` | `Media` | Auto |
|
|
30
30
|
| `Menu` | `Menu` | Auto |
|
|
31
31
|
| `Message` | `Message` | Auto; `size` flagged |
|
|
32
|
-
| `Modal` | `Modal` | `show`→`active`; `
|
|
32
|
+
| `Modal` | `Modal` | `show`→`active`, `closeOnEsc`→`closeOnEscape`; `closeOnBlur`/`showClose` flagged (compound form renders neither) |
|
|
33
33
|
| `Navbar` | `Navbar` | Auto; see dropdown note below |
|
|
34
34
|
| `Notification` | `Notification` | Auto; `light`→`isLight` |
|
|
35
35
|
| `Pagination` | `Pagination` | `onChange`→`onPageChange`; `delta`/labels/`showFirstLast`/`autoHide` flagged |
|
|
@@ -9,7 +9,7 @@ this automatically for literal values; dynamic values get TODOs.
|
|
|
9
9
|
| RBC | bestax |
|
|
10
10
|
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
11
11
|
| `renderAs` | `as` — **only** on polymorphic components (Button, Title/SubTitle, Footer, Level.Item, Media\*, Menu.Item, Navbar.Item/Link, Dropdown.Item); elsewhere flagged |
|
|
12
|
-
| `domRef` | flagged —
|
|
12
|
+
| `domRef` | flagged — rename to `ref` on the components that forward one, else use a DOM child |
|
|
13
13
|
| `backgroundColor` | `bgColor` |
|
|
14
14
|
| `textColor` | `textColor` (same) |
|
|
15
15
|
| `colorVariant` | flagged — use `isLight` or a color shade |
|
|
@@ -66,11 +66,26 @@ Drop `delta` (built-in), render conditionally instead of `autoHide`
|
|
|
66
66
|
(`{total > 1 && <Pagination …/>}`), and compose `Pagination.Previous`/`Pagination.Next`
|
|
67
67
|
manually if custom labels are essential.
|
|
68
68
|
|
|
69
|
-
## `Modal` (`
|
|
69
|
+
## `Modal` (`closeOnBlur`, `showClose`)
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
`closeOnEsc` is not in this list: bestax has `closeOnEscape` (default `true`) and the codemod
|
|
72
|
+
renames it, so `closeOnEsc={false}` keeps suppressing Escape rather than inheriting the default.
|
|
73
|
+
|
|
74
|
+
The other two depend on which form the migrated modal lands in. bestax's `Modal` supplies a
|
|
75
|
+
background wired to `onClose` and a floating close button only in its **legacy** form — plain
|
|
76
|
+
children, no compound child. A `Modal.Content` or `Modal.Card` child (which is what almost every
|
|
77
|
+
RBC modal has) selects the **compound** form, and that renders only the children you wrote:
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
<Modal active={show} onClose={close}>
|
|
81
|
+
<Modal.Background onClick={close} />
|
|
82
|
+
<Modal.Content>…</Modal.Content>
|
|
83
|
+
<Modal.Close variant="floating" onClick={close} />
|
|
84
|
+
</Modal>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
So `closeOnBlur` and `showClose={true}` mean "add those two children"; passing either as `false`
|
|
88
|
+
means "drop the prop", since the compound form gives you neither unless you ask.
|
|
74
89
|
|
|
75
90
|
## `touch` / `untilWidescreen` / `untilFullhd` / `{ only: true }` breakpoints
|
|
76
91
|
|
|
@@ -113,8 +128,23 @@ bestax `Button` colors are the semantic set + `text`/`ghost`. For shades use
|
|
|
113
128
|
|
|
114
129
|
## `domRef`
|
|
115
130
|
|
|
116
|
-
bestax components don't take `domRef
|
|
117
|
-
|
|
131
|
+
bestax components don't take `domRef`, but many forward a plain `ref` — the form controls
|
|
132
|
+
and `Button`, `LinkButton`, `Modal`, `Dropdown`, `Navbar` (plus `Navbar.Burger` and
|
|
133
|
+
`Navbar.Link`), `Dialog`, `Sidebar`, `Toast` and `Carousel`. On those, rename `domRef` to
|
|
134
|
+
`ref` and it works; do not restructure the markup. Everywhere else there is no ref to
|
|
135
|
+
forward — attach the ref to a DOM element inside, or wrap the component in a `<div ref={…}>`.
|
|
136
|
+
|
|
137
|
+
The codemod does not do that rename for you: `domRef` is flagged on every component, so the
|
|
138
|
+
TODO names both cases and you pick. `Navbar.Dropdown` is the trap, and it cuts both ways —
|
|
139
|
+
RBC's is the menu itself, so it maps to bestax's `Navbar.DropdownMenu`, which forwards no ref;
|
|
140
|
+
bestax reserves the name `Navbar.Dropdown` for the outer container, which is what the
|
|
141
|
+
`Navbar.Item` wrapping your dropdown becomes, and that one _does_ forward one. So after the
|
|
142
|
+
codemod runs, read the target name on the line, not the one you wrote.
|
|
143
|
+
|
|
144
|
+
`Button` has the same shape of trap. `<Button remove>` is Bulma's delete cross, so it migrates
|
|
145
|
+
to `<Delete>`, a plain function component that forwards no ref — even though `Button` itself
|
|
146
|
+
does. The codemod detects that case and replaces the general advice with a TODO naming
|
|
147
|
+
`Delete`, so the message on the line is the one to trust.
|
|
118
148
|
|
|
119
149
|
## Helper props dropped from plain-element replacements
|
|
120
150
|
|