Customization
Customize themes using ThemeProvider's theme and themeOverride properties (applied to providers, not components).
The theme
and themeOverride
properties are applied via ThemeProvider (not on individual components). You can scope changes globally or to any subtree by wrapping that part of your UI with a ThemeProvider, leaving the rest of the app unaffected.
The theme
property accepts a partial theme object that merges with the default theme values. This allows you to override specific theme tokens while keeping the rest of the default values intact.
interface PartialTheme { colors?: { primary?: string; secondary?: string; success?: string; danger?: string; warning?: string; info?: string; accent?: string; }; sizes?: { xs?: string; sm?: string; md?: string; lg?: string; xl?: string; }; radius?: { xs?: string; sm?: string; md?: string; lg?: string; xl?: string; };}
The themeOverride
function receives the current theme as a parameter and returns a modified theme object. This approach gives you complete control over theme transformations and allows for complex customizations.
type ThemeOverride = (theme: ThemeProps) => ThemeProps;
Override specific colors for individual components:
import { ThemeProvider, Button, Badge, Card } from '@vaneui/ui';
function CustomThemedComponents() { const customTheme = { colors: { primary: '#8b5cf6', success: '#10b981', danger: '#ef4444' } };
return ( <ThemeProvider theme={customTheme}> <div> <Button filled primary> Custom Purple Button </Button> <Badge success> Custom Green Badge </Badge> <Card danger> Custom Red Card </Card> </div> </ThemeProvider> );}
Modify sizing and border radius values:
import { ThemeProvider, Button, Chip } from '@vaneui/ui';
function CustomSizedComponents() { const sizeTheme = { sizes: { sm: '2rem', md: '2.5rem', lg: '3rem' }, radius: { md: '1rem', lg: '1.5rem' } };
return ( <ThemeProvider theme={sizeTheme}> <div> <Button sm> Custom Button </Button> <Chip md> Custom Chip </Chip> </div> </ThemeProvider> );}
Create reusable theme objects for consistent styling:
import { Button, Badge } from '@vaneui/ui';
const brandTheme = { colors: { primary: '#6366f1', secondary: '#8b5cf6', accent: '#ec4899' }, radius: { sm: '0.5rem', md: '0.75rem', lg: '1rem' }};
const warningTheme = { colors: { warning: '#f59e0b', danger: '#ef4444' }};
function ThemedInterface() { return ( <div> {/* Brand-themed components */} <ThemeProvider theme={brandTheme}> <Button primary> Brand Button </Button> <Badge accent> Brand Badge </Badge> </ThemeProvider> {/* Warning-themed components */} <ThemeProvider theme={warningTheme}> <Button warning> Warning Button </Button> </ThemeProvider> </div> );}
Transform themes based on conditions or calculations:
import { ThemeProvider, Button } from '@vaneui/ui';
function DynamicThemedButton({ isHighContrast = false }) { const themeOverride = (theme) => { if (isHighContrast) { return { ...theme, colors: { ...theme.colors, primary: '#000000', secondary: '#333333' } }; } return { ...theme, colors: { ...theme.colors, primary: '#6366f1' } }; };
return ( <ThemeProvider themeOverride={themeOverride}> <Button primary> Adaptive Button </Button> </ThemeProvider> );}
Create sophisticated theme modifications:
import { ThemeProvider, Card, Text } from '@vaneui/ui';
function GradientCard({ baseColor = '#3b82f6' }) { const gradientThemeOverride = (theme) => { // Generate complementary colors const lighterColor = adjustColor(baseColor, 20); const darkerColor = adjustColor(baseColor, -20); return { ...theme, colors: { ...theme.colors, primary: baseColor, secondary: lighterColor }, customStyles: { background: `linear-gradient(135deg, ${lighterColor}, ${darkerColor})` } }; };
return ( <ThemeProvider themeOverride={gradientThemeOverride}> <Card primary> <Text>Gradient themed card</Text> </Card> </ThemeProvider> );}
// Helper function to adjust color brightnessfunction adjustColor(color, percent) { // Implementation would adjust color brightness return color;}
Apply different themes based on props or state:
import { Button } from '@vaneui/ui';
function ConditionalThemedButton({ variant, disabled }) { const conditionalOverride = (theme) => { let modifiedTheme = { ...theme }; // Apply variant-specific modifications if (variant === 'special') { modifiedTheme.colors.primary = '#8b5cf6'; modifiedTheme.radius.md = '1rem'; } // Apply disabled state modifications if (disabled) { modifiedTheme.colors = { ...modifiedTheme.colors, primary: '#9ca3af' }; } return modifiedTheme; };
return ( <ThemeProvider themeOverride={conditionalOverride}> <Button primary disabled={disabled} > Conditional Button </Button> </ThemeProvider> );}
You can use both properties together, where theme
is applied first, then themeOverride
:
import { Button } from '@vaneui/ui';
function CombinedThemeButton() { const baseTheme = { colors: { primary: '#3b82f6' } }; const override = (theme) => ({ ...theme, radius: { ...theme.radius, md: '1rem' } });
return ( <ThemeProvider theme={baseTheme} themeOverride={override}> <Button primary> Combined Theming </Button> </ThemeProvider> );}
Create hierarchical theme structures:
import { Card, Button, Text } from '@vaneui/ui';
function ThemeHierarchy() { const parentTheme = { colors: { primary: '#8b5cf6', secondary: '#6b7280' } }; const childOverride = (theme) => ({ ...theme, colors: { ...theme.colors, accent: '#ec4899' } });
return ( <ThemeProvider theme={parentTheme}> <Card secondary> <Text primary>Parent themed text</Text> <ThemeProvider theme={parentTheme} themeOverride={childOverride}> <Button accent> Child with override </Button> </ThemeProvider> </Card> </ThemeProvider> );}
Adapt themes based on screen size or device capabilities:
import { useMediaQuery } from './hooks/useMediaQuery';import { Button } from '@vaneui/ui';
function ResponsiveThemedButton() { const isMobile = useMediaQuery('(max-width: 768px)'); const responsiveOverride = (theme) => ({ ...theme, sizes: { ...theme.sizes, md: isMobile ? '2rem' : '2.5rem' }, radius: { ...theme.radius, md: isMobile ? '0.5rem' : '0.75rem' } });
return ( <ThemeProvider themeOverride={responsiveOverride}> <Button md> Responsive Button </Button> </ThemeProvider> );}
Use useMemo
to prevent unnecessary theme recalculations:
import { useMemo } from 'react';import { Button } from '@vaneui/ui';
function OptimizedThemedButton({ color, isActive }) { const theme = useMemo(() => ({ colors: { primary: isActive ? '#8b5cf6' : '#6b7280' } }), [isActive]); const themeOverride = useMemo(() => (theme) => ({ ...theme, colors: { ...theme.colors, secondary: color } }), [color]);
return ( <ThemeProvider theme={theme} themeOverride={themeOverride}> <Button primary> Optimized Button </Button> </ThemeProvider> );}
The theme
and themeOverride
properties are provided by ThemeProvider and can be scoped to any part of your UI by wrapping with a ThemeProvider. This enables precise control over specific areas while maintaining consistent theming elsewhere.