Theming
Every BytesUI component shares one design token system. Configure it once with ThemeProvider and control colors, variants, and per-component style overrides globally or per instance.
Overview
BytesUI ships with a centralized theme system built around 8 semantic colors (primary, secondary, tertiary, success, warning, error, neutral, info) and 4 visual variants (solid, outlined, soft, plain). Every themeable component (OtpInput, MentionTextArea, TourOverlay, and more to come) accepts `color` and `variant` props that resolve against the active theme, plus a `style` prop for instance-level slot overrides using `Bui.*` keys.
type Color =
| 'primary'
| 'secondary'
| 'tertiary'
| 'success'
| 'warning'
| 'error'
| 'neutral'
| 'info';
type Variant = 'solid' | 'outlined' | 'soft' | 'plain';1. Wrap Your App with ThemeProvider
Add `ThemeProvider` once at the root of your application, above any BytesUI component. Choose `light` or `dark`, BytesUI's two built-in themes.
import { ThemeProvider } from '@bytesui/react';
import App from './App';
export default function Root() {
return (
<ThemeProvider theme="light">
<App />
</ThemeProvider>
);
}Built-in Themes
| Theme | Description |
|---|---|
light | Default theme. Bright surfaces with WCAG AA-compliant semantic colors. Used automatically when `theme` is omitted. |
dark | Dedicated dark-mode surface, text, and border tokens (not simply an inverted light theme), tuned for contrast and visibility. |
Colors & Variants
All 8 semantic colors and all 4 variants are available on every themed component via the `color` and `variant` props. Combine them freely — the palette resolves automatically from the active theme.
import { OtpInput } from '@bytesui/react';
const colors = ['primary', 'secondary', 'tertiary', 'success', 'warning', 'error', 'neutral', 'info'];
const variants = ['solid', 'outlined', 'soft', 'plain'];
export default function ColorVariantGrid() {
return (
<>
{colors.map((color) =>
variants.map((variant) => (
<OtpInput key={`${color}-${variant}`} length={4} color={color} variant={variant} />
))
)}
</>
);
}Creating a Custom Theme
Pass a `themes` map to `ThemeProvider` to register additional named themes. A custom theme can be a full theme object, or a partial override that gets deep-merged on top of the built-in light theme.
import { ThemeProvider } from '@bytesui/react';
const customThemes = {
corporate: {
colors: {
primary: {
main: '#0f172a',
hover: '#1e293b',
focusBorder: '#0f172a',
focusRing: 'rgba(15, 23, 42, 0.15)'
}
}
}
};
export default function App({ children }) {
return (
<ThemeProvider theme="corporate" themes={customThemes} defaultTheme="light">
{children}
</ThemeProvider>
);
}Component-Level Theme Overrides
Add a `components` block to any theme to set default `color`/`variant` props and default slot style overrides for a component across your whole app. Instance-level `style` props still take precedence.
export const myTheme = {
// ...full theme colors, surfaces, text, borders, transitions, typography
components: {
OtpInput: {
defaultProps: { color: 'success', variant: 'soft' },
styleOverrides: {
'Bui.root': { gap: '12px' }
}
}
}
};Per-Instance Slot Styling
Every themed component accepts a `style` prop keyed by `Bui.*` slot names for one-off customization without writing separate CSS. Slot overrides always win over theme defaults.
import { OtpInput } from '@bytesui/react';
export default function SlotStylingExample() {
return (
<OtpInput
length={6}
color="secondary"
variant="soft"
style={{
'Bui.root': { gap: '12px' },
'Bui.input': { borderRadius: '10px', fontWeight: 700 },
'Bui.placeholder': { color: '#94a3b8', opacity: 0.6 }
}}
/>
);
}useTheme() Hook
Access the active theme object and helper utilities inside your own components to build custom themed UI that matches BytesUI components.
import { useTheme, resolveColorTokens, getVariantTokens } from '@bytesui/react';
export default function CustomBadge({ color = 'primary', variant = 'soft', children }) {
const theme = useTheme();
const palette = resolveColorTokens(theme, color, variant);
const tokens = getVariantTokens(palette, variant);
return (
<span
style={{
background: tokens.bg,
color: tokens.text,
border: tokens.border ? `1px solid ${tokens.border}` : 'none',
borderRadius: 999,
padding: '4px 10px',
fontFamily: theme.typography.fontFamily
}}
>
{children}
</span>
);
}ThemeProvider Props
| Prop | Type | Default | Description |
|---|---|---|---|
theme | string | "light" | Name of the active theme. Built-in options: `light`, `dark`, or any key registered via `themes`. |
themes | Record<string, Partial<BytesTheme>> | {} | Custom theme registry. Values can be a full theme object or a partial object deep-merged onto the built-in light theme. |
defaultTheme | string | "light" | Fallback theme name used if `theme` does not match any registered theme. |
children | ReactNode | required | Your application tree. Must wrap any BytesUI component that reads theme context. |
Semantic Colors
| Color | Typical Use |
|---|---|
primary | Main brand color and default action color. |
secondary | Supporting brand accent for secondary actions. |
tertiary | Additional accent color for tags, highlights, and variety. |
success | Positive states, confirmations, and validation. |
warning | Caution states that need attention but aren't errors. |
error | Destructive actions and validation failures. |
neutral | Default/neutral gray for disabled or low-emphasis UI. |
info | Informational messages and hints. |
Variants
| Variant | Description |
|---|---|
solid | Filled background using the color's `main` tone with high-contrast text. |
outlined | Transparent/surface background with a colored border. The default variant. |
soft | Light tinted background using the color's `lightest` tone with `dark` text. |
plain | No background or border — colored text/icon only. |
Theme Utilities & Exports
| Export | Description |
|---|---|
ThemeProvider | React provider that supplies the active theme to all BytesUI components. |
useTheme() | Hook returning the active theme object. |
lightTheme / darkTheme | Built-in theme objects you can import directly for reference or to spread into a custom theme. |
resolveColorTokens(theme, color, variant) | Returns the full color palette object for a semantic color. |
getVariantTokens(palette, variant) | Extracts `{ bg, text, border }` for a specific variant from a resolved palette. |
mapTokensToCSSVariables(tokens, prefix) | Converts palette tokens into a `--prefix-token` CSS variable map. |
generateThemeCSS(theme, prefix?) | Generates a `:root { ... }` CSS string with every theme token, useful outside React. |
getContrastingTextColor(hex) | Returns `#ffffff` or `#000000` based on background luminance. |
createComponentThemeResolver(componentName, theme) | Returns a resolver function that applies `theme.components.<Name>.defaultProps` before resolving tokens. |