Theme

Advanced theming components that provide comprehensive visual customization for your application. The theme system includes Theme for advanced styling options and ThemeProvider for managing light/dark modes.

Import

import { Theme, ThemeProvider, useTheme } from '@beauginbey/vanilla-components';

Basic Usage

Wrap your application with ThemeProvider and Theme to enable theming.

import { Theme, ThemeProvider, Box, Text, Button } from '@beauginbey/vanilla-components';

export default function App() {
  return (
    <ThemeProvider defaultTheme="light">
      <Theme>
        <Box p={6}>
          <Text as="h1" size="3xl" weight="bold" marginBottom={4}>
            Themed Application
          </Text>
          <Text color="secondary" marginBottom={4}>
            This content is wrapped with theme providers for consistent styling.
          </Text>
          <Button variant="solid">
            Themed Button
          </Button>
        </Box>
      </Theme>
    </ThemeProvider>
  );
}

Theme Toggle

Use the useTheme hook to create theme toggles and access theme state.

import { ThemeProvider, Theme, useTheme, Box, Text, Button, IconButton } from '@beauginbey/vanilla-components';

// Theme toggle component
function ThemeToggle() {
  const { theme, setTheme } = useTheme();
  
  return (
    <Button
      variant="outline"
      onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
    >
      {theme === 'light' ? '🌙 Dark' : '☀️ Light'}
    </Button>
  );
}

// Main app component
function ThemedApp() {
  return (
    <Box p={6}>
      <Box display="flex" justifyContent="space-between" alignItems="center" marginBottom={6}>
        <Text as="h2" size="2xl" weight="bold">
          Theme Example
        </Text>
        <ThemeToggle />
      </Box>
      
      <Box p={4} backgroundColor="2" borderRadius="lg">
        <Text marginBottom={2}>
          The theme automatically switches between light and dark modes.
        </Text>
        <Text size="sm" color="secondary">
          All components respect the current theme setting.
        </Text>
      </Box>
    </Box>
  );
}

export default function App() {
  return (
    <ThemeProvider defaultTheme="light" storageKey="theme-demo">
      <Theme>
        <ThemedApp />
      </Theme>
    </ThemeProvider>
  );
}

Accent Colors

Theme supports various accent colors to customize the primary color scheme.

import { Theme, ThemeProvider, Box, Text, Button, Flex } from '@beauginbey/vanilla-components';
import React from 'react';

export default function App() {
  const accentColors = ['blue', 'green', 'red', 'purple', 'orange', 'pink'];
  const [accent, setAccent] = React.useState('blue');

  return (
    <ThemeProvider>
      <Theme accentColor={accent}>
        <Box p={6}>
          <Text as="h2" size="2xl" weight="bold" marginBottom={4}>
            Accent Colors
          </Text>
          
          <Flex gap={2} marginBottom={6} wrap="wrap">
            {accentColors.map(color => (
              <Button
                key={color}
                variant={accent === color ? 'solid' : 'outline'}
                size="sm"
                onClick={() => setAccent(color)}
              >
                {color}
              </Button>
            ))}
          </Flex>
          
          <Box p={4} backgroundColor="2" borderRadius="lg">
            <Text marginBottom={3}>
              Current accent: <strong>{accent}</strong>
            </Text>
            <Flex gap={3}>
              <Button variant="solid">Primary</Button>
              <Button variant="outline">Secondary</Button>
              <Button variant="ghost">Ghost</Button>
            </Flex>
          </Box>
        </Box>
      </Theme>
    </ThemeProvider>
  );
}

Gray Colors

Customize the gray color palette used throughout your application.

import { Theme, ThemeProvider, Box, Text, Button, Flex } from '@beauginbey/vanilla-components';
import React from 'react';

export default function App() {
  const grayColors = ['gray', 'mauve', 'slate', 'sage', 'olive', 'sand'];
  const [gray, setGray] = React.useState('gray');

  return (
    <ThemeProvider>
      <Theme grayColor={gray}>
        <Box p={6}>
          <Text as="h2" size="2xl" weight="bold" marginBottom={4}>
            Gray Palettes
          </Text>
          
          <Flex gap={2} marginBottom={6} wrap="wrap">
            {grayColors.map(color => (
              <Button
                key={color}
                variant={gray === color ? 'solid' : 'outline'}
                size="sm"
                onClick={() => setGray(color)}
              >
                {color}
              </Button>
            ))}
          </Flex>
          
          <Flex gap={3} direction="column">
            <Box p={3} backgroundColor="1" borderRadius="md">
              <Text>Background 1</Text>
            </Box>
            <Box p={3} backgroundColor="2" borderRadius="md">
              <Text>Background 2</Text>
            </Box>
            <Box p={3} backgroundColor="3" borderRadius="md">
              <Text>Background 3</Text>
            </Box>
          </Flex>
        </Box>
      </Theme>
    </ThemeProvider>
  );
}

Appearance

Control the overall theme appearance (light/dark) at the Theme level.

