Skip to main content

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​

Skill bestax-themingModel Claude Opus 4.8Generated 2026-06-27

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>
  );
}

note

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​

Recorded before the label and text advice

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.

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>
);
}

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​

Skill bestax-themingModel Claude Opus 4.8Generated 2026-06-27

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.

Recorded before the first-paint advice

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.

Why there's no live demo here

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.