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
bulma@0.7.5as 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 deletes five dependencies — rbx and all four of
its Bulma extensions — and replaces them with @allxsmith/bestax-bulma and Bulma v1.
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/Loader→Loading,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}. - 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 (…), and thebulma-badge/bulma-divider/bulma-pageloader/bulma-tooltipimports are dropped: bestax shipsBadge,Divider,LoadingandTooltipitself.
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.