import { Theme, ThemeProvider, Box, Text, Button, Flex } from '@beauginbey/vanilla-components';
import React from 'react';

export default function App() {
  const [appearance, setAppearance] = React.useState('light');

  return (
    <ThemeProvider>
      <Theme appearance={appearance}>
        <Box p={6}>
          <Text as="h2" size="2xl" weight="bold" marginBottom={4}>
            Appearance Control
          </Text>
          
          <Flex gap={3} marginBottom={6}>
            <Button
              variant={appearance === 'light' ? 'solid' : 'outline'}
              onClick={() => setAppearance('light')}
            >
              Light
            </Button>
            <Button
              variant={appearance === 'dark' ? 'solid' : 'outline'}
              onClick={() => setAppearance('dark')}
            >
              Dark
            </Button>
            <Button
              variant={appearance === 'inherit' ? 'solid' : 'outline'}
              onClick={() => setAppearance('inherit')}
            >
              System
            </Button>
          </Flex>
          
          <Box p={4} backgroundColor="2" borderRadius="lg">
            <Text marginBottom={2}>
              Current appearance: <strong>{appearance}</strong>
            </Text>
            <Text size="sm" color="secondary">
              The appearance can be controlled independently from the theme provider.
            </Text>
          </Box>
        </Box>
      </Theme>
    </ThemeProvider>
  );
}

Complete Theme Configuration

Combine all theme options for full customization.

import { Theme, ThemeProvider, Box, Text, Button, Flex, Container, Section } from '@beauginbey/vanilla-components';
import React from 'react';

export default function App() {
  const [config, setConfig] = React.useState({
    accentColor: 'blue',
    grayColor: 'gray',
    panelBackground: 'translucent',
    radius: 'medium',
    scaling: '100%',
  });

  const updateConfig = (key, value) => {
    setConfig(prev => ({ ...prev, [key]: value }));
  };

  return (
    <ThemeProvider>
      <Theme {...config}>
        <Section>
          <Container size="2">
            <Text as="h2" size="3xl" weight="bold" marginBottom={6}>
              Theme Configuration
            </Text>
            
            <Flex direction="column" gap={4} marginBottom={6}>
              <Box>
                <Text weight="semibold" marginBottom={2}>Accent Color</Text>
                <Flex gap={2} wrap="wrap">
                  {['blue', 'green', 'red', 'purple', 'orange'].map(color => (
                    <Button
                      key={color}
                      size="sm"
                      variant={config.accentColor === color ? 'solid' : 'outline'}
                      onClick={() => updateConfig('accentColor', color)}
                    >
                      {color}
                    </Button>
                  ))}
                </Flex>
              </Box>
              
              <Box>
                <Text weight="semibold" marginBottom={2}>Border Radius</Text>
                <Flex gap={2}>
                  {['none', 'small', 'medium', 'large', 'full'].map(radius => (
                    <Button
                      key={radius}
                      size="sm"
                      variant={config.radius === radius ? 'solid' : 'outline'}
                      onClick={() => updateConfig('radius', radius)}
                    >
                      {radius}
                    </Button>
                  ))}
                </Flex>
              </Box>
              
              <Box>
                <Text weight="semibold" marginBottom={2}>Scaling</Text>
                <Flex gap={2}>
                  {['90%', '95%', '100%', '105%', '110%'].map(scale => (
                    <Button
                      key={scale}
                      size="sm"
                      variant={config.scaling === scale ? 'solid' : 'outline'}
                      onClick={() => updateConfig('scaling', scale)}
                    >
                      {scale}
                    </Button>
                  ))}
                </Flex>
              </Box>
            </Flex>
            
            <Box p={6} backgroundColor="2" borderRadius="lg">
              <Text size="lg" weight="semibold" marginBottom={3}>
                Preview
              </Text>
              <Flex gap={3} wrap="wrap">
                <Button variant="solid">Primary</Button>
                <Button variant="outline">Outline</Button>
                <Button variant="ghost">Ghost</Button>
              </Flex>
            </Box>
          </Container>
        </Section>
      </Theme>
    </ThemeProvider>
  );
}

Props

ThemeProvider Props

PropTypeDefaultDescription
defaultTheme'light' | 'dark''light'Default theme mode
storageKeystring'theme'LocalStorage key for persisting theme
childrenReactNode-Child components

Theme Props

PropTypeDefaultDescription
accentColorAccentColor'blue'Primary accent color
grayColorGrayColor'gray'Gray color palette
appearance'light' | 'dark' | 'inherit''inherit'Theme appearance
panelBackground'solid' | 'translucent''translucent'Panel background style
radius'none' | 'small' | 'medium' | 'large' | 'full''medium'Border radius scale
scaling'90%' | '95%' | '100%' | '105%' | '110%''100%'UI scaling factor

useTheme Hook

Returns an object with:

  • theme: Current theme ('light' or 'dark')
  • setTheme: Function to update theme
  • toggleTheme: Function to toggle between light and dark