Skip to main content

Configuration

ConfigProvider is bestax-bulma's extension point for app-wide choices that Bulma itself can't express in React: a class-prefix namespace for the Bulma CSS classes your components emit, a default icon library every Icon should fall back to, and where portaled content such as a Popover panel renders. It works through React context, so any setting you provide applies to every descendant component, with no prop drilling.

Overview​

ConfigProvider takes these settings:

  • classPrefix — prefix applied to every Bulma class name the library renders (pair it with the matching prefixed bestax CSS bundle, @allxsmith/bestax-bulma/versions/bestax-prefixed.css, for classPrefix="bestax-").
  • iconLibrary — the default icon library ('fa', 'mdi', 'ion', 'material-icons', 'material-symbols') that Icon components resolve to when no library prop is set.
  • portalContainer: where portaled content goes when it has no target of its own, such as Popover's appendToBody panel, a Modal with portal, or a Portal with no container.

Each is optional; without a ConfigProvider the library uses unprefixed Bulma classes and Font Awesome icons, and portals into document.body.

CSS Class Prefixing​

Class prefixing adds a namespace to every Bulma class the library renders:

  • button becomes bestax-button
  • box becomes bestax-box
  • title becomes bestax-title

The goal is to avoid collisions between Bulma's generic class names (.button, .card, .title, .menu, .notification, …) and the class names used by your own application's CSS. Teams that have their own hand-written stylesheets — design tokens, layout utilities, component classes — often already use some of those names; prefixing every Bulma class lets both sets coexist cleanly.

Not for combining CSS frameworks

Class prefixing is about namespacing Bulma's class names, not about running bestax alongside another CSS framework like Bootstrap or Tailwind Preflight. Bulma's base-element rules (in bulma/sass/base/minireset.scss and generic.scss) target raw HTML tags — body, p, h1–h6, ul, img, table, … — and apply globally regardless of any class prefix. Stacking Bulma on top of another framework's reset is not a supported setup; pick one framework for the base layer.

Basic Usage​

Standard Configuration​

import { ConfigProvider, Button, Box, Title } from '@allxsmith/bestax-bulma';
import '@allxsmith/bestax-bulma/versions/bestax-prefixed.css';

function App() {
return (
<ConfigProvider classPrefix="bestax-">
<Box p="4">
<Title size="4">Prefixed Components</Title>
<Button color="primary">Prefixed Button</Button>
</Box>
</ConfigProvider>
);
}

This renders HTML with prefixed CSS classes:

<div class="bestax-box p-4">
<h4 class="bestax-title is-4">Prefixed Components</h4>
<button class="bestax-button is-primary">Prefixed Button</button>
</div>

Avoiding Conflicts With Your Own Stylesheets​

If your application already ships its own CSS — a home-grown design system, marketing-page styles, vendored legacy stylesheets — odds are some of your selectors clash with Bulma's (.button, .card, .title, .menu, .notification, .content…). Prefixing every Bulma class keeps the two worlds distinct:

import { ConfigProvider, Button, Box, Title } from '@allxsmith/bestax-bulma';
import '@allxsmith/bestax-bulma/versions/bestax-prefixed.css';
import './styles/app.css'; // your own CSS, free to define its own .button, .card, etc.

function App() {
return (
<ConfigProvider classPrefix="bestax-">
{/* bestax renders .bestax-button, .bestax-box, etc.
Your app's own .button / .card rules are untouched. */}
<Box p="4">
<Title size="4">App section</Title>
<Button color="primary">Action</Button>
</Box>
</ConfigProvider>
);
}

Default Icon Library​

Every Icon component can resolve to a different icon library — Font Awesome, Material Design Icons, Ionicons, Material Icons, or Material Symbols. Setting iconLibrary on ConfigProvider lets the whole tree default to one library; individual Icon components can still override per-use.

import { ConfigProvider, Icon, Button } from '@allxsmith/bestax-bulma';
import '@mdi/font/css/materialdesignicons.min.css';

function App() {
return (
<ConfigProvider iconLibrary="mdi">
<Button color="primary">
<Icon name="rocket-launch" aria-hidden="true" />
<span>Launch</span>
</Button>
</ConfigProvider>
);
}

Valid values are 'fa' (Font Awesome), 'mdi' (Material Design Icons), 'ion' (Ionicons), 'material-icons', and 'material-symbols'. This is the same choice pnpm create bestax@latest prompts for during project setup.

Where Portaled Content Goes​

Content a component portals, such as the panel Popover renders with appendToBody, a Modal with portal, or a Toast, goes to document.body unless portalContainer names an element or a selector to use instead. Set it when that content has to stay inside something document.body is outside of: a scoped Theme, whose variables sit on its own wrapper, or a shadow root, whose styles stay inside it. The element must not sit under an ancestor with a transform, filter, backdrop-filter, perspective, will-change: transform, or a contain that includes paint or layout, because the overlays it receives are position: fixed and would be placed against that ancestor instead of the viewport. The ConfigProvider reference has the rest of what to check, and a worked example.

Combining Prefix and Icon Library​

Both settings are independent and compose. Set whichever you need:

<ConfigProvider classPrefix="bestax-" iconLibrary="mdi">
<App />
</ConfigProvider>

