Theming skill
The bestax-theming
skill teaches an agent to customize colors, branding, and dark mode of an app built with
@allxsmith/bestax-bulma. Bulma 1.x is themed through --bulma-* CSS variables; recolor a brand
color by overriding its hue/saturation/lightness trio with the exported Theme component.
Install
npx skills add https://github.com/allxsmith/bestax --skill bestax-theming
Custom brand theme
Prompt
Set up a custom brand theme for an app built with @allxsmith/bestax-bulma —
override the brand colors and the corner radius — following the bestax theming
skill.
Live result
The wrapped section below recolors via a scoped <Theme> (no isRoot), so the override
applies only to its children.
function example() { return ( <Theme infoH="291" infoS="70%" infoL="65%" linkH="291" linkS="70%" linkL="40%" bulmaVars={{ '--bulma-radius': '9999px' }} > <div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap', alignItems: 'center', }} > <Button color="info">Info button</Button> <Button color="link">Link button</Button> <Tag color="info">Themed tag</Tag> </div> </Theme> ); }
This live preview pins --bulma-primary-*, so the demo recolors info/link to show the effect.
In a real app, override primaryH/primaryS/primaryL the same way to recolor the brand primary.
Generated code
This run predates the skill's guidance on the lightnesses a trio doesn't move, and its colors are
the ones that guidance was written for. Page links read the link color's on-scheme lightness,
not linkL, so its link override leaves them at under 2.5:1 on white, and the scoped orange's
white labels read at under 3.5:1. The skill's current
brand-theme example
drops the link override and darkens the orange until its labels read.
- App root (global)
- Scoped override
import { Theme } from '@allxsmith/bestax-bulma';
// Wrap the app once. `isRoot` writes the variables to :root globally.
export function ThemedApp({ children }: { children: React.ReactNode }) {
return (
<Theme
isRoot
primaryH="265"
primaryS="65%"
primaryL="55%"
linkH="200"
linkS="80%"
linkL="45%"
bulmaVars={{
'--bulma-radius': '0.75rem',
'--bulma-family-primary': "'Inter', system-ui, sans-serif",
}}
>
{children}
</Theme>
);
}
import { Theme, Box, Button } from '@allxsmith/bestax-bulma';
// Theme one section; the rest of the app is untouched (no `isRoot`).
export function PromoPanel() {
return (
<Theme primaryH="16" primaryS="85%" primaryL="55%">
<Box>
<Button color="primary">Warm primary, only here</Button>
</Box>
</Theme>
);
}
Overriding a color's --bulma-<color>-h/-s/-l trio recolors the color itself, and its shades and
variants take the new hue and saturation at the lightnesses the stylesheet was built with. The
label on a solid color and the color's text on the page keep lightnesses picked for the built
color, so a brand color that reads lighter or darker also sets --bulma-<color>-invert-l and
--bulma-<color>-on-scheme-l in CSS; the skill's
CSS variables reference
says how. Non-color tokens (radius, fonts, sizes) go through bulmaVars, keyed by their real
--bulma-* names.
Dark mode
Prompt
Add a light/dark mode toggle to an app built with @allxsmith/bestax-bulma —
there is no shipped dark-mode component — following the bestax theming skill.
Generated code
The Theme component drives dark mode via its colorMode prop.
This run predates the skill's guidance on the first paint. Its toggle starts from the OS scheme
on every load and keeps no choice between visits. colorMode alone can't bring a saved choice
back without a frame of the OS scheme first, because it writes data-theme only once the app's
script runs, so the skill's current
dark-mode example
adds an inline <head> script that writes the saved choice before the first paint.
import { useState } from 'react';
import {
Theme,
Box,
Button,
Title,
Notification,
} from '@allxsmith/bestax-bulma';
type Mode = 'light' | 'dark' | 'system';
export function DarkModeToggle() {
const [mode, setMode] = useState<Mode>('system');
return (
<Theme isRoot colorMode={mode}>
<Box>
<Title size="5">Color mode: {mode}</Title>
<Notification color="info">
Components follow the current Bulma color scheme.
</Notification>
<Button color="primary" onClick={() => setMode('light')}>
Light
</Button>
<Button color="primary" onClick={() => setMode('dark')}>
Dark
</Button>
<Button onClick={() => setMode('system')}>System</Button>
</Box>
</Theme>
);
}
How it works
Theme's colorMode prop ('light' | 'dark' | 'system') writes Bulma's data-theme attribute on
<html>, plus data-<prefix>theme under a ConfigProvider classPrefix, which the prefixed
flavors read. The whole document follows the chosen scheme — global, even on a scoped Theme.
'system' removes the attributes so Bulma follows the OS prefers-color-scheme. Brand overrides
from <Theme isRoot> still apply on top of either scheme.
colorMode flips the page-level data-theme on <html> — the same attribute this documentation
site uses for its own light/dark mode, and the embedded previews are sandboxed to the site theme.
A live toggle would flip the entire site, not a contained example. To see it: toggle this site's
dark mode (top-right of the navbar) to view components in dark, or run the Helpers / Theme →
DarkMode story in Storybook.