Theming
BiibaOS is fully customizable through a single JSON object passed to BiibaOSProvider. Every color, font, control size, radius, shadow, and animation token is controlled from one place — and reflected instantly via CSS variables across every component in your app.
Colors
Full light + dark palette
Typography
20 Google Font presets
Control Sizes
Button, Input & Select heights
Elevation
Shadow + glass surfaces
Motion
Speed + physics presets
Quick Start
Any key you omit falls back to the default. You do not need to specify everything — pass only what you want to override.
import { BiibaOSProvider } from 'biibaos'
const customTheme = {
colors: {
light: {
primary: '#5B4FE8', // Brand accent — buttons, links, indicators
background: '#ffffff',
surface: '#f9f9f9',
},
dark: {
primary: '#7B72FF', // Slightly lighter for dark backgrounds
background: '#0a0a0a',
surface: '#141414',
},
},
font: {
fontPreset: 'inter', // Loads automatically from Google Fonts
},
controlHeight: {
xs: 22,
sm: 28,
md: 32, // default size — Button, Input, Select
lg: 40,
xl: 48,
},
radius: {
sm: '8px',
md: '12px',
lg: '18px',
xl: '28px',
},
}
export default function App({ children }) {
return (
<BiibaOSProvider
theme={customTheme}
followSystemTheme={false} // default: light
defaultDark={false}
>
{children}
</BiibaOSProvider>
)
}Live Playground
Changes apply across this entire documentation site instantly.
Light Mode
#0A0A0ADark Mode
#FFFFFFResizes every default-sized Button, Input, and Select
Design System
Changes apply in real time.
Component Surface
Radius, color & font live here
Glass Surface
var(--biiba-vibrancy-bg) + backdrop-filter
Color Tokens
BiibaOS exposes the full color palette as CSS custom properties. They update automatically when the theme changes or dark mode is toggled — no class manipulation needed.
/* All color tokens BiibaOS exposes on :root */
/* ── Brand ─────────────────────────────────────── */
var(--biiba-primary) /* Main brand color */
var(--biiba-primary-fg) /* Text on primary background */
var(--biiba-primary-light) /* 10% opacity tint — used for active states */
/* ── Semantic ───────────────────────────────────── */
var(--biiba-secondary) /* Secondary button / muted action */
var(--biiba-secondary-fg)
var(--biiba-danger) /* Destructive actions, error states */
var(--biiba-danger-fg)
var(--biiba-success) /* Confirmation, positive states */
var(--biiba-success-fg)
var(--biiba-warning) /* Caution states */
var(--biiba-warning-fg)
/* ── Backgrounds ────────────────────────────────── */
var(--biiba-bg) /* Page background */
var(--biiba-surface) /* Component background (cards, inputs) */
var(--biiba-surface-raised) /* Elevated surface — dropdowns, popovers */
var(--biiba-surface-0) /* Deepest layer */
var(--biiba-surface-1) /* Default card surface */
var(--biiba-surface-2) /* Slightly elevated */
var(--biiba-surface-3) /* Most elevated (e.g. modals) */
/* ── Glass / Vibrancy (Tahoe) ───────────────────── */
var(--biiba-glass-bg) /* Frosted glass: rgba white/black + 0.75 */
var(--biiba-glass-border) /* Subtle translucent border */
var(--biiba-vibrancy-bg) /* High-opacity blur (sidebars, bottom nav) */
var(--biiba-vibrancy-border) /* Vibrancy border */
/* ── Text ───────────────────────────────────────── */
var(--biiba-text) /* Primary text */
var(--biiba-text-muted) /* Secondary text — labels, captions */
var(--biiba-text-subtle) /* Placeholder, disabled */
/* ── Borders & Overlays ─────────────────────────── */
var(--biiba-border) /* Default border */
var(--biiba-border-focus) /* Focus ring border */
var(--biiba-overlay) /* Modal backdrop */Border Radius
The Tahoe radius scale (8/12/18/28px) is tuned to match native device aesthetics. Override all values in your theme, or pick individual ones.
sm
8px
Badges, chips
md
12px
Buttons, inputs
lg
18px
Cards, panels
xl
28px
Sheets, drawers
full
9999px
Pills, avatars
/* Border radius scale — all configurable in your theme */
var(--biiba-radius-sm) /* 8px — small elements: badges, chips, small inputs */
var(--biiba-radius-md) /* 12px — default: buttons, inputs, cards */
var(--biiba-radius-lg) /* 18px — panels, sidebars, modals */
var(--biiba-radius-xl) /* 28px — bottom sheets, action sheets */
var(--biiba-radius-full) /* 9999px — pills, avatars, toggles */
/* Override via theme: */
const theme = {
radius: {
sm: '4px', // sharp / enterprise feel
md: '8px',
lg: '12px',
xl: '20px',
}
}Control Sizes
Button, Input, and Select all read their height from the same controlHeight scale. Change md — the default size, used whenever no size prop is passed — to resize every default-sized control app-wide, or override any subset of the steps for a fully custom scale. Each step's font size still comes from the matching step in theme.font.size, so set both together when you want a proportionally smaller or larger control.
xs
22px
sm
28px
md
32px
lg
40px
xl
48px
Live comparison — Button, Input, Select
/* Control height scale — Button, Input, and Select all size off this
one scale, so changing a single number resizes every default-sized
control app-wide. */
const theme = {
controlHeight: {
xs: 22, // px
sm: 28,
md: 32, // default size — used when no size prop is passed
lg: 40,
xl: 48,
},
}
/* Exposed as CSS variables: */
var(--biiba-size-xs) /* 22px */
var(--biiba-size-sm) /* 28px */
var(--biiba-size-md) /* 32px */
var(--biiba-size-lg) /* 40px */
var(--biiba-size-xl) /* 48px */
/* Want every default-sized control to be exactly 20px tall? */
const theme = {
controlHeight: { md: 20 },
}
/* Font size for each step still comes from theme.font.size (see
Typography below) — set both together for a fully custom scale: */
const theme = {
controlHeight: { md: 20 },
font: { size: { md: '12px' } },
}
/* Note: Badge keeps its own independent size scale (18/22/26px) since
it's a compact label chip, not a form control — tying it to
controlHeight would distort it at most values. */Elevation & Shadows
Four elevation tiers, automatically adjusted for dark mode. Use these on your own elements to match the library's depth system.
shadow-sm
var(--biiba-shadow-sm)
shadow-md
var(--biiba-shadow-md)
shadow-lg
var(--biiba-shadow-lg)
shadow-xl
var(--biiba-shadow-xl)
/* Elevation shadow tokens — auto switch light/dark */
var(--biiba-shadow-sm) /* Subtle hover lift — buttons, cards */
var(--biiba-shadow-md) /* Popover, dropdown shadow */
var(--biiba-shadow-lg) /* Modal, sheet shadow */
var(--biiba-shadow-xl) /* Maximum elevation — command palette */
/* Usage: */
.my-card {
box-shadow: var(--biiba-shadow-md);
}Animation & Motion
Duration tokens ensure every timed transition in your app uses the same speed vocabulary. Combined with Tahoe's spring presets, they give your UI a coherent sense of weight and momentum.
80ms
instant
Checkboxes, switches, micro toggle states
150ms
fast
Button press, hover color transitions
250ms
normal
Modal open, popover, dropdown
400ms
slow
Sidebar slide, sheet reveal, page fade
/* Motion duration tokens */
var(--biiba-duration-instant) /* 80ms — micro feedback (checkboxes, switches) */
var(--biiba-duration-fast) /* 150ms — button press, hover state change */
var(--biiba-duration-normal) /* 250ms — panel transitions, modals */
var(--biiba-duration-slow) /* 400ms — page transitions, sheet open */
var(--biiba-duration-very-slow)/* 600ms — onboarding, first-time reveals */
/* Override via theme: */
const theme = {
animation: {
duration: {
fast: 100, // snappier on all interactions
normal: 200,
},
preset: 'snappy', // 'fluid' | 'moderate' | 'snappy' | 'instant'
reducedMotion: false,
haptics: true, // enable haptic pulses on mobile taps
}
}Typography
Specify a fontPreset and the provider injects the Google Fonts stylesheet automatically — no manual <link> tags. You can also set per-role overrides for display headings, code blocks, and captions. The size scale below (xs–xxl) is the same scale Button, Input, and Select use for their own size prop — see Control Sizes to pair it with matching control heights.
All Available Presets
import { BiibaOSProvider } from 'biibaos'
const typographyTheme = {
font: {
fontPreset: 'space-grotesk', // loaded from Google Fonts automatically
// Or set a fully custom family
family: '"Space Grotesk", sans-serif',
// Override the type scale — Button, Input, and Select all read the
// step matching their own size prop (xs/sm/md/lg/xl) from here.
size: {
xs: '11px',
sm: '13px',
md: '15px',
lg: '17px',
xl: '20px',
xxl: '28px',
},
// Per-role overrides (e.g. serif headings + sans body)
variants: {
display: {
fontPreset: 'syne',
weight: 700,
letterSpacing: '-0.02em',
},
mono: {
fontPreset: 'fira-code',
},
},
},
}
export default function App({ children }) {
return <BiibaOSProvider theme={typographyTheme}>{children}</BiibaOSProvider>
}Typography CSS Variables
/* Typography CSS variables */
var(--biiba-font) /* Global font-family — set by fontPreset */
var(--biiba-text-xs) /* 11px */
var(--biiba-text-sm) /* 13px */
var(--biiba-text-md) /* 15px */
var(--biiba-text-lg) /* 17px */
var(--biiba-text-xl) /* 20px */
var(--biiba-text-xxl) /* 28px */
/* Spacing tokens */
var(--biiba-space-xs) /* 4px */
var(--biiba-space-sm) /* 8px */
var(--biiba-space-md) /* 16px */
var(--biiba-space-lg) /* 24px */
var(--biiba-space-xl) /* 32px */Using Tokens in Your CSS
Every token is a native CSS custom property on :root. Use them in your own stylesheets, inline styles, or Tailwind's arbitrary value syntax — they are always in sync with the current theme.
/* Using theme tokens in your own CSS */
.my-button {
background: var(--biiba-primary);
color: var(--biiba-primary-fg);
border-radius: var(--biiba-radius-md);
font-family: var(--biiba-font);
font-size: var(--biiba-text-sm);
box-shadow: var(--biiba-shadow-sm);
transition: box-shadow var(--biiba-duration-fast) ease;
}
.my-button:hover {
box-shadow: var(--biiba-shadow-md);
}
.my-card {
background: var(--biiba-surface-1);
border: 1px solid var(--biiba-border);
border-radius: var(--biiba-radius-lg);
padding: var(--biiba-space-lg);
}
/* Glass surface (Tahoe) */
.my-navbar {
background: var(--biiba-vibrancy-bg);
border-bottom: 1px solid var(--biiba-vibrancy-border);
backdrop-filter: blur(24px);
-webkit-backdrop-filter: blur(24px);
}Utility Classes
For rapid prototyping without writing CSS, BiibaOS exposes a small set of utility classes. These are best for quick layout work — use the CSS variables for production code.
<!-- Utility classes for rapid prototyping -->
<!-- Text colors -->
<span class="biiba_text-primary">Brand colored text</span>
<span class="biiba_text-muted">Muted secondary text</span>
<span class="biiba_text-danger">Error state text</span>
<span class="biiba_text-success">Success text</span>
<!-- Backgrounds -->
<div class="biiba_bg-surface">Default card surface</div>
<div class="biiba_bg-surface-raised">Elevated surface</div>
<div class="biiba_bg-danger-light">Light danger tint</div>
<div class="biiba_bg-primary-light">Light primary tint (active state)</div>
<!-- Borders -->
<div class="biiba_border">Standard border</div>
<div class="biiba_border-focus">Focus ring border</div>Runtime Theme Control
The useBiibaOS hook gives you full runtime control over the theme. Changes are applied immediately via CSS variable mutation — no rebuild, no flash. Dark mode preference is persisted to localStorage automatically.
'use client'
import { useBiibaOS } from 'biibaos'
export function ThemeToggle() {
const { isDark, toggleDark, setTheme, theme } = useBiibaOS()
return (
<div style={{ display: 'flex', gap: 12 }}>
{/* Toggle dark mode */}
<button onClick={toggleDark}>
{isDark ? 'Light mode' : 'Dark mode'}
</button>
{/* Change primary brand color at runtime */}
<input
type="color"
value={theme.colors.light.primary}
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setTheme({ colors: { light: { primary: e.target.value } } })
}
/>
{/* Switch font preset at runtime */}
<button onClick={() => setTheme({ font: { fontPreset: 'syne' } })}>
Syne font
</button>
</div>
)
}
// useBiibaOS returns:
// theme — the full resolved BiibaTheme object
// isDark — boolean, current mode
// setTheme(partial) — deep-merge a partial theme at runtime
// setDark(bool) — set dark mode explicitly
// toggleDark() — flip current mode