Migrating from rbx
rbx was a well-built, fully typed React wrapper for Bulma — its
last commit was June 2019. @allxsmith/bestax-bulma is actively maintained, targets
Bulma v1 (CSS variables, dark mode, Grid), and covers the same component surface.
rbx users are stuck in a way most legacy-library users are not, for two reasons:
- rbx pins Bulma itself. It ships
[email protected]as a direct dependency, plusbulma-badge,bulma-divider,bulma-pageloaderandbulma-tooltip. Your app cannot pick its own Bulma version while rbx is installed, so there is no incremental path to Bulma v1. - React 19 removed
defaultPropson function components, which is what rbx'sforwardRefAsbase is built on.
Migrating clears both at once. The codemod removes rbx and moves you to Bulma v1 with
@allxsmith/bestax-bulma. It also reports the four Bulma extensions rbx pulled in —
bulma-badge, bulma-divider, bulma-pageloader, bulma-tooltip — which bestax replaces with
real components; those it flags rather than deletes, because a manifest entry is something you
declared and your own Sass may still import it.
For a capability-by-capability comparison of bestax against the other major React libraries, see the latest edition of The State of React.
Run the codemod
# Preview the changes and the TODO report without writing anything
pnpm dlx bestax-migrate rbx src/ --dry
# Apply it
pnpm dlx bestax-migrate rbx src/
(npx bestax-migrate … works the same.) Useful flags: --print echoes transformed files to
stdout; --extensions controls which files are considered (default
js,jsx,ts,tsx,scss,sass); --css bestax|bulma|keep picks the stylesheet target
(default bestax); --no-deps skips the package.json update.
The codemod uses jscodeshift to rewrite your source in place:
- Imports —
rbx→@allxsmith/bestax-bulma, including namespace imports andconst { Item } = Card;destructuring. Deep imports likerbx/base/themeare flagged with a pointer to bestax'sThemeandConfigProvider. - Components — every rbx export and its dot-notation compounds are mapped, e.g.
Card.Footer.Item→Card.FooterItem,Tag.Group→Tags,Column.Group→Columns,Table.Cell→Table.Td,PageLoader→Loading(withisFullPage),Navbar.Dropdown→Navbar.DropdownMenu(bestax'sNavbar.Dropdownis the outer container, which<Navbar.Item dropdown>becomes),Level.Item align="right"→Level.Right,Navbar.Segment align="end"→Navbar.End, andTitle subtitle→SubTitle. - Props — bare boolean modifiers gain their bestax prefixes (
outlined→isOutlined,rounded→isRounded),state="loading"→isLoading, and the Bulma v1 spacing helpers replace the removedis-*lessclasses (marginless→m="0",radiusless→radius="radiusless"). Most of rbx's helper values need no remapping at all — itstextAlign,textWeightanddisplayunions are already bestax's. - Breakpoint objects — all three rbx shapes flatten:
responsive={{ tablet: { display: { value: 'flex' } } }}→displayTablet="flex",<Column tablet={{ size: 6 }}>→sizeTablet={6}, and<Column.Group tablet={{ gapSize: 2 }}>→gapTablet={2}. Loader— becomes a plain<div className="loader">, not bestax'sLoading. They are different components: rbx'sLoaderis Bulma's inline spinner and always renders, whileLoadingis a dismissible overlay that renders nothing unlessactive. (PageLoaderisLoading, withisFullPage.)- Structure — rbx's badge and tooltip helper props become real wrapping components
(
<Button tooltip="Hi" />→<Tooltip label="Hi"><Button /></Tooltip>),Select.ContainerandImage.Containerfold onto the component they wrap, andHelp/Labelbecome the plain Bulma markup bestax expects. - Stylesheets — Bulma 0.9-era
@importlines become@use "bulma/sass" with (…). Thebulma-badge/bulma-divider/bulma-pageloader/bulma-tooltipCSS imports are kept, each with a TODO: bestax shipsBadge,Divider,LoadingandTooltipwith their own styles, so the import is only still needed by markup outside rbx that uses the extension's classes directly. Drop it once nothing does.
The TODO report
Anything the codemod cannot convert safely is left in place with a
// TODO(bestax-migrate): … comment on the enclosing statement, and summarised in a report at
the end of the run. Nothing is ever silently dropped or best-guessed.
The four you are most likely to see, in the order they show up when the codemod is run over rbx's own documentation examples:
| What | Why | What to do |
|---|---|---|
component:Icon | bestax's Icon takes a required name, which cannot be read out of an rbx <FontAwesomeIcon icon={faHome} /> child | <Icon name="home" library="fa" variant="solid" /> |
component:Tile | Bulma v1 removed Tiles | Use Grid and Cell; see the Bulma 0.9 → 1 guide |
component:File.* | bestax's <File> renders the whole file-input structure from its own props | Drop the parts; set label, hasName, isBoxed on <File> |
prop:as | rbx's forwardRefAs puts as on every component; bestax declares it on a smaller set, several narrowed to specific tags | Restructure, or render the tag directly |
Generic, Tile, List, Fieldset, Numeric and Highlight have no bestax counterpart, so
their imports are kept (trimmed and TODO-annotated) — your app still runs while you migrate
them by hand.
Finish the migration
- Install — the codemod already rewrote
package.json; apply it withnpm install(or pnpm/yarn). Expect apeer-depsreport entry: rbx peer-depended on React^16.8.6and bestax-bulma needs React 18 or 19, so upgradereact/react-domfirst. If you were on Font Awesome 5, bestax's optional peer wants FA ≥ 6.7 — upgrade, or install withnpm install --legacy-peer-deps. - Styling follow-ups — pick a different CSS flavor if you need
prefixed/no-helpers/light-only builds, and read the
Bulma 0.9 → 1 guide for the styling changes that aren't code-level.
Because rbx pinned Bulma 0.7.5, you are crossing two Bulma majors — expect more visual
drift than the guide's 0.9 → 1 baseline describes. One deliberate change:
bestax.cssships$primaryas bestax blue (#1e6b99) rather than Bulma's stock turquoise — keep the stock look with--css bulma, or set your own brand color via the--bulma-primary-*CSS variables. - Theming — rbx's
ThemeContext(rbx/base/theme) has no direct equivalent. bestax splits that job betweenThemefor CSS-variable overrides andConfigProviderfor the class prefix and icon library. - Verify — typecheck, build, and compare the rendered app against the pre-migration UI.
Version support
The codemod maps the rbx v2 API (v2.2.0 is the final release). The mapping table is checked
against rbx's own export surface in both directions, so a component it does not know about is
reported as unknown-component rather than being silently skipped.
Coming from a different library?
If you're using a specific React Bulma package that isn't supported by the migration tool yet, open a feature request naming the package and the components you use — the codemod platform is built to grow new source libraries.