Theming
ThemeProvider, createTheme, dark mode, high contrast, and custom brand themes for MindeesUI. Tokens cover colour, typography, spacing, radii, shadows, motion, breakpoints, z-index, and density.
Theming
MindeesUI ships four themes out of the box — lightTheme, darkTheme, highContrastLightTheme, highContrastDarkTheme — plus createThemes() to rebrand the whole app from a single colour and createTheme() for fully custom control.
Theme in one line: createThemes
The fastest way to rebrand. Give a brand colour for light and dark; MindeesUI generates a matched theme pair and derives the hover/active shades and a readable on-accent text colour for you.
import { createThemes, ThemeProvider } from '@mindees/ui';
const { light, dark } = createThemes({
name: 'acme',
light: { brand: '#6d28d9' },
dark: { brand: '#a78bfa' },
});
export default function App() {
return (
<ThemeProvider light={light} dark={dark}>
{/* app */}
</ThemeProvider>
);
}
That single brand colour drives buttons, links, focus rings, selected states, and the status.info accent. Optionally pass success / danger / warning (subtle variants are derived), density, contrast, or any non-colour token override.
Copy-edit template
themeTemplate is a ready-to-edit starting point — change the colours, pass it to createThemes, done:
import { createThemes, themeTemplate } from '@mindees/ui';
const { light, dark } = createThemes({
...themeTemplate,
light: { ...themeTemplate.light, brand: '#0ea5e9' },
dark: { ...themeTemplate.dark, brand: '#38bdf8' },
});
ThemeProvider
Wrap your app once. Listens to the OS for colour-scheme changes, reduce-motion, and high-contrast preferences.
import { ThemeProvider } from '@mindees/ui';
<ThemeProvider mode="auto">
{' '}
{/* 'auto' | 'light' | 'dark' */}
{/* app */}
</ThemeProvider>;
| Prop | Type | Default | Description |
|---|---|---|---|
mode | 'auto' | 'light' | 'dark' | 'auto' | follows OS in auto |
light | Theme | lightTheme | theme used in light mode |
dark | Theme | darkTheme | theme used in dark mode |
highContrastLight | Theme | highContrastLightTheme | when OS reports high-contrast |
highContrastDark | Theme | highContrastDarkTheme | likewise in dark |
createTheme
import { createTheme } from '@mindees/ui';
const brand = createTheme({
name: 'brand',
colorScheme: 'light',
contrast: 'normal', // 'normal' | 'high'
density: 'comfortable', // 'compact' | 'comfortable' | 'spacious'
colors: {
action: { primary: '#ff00aa', primaryHover: '#e6009a' },
text: { primary: '#1a1a1a' },
},
});
Override granularity: any leaf of SemanticColors is overridable (deep-merged onto the base), and you can override every token category too — space, radii, shadows, textStyles, breakpoints, zIndex, duration, easing. Setting density actually scales the spacing rhythm (compact tightens, spacious loosens), grid-aligned.
For most apps, prefer createThemes — it wraps createTheme and derives the accent shades for you.
Hooks
import { useTheme, useTokens, useReduceMotion } from '@mindees/ui';
function Card() {
const t = useTokens();
const reduceMotion = useReduceMotion();
return (
<View
style={{
padding: t.space.lg,
backgroundColor: t.colors.background.surface,
borderRadius: t.radii.lg,
}}
/>
);
}
Used outside a <ThemeProvider>, hooks return lightTheme — keeps Storybook stories renderable without setup.
Tokens
Every styling decision goes through a named token. See @mindees/tokens:
- Color: 12-step scales (gray / blue / green / red / yellow / orange) in light + dark, plus semantic mappings (
background.canvas,text.primary,action.primary,status.success, etc.) and high-contrast variants. - Typography:
2xs–6xlsize scale; named text styles (display,h1–h6,body,label,caption,overline,code). - Spacing: 4-point scale (
none→7xl). - Radii:
none→3xl,pill,full. - Shadows: iOS shadow* + Android elevation in one resolver.
- Motion: Doherty-Threshold-aware durations + named easings.
- Breakpoints:
xs–2xlfor responsive layouts. - Z-index: named layers so overlays never collide.
- Density:
compact/comfortable/spacious.
Dark mode
ThemeProvider mode="auto" follows the OS automatically (Appearance.addChangeListener). Force a fixed scheme by passing mode="light" or mode="dark".
High-contrast mode
Honored automatically when the OS reports prefers-contrast: more (or platform equivalent). Ships separate high-contrast palettes that push contrast ratios above WCAG 2.2 AAA.
Custom Unistyles config
The library configures Unistyles for you via configureUnistyles(). To use a custom theme:
import { configureUnistyles, createTheme } from '@mindees/ui';
const brand = createTheme({ name: 'brand', colorScheme: 'light', colors: { ... } });
configureUnistyles({
themes: { light: brand, dark: brand },
adaptiveThemes: true,
});Layout Intelligence Layer
How MindeesUI components introspect their children and auto-adjust spacing, sizing, alignment, accessibility roles, and styling. Every rule is deterministic, documented, and overridable — never AI magic.
Providers
ThemeProvider, PortalProvider, ErrorBoundary — the three root-level providers MindeesUI needs. Lightweight, dependency-free, and designed for the New Architecture.