Prefixed bestax CSS bundle​

bestax ships a prebuilt, bestax--prefixed bundle (Bulma and the bestax extras, all prefixed together) that pairs with classPrefix="bestax-". Import it directly:

// Prefixed bestax bundle (Bulma + extras, all "bestax-" prefixed)
import '@allxsmith/bestax-bulma/versions/bestax-prefixed.css';

function App() {
return (
<ConfigProvider classPrefix="bestax-">
<Button color="primary">Uses bestax-button class</Button>
</ConfigProvider>
);
}

Custom Prefix Builds​

For teams building custom Bulma CSS with their own prefixes:

1. Install Dependencies​

pnpm add bulma sass

If pnpm stops on a build script here, see When pnpm blocks a build script.

2. Create Custom Sass File​

src/styles/mycompany-bulma.scss
@use 'bulma/sass' with (
$class-prefix: 'mycompany-'
);

3. Configure Your Application​

src/App.tsx
import { ConfigProvider, Button, Box } from '@allxsmith/bestax-bulma';
import './styles/mycompany-bulma.scss';

function App() {
return (
<ConfigProvider classPrefix="mycompany-">
<Box>
<Button color="primary">Custom Prefixed Button</Button>
</Box>
</ConfigProvider>
);
}

Advanced Configuration​

Nested Providers​

ConfigProviders can be nested. An inner provider replaces the outer one's settings rather than adding to them, so inside it any setting it leaves out is back to its default:

function NestedConfiguration() {
return (
<ConfigProvider classPrefix="outer-">
<Box p="4">
<Title>Outer Prefix (outer-)</Title>

<ConfigProvider classPrefix="inner-">
<Box p="4" mt="3">
<Title>Inner Prefix (inner-)</Title>
<Button color="primary">Inner Button</Button>
</Box>
</ConfigProvider>

<Button color="info" mt="3">
Outer Button
</Button>
</Box>
</ConfigProvider>
);
}

Using Configuration in Custom Components​

Your own components can participate in the same prefix/icon conventions as bestax's built-ins:

import { usePrefixedClass } from '@allxsmith/bestax-bulma';

function CustomComponent() {
const prefixed = usePrefixedClass();
return <div className={prefixed('custom-component')}>Custom content</div>;
}

Configuration Hooks​

These hooks expose the active configuration so your own components can honor the same settings as bestax's built-ins.

useConfig​

Returns the full configuration object:

import { useConfig } from '@allxsmith/bestax-bulma';

function MyComponent() {
const { classPrefix, iconLibrary } = useConfig();
// ...
}

useClassPrefix​

Convenience hook that returns just the class prefix as a string (empty string if none):

import { useClassPrefix } from '@allxsmith/bestax-bulma';

function MyComponent() {
const classPrefix = useClassPrefix();
}

usePrefixedClass​

Returns a function that applies the configured prefix to a class name — handy when building custom components that need to stay in sync with a prefixed Bulma build:

import { usePrefixedClass } from '@allxsmith/bestax-bulma';

function CustomBanner() {
const prefixed = usePrefixedClass();
// Renders "bestax-notification" under ConfigProvider classPrefix="bestax-",
// or plain "notification" without a prefix.
return <div className={prefixed('notification')}>Hello</div>;
}

useIconLibrary​

Returns the configured icon library (or undefined):

import { useIconLibrary } from '@allxsmith/bestax-bulma';

function MyIcon({ name }) {
const library = useIconLibrary() ?? 'fa';
// Render an icon using the configured library
}

Use Cases​

Multi-tenant Applications​

Different tenants can have different styling namespaces:

function TenantApp({ tenantName }) {
return (
<ConfigProvider classPrefix={`${tenantName}-`}>
<App />
</ConfigProvider>
);
}

Component Library Wrapping​

When building your own component library on top of bestax, give its Bulma classes a distinct namespace so they can't clash with anything a consumer adds:

function MyLibraryProvider({ children }) {
return <ConfigProvider classPrefix="mylib-">{children}</ConfigProvider>;
}

Best Practices​

  1. Set at the root level — apply ConfigProvider once near the top of your tree; nest only when a subtree genuinely needs different settings.
  2. Match CSS and React — if you set classPrefix="bestax-", import the matching prefixed bestax bundle @allxsmith/bestax-bulma/versions/bestax-prefixed.css (or your own Sass build with the same prefix). Using the bestax bundle — rather than stock bulma/css/... plus a separate extras.css — keeps the bestax extra components (Notification, Tooltip, etc.) prefixed too.
  3. Match icon font and setting — if you set iconLibrary="mdi", make sure the MDI font package is imported somewhere in your app.
  4. Trust one source — the create-bestax installer wires all of this up in a consistent way; reach for a custom ConfigProvider only when the defaults don't fit.

Integration with Other Features​

ConfigProvider works seamlessly with other library features:

function CompleteSetup() {
return (
<ConfigProvider classPrefix="bestax-">
<Theme primaryH="270" primaryS="100%" primaryL="50%" isRoot>
<App />
</Theme>
</ConfigProvider>
);
}

For detailed API documentation and more examples, see the ConfigProvider API reference.