or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

components.mdhooks-utilities.mdindex.mdstyling-system.mdtheming.md
tile.json

theming.mddocs/

Theming System

The Theme UI theming system provides a comprehensive approach to design systems with color modes, design tokens, theme specification compliance, and component variants. It enables consistent, constraint-based design across applications with built-in support for light/dark modes and theme customization.

Capabilities

Theme Provider

The ThemeUIProvider component provides theme context to all child components and manages color mode state.

/**
 * Main theme provider component with color mode support
 * @param theme - Theme object following Theme UI specification
 * @param children - Child components that will receive theme context
 */
interface ThemeUIProviderProps {
  theme: Theme;
  children: React.ReactNode;
}

function ThemeUIProvider(props: ThemeUIProviderProps): JSX.Element;

// Deprecated alias - use ThemeUIProvider instead
function ThemeProvider(props: ThemeUIProviderProps): JSX.Element;

Usage Examples:

import { ThemeUIProvider } from 'theme-ui'

const theme = {
  colors: {
    text: '#000',
    background: '#fff',
    primary: '#07c',
    secondary: '#30c',
    modes: {
      dark: {
        text: '#fff',
        background: '#000',
        primary: '#0cf',
        secondary: '#f0c'
      }
    }
  },
  fonts: {
    body: 'system-ui, sans-serif',
    heading: '"Avenir Next", sans-serif',
    monospace: 'Menlo, monospace'
  }
}

export default function App({ children }) {
  return (
    <ThemeUIProvider theme={theme}>
      {children}
    </ThemeUIProvider>
  )
}

Theme Object Structure

The theme object follows the System UI Theme Specification and defines all design tokens used throughout the application.

interface Theme {
  /** Color palette including mode variants */
  colors?: ColorTheme;
  /** Font family definitions */
  fonts?: { [key: string]: string };
  /** Font size scale (array or object) */
  fontSizes?: (string | number)[] | { [key: string]: string | number };
  /** Font weight definitions */
  fontWeights?: { [key: string]: string | number };
  /** Line height scale */
  lineHeights?: { [key: string]: string | number };
  /** Spacing scale for margin and padding */
  space?: (string | number)[] | { [key: string]: string | number };
  /** Size scale for width, height, etc. */
  sizes?: { [key: string]: string | number };
  /** Border radius scale */
  radii?: { [key: string]: string | number };
  /** Box shadow definitions */
  shadows?: { [key: string]: string };
  /** Responsive breakpoints */
  breakpoints?: Breakpoints;
  /** Z-index scale */
  zIndices?: { [key: string]: number };
  /** Global and element styles */
  styles?: ThemeStyles;
  /** Component variant definitions */
  [componentName: string]: any;
}

Usage Examples:

const theme = {
  // Color system with modes
  colors: {
    text: '#333',
    background: '#fff',
    primary: '#007acc',
    secondary: '#ff6b6b',
    muted: '#f6f6f6',
    accent: '#9c27b0',
    modes: {
      dark: {
        text: '#fff',
        background: '#111',
        primary: '#3eb8ff',
        secondary: '#ff8a80',
        muted: '#2d2d2d'
      }
    }
  },
  
  // Typography scale
  fonts: {
    body: '"Inter", system-ui, sans-serif',
    heading: '"Playfair Display", Georgia, serif',
    monospace: '"Fira Code", Consolas, monospace'
  },
  fontSizes: [12, 14, 16, 20, 24, 32, 48, 64, 96],
  fontWeights: {
    light: 300,
    normal: 400,
    medium: 500,
    semibold: 600,
    bold: 700,
    extrabold: 800
  },
  lineHeights: {
    solid: 1,
    title: 1.25,
    copy: 1.5,
    loose: 1.75
  },
  
  // Spacing and sizing
  space: [0, 4, 8, 16, 32, 64, 128, 256, 512],
  sizes: {
    container: 1200,
    sidebar: 300,
    avatar: 48
  },
  
  // Design tokens
  radii: {
    none: 0,
    sm: 2,
    default: 4,
    md: 6,
    lg: 8,
    xl: 12,
    full: 9999
  },
  shadows: {
    sm: '0 1px 3px rgba(0,0,0,0.12)',
    md: '0 4px 6px rgba(0,0,0,0.12)',
    lg: '0 10px 25px rgba(0,0,0,0.12)',
    inner: 'inset 0 2px 4px rgba(0,0,0,0.06)'
  },
  
  // Responsive breakpoints
  breakpoints: ['40em', '52em', '64em', '80em']
}

Color Mode System

Theme UI provides built-in support for multiple color modes with automatic persistence and flash prevention.

interface ColorTheme {
  /** Base color definitions */
  [colorName: string]: string;
  /** Color mode variants */
  modes?: {
    [modeName: string]: {
      [colorName: string]: string;
    };
  };
}

interface ColorModeOptions {
  /** Initial color mode */
  initialColorModeName?: string;
  /** Use system preference for initial mode */
  useColorSchemeMediaQuery?: boolean;
  /** Use custom color mode storage */
  useLocalStorage?: boolean;
}

Usage Examples:

// Color mode configuration in theme
const theme = {
  initialColorModeName: 'light',
  useColorSchemeMediaQuery: true,
  colors: {
    text: '#000',
    background: '#fff',
    primary: '#007acc',
    modes: {
      dark: {
        text: '#fff',
        background: '#111',
        primary: '#3eb8ff'
      },
      sepia: {
        text: '#5c4e37',
        background: '#f4f3e8',
        primary: '#8b4513'
      }
    }
  }
}

// Component using color mode
import { useColorMode } from 'theme-ui'

function ColorModeToggle() {
  const [colorMode, setColorMode] = useColorMode()
  
  return (
    <button
      onClick={() => {
        const modes = ['light', 'dark', 'sepia']
        const next = modes[(modes.indexOf(colorMode) + 1) % modes.length]
        setColorMode(next)
      }}
    >
      Switch to {colorMode === 'light' ? 'dark' : 'light'} mode
    </button>
  )
}

Global Styles

Theme UI supports global styles and element styling through the styles object in the theme.

interface ThemeStyles {
  /** Root element styles */
  root?: ThemeUIStyleObject;
  /** HTML element styles by tag name */
  [element: string]: ThemeUIStyleObject | undefined;
}

interface GlobalStylesProps {
  styles?: ThemeStyles;
}

function Global(props: GlobalStylesProps): JSX.Element;

Usage Examples:

// Global styles in theme
const theme = {
  styles: {
    root: {
      fontFamily: 'body',
      lineHeight: 'body',
      fontWeight: 'body',
      color: 'text',
      bg: 'background',
      margin: 0,
      padding: 0,
      boxSizing: 'border-box'
    },
    h1: {
      fontFamily: 'heading',
      fontWeight: 'bold',
      fontSize: 6,
      lineHeight: 'title',
      color: 'text',
      mt: 0,
      mb: 3
    },
    h2: {
      fontFamily: 'heading',
      fontWeight: 'bold',
      fontSize: 5,
      lineHeight: 'title',
      color: 'text',
      mt: 0,
      mb: 3
    },
    p: {
      fontFamily: 'body',
      fontSize: 2,
      lineHeight: 'copy',
      color: 'text',
      mt: 0,
      mb: 3
    },
    a: {
      color: 'primary',
      textDecoration: 'none',
      '&:hover': {
        textDecoration: 'underline'
      }
    }
  }
}

// Manual global styles injection
import { Global } from 'theme-ui'

function App() {
  return (
    <>
      <Global
        styles={{
          '*': {
            boxSizing: 'border-box'
          },
          body: {
            margin: 0,
            fontFamily: 'system-ui'
          }
        }}
      />
      <main>App content</main>
    </>
  )
}

Component Variants

Theme UI supports component variants for consistent styling patterns across your design system.

interface ComponentVariants {
  [componentName: string]: {
    [variantName: string]: ThemeUIStyleObject;
  };
}

interface VariantProps {
  /** Component variant name */
  variant?: string;
}

Usage Examples:

// Component variants in theme
const theme = {
  buttons: {
    primary: {
      bg: 'primary',
      color: 'white',
      border: 'none',
      borderRadius: 'default',
      px: 4,
      py: 2,
      fontSize: 2,
      fontWeight: 'semibold',
      cursor: 'pointer',
      '&:hover': {
        bg: 'secondary'
      }
    },
    secondary: {
      bg: 'transparent',
      color: 'primary',
      border: '2px solid',
      borderColor: 'primary',
      borderRadius: 'default',
      px: 4,
      py: 2,
      fontSize: 2,
      fontWeight: 'semibold',
      cursor: 'pointer',
      '&:hover': {
        bg: 'primary',
        color: 'white'
      }
    },
    ghost: {
      bg: 'transparent',
      color: 'text',
      border: 'none',
      px: 4,
      py: 2,
      fontSize: 2,
      fontWeight: 'normal',
      cursor: 'pointer',
      '&:hover': {
        bg: 'muted'
      }
    }
  },
  
  cards: {
    primary: {
      bg: 'background',
      border: '1px solid',
      borderColor: 'muted',
      borderRadius: 'default',
      p: 4,
      boxShadow: 'sm'
    },
    elevated: {
      bg: 'background',
      border: 'none',
      borderRadius: 'lg',
      p: 4,
      boxShadow: 'lg'
    }
  },
  
  text: {
    heading: {
      fontFamily: 'heading',
      fontWeight: 'bold',
      lineHeight: 'title',
      color: 'text'
    },
    body: {
      fontFamily: 'body',
      fontWeight: 'normal',
      lineHeight: 'copy',
      color: 'text'
    },
    caption: {
      fontFamily: 'body',
      fontSize: 1,
      fontWeight: 'normal',
      lineHeight: 'copy',
      color: 'muted'
    }
  }
}

// Using variants in components
import { Button, Card, Text } from 'theme-ui'

function Example() {
  return (
    <Card variant="elevated">
      <Text variant="heading" as="h2">
        Card Title
      </Text>
      <Text variant="body">
        Card content goes here.
      </Text>
      <Button variant="primary">
        Primary Action
      </Button>
      <Button variant="secondary" sx={{ ml: 2 }}>
        Secondary Action
      </Button>
    </Card>
  )
}

BaseStyles Component

The BaseStyles component applies base theme styles to its children, useful for styling content from external sources.

interface BaseStylesProps extends SxProp {
  /** Child content to apply base styles to */
  children?: React.ReactNode;
  [key: string]: any;
}

function BaseStyles(props: BaseStylesProps): JSX.Element;

Usage Examples:

import { BaseStyles } from 'theme-ui'

// Apply theme styles to markdown content
function MarkdownContent({ html }) {
  return (
    <BaseStyles>
      <div dangerouslySetInnerHTML={{ __html: html }} />
    </BaseStyles>
  )
}

// Wrap external content
function ExternalContent({ children }) {
  return (
    <BaseStyles sx={{ 
      '& h1': { fontSize: 5 },
      '& p': { mb: 3 }
    }}>
      {children}
    </BaseStyles>
  )
}

Flash Prevention

Theme UI includes utilities to prevent flash of unstyled content (FOUC) during color mode transitions.

/**
 * Script component to prevent color mode flash during SSR hydration
 */
function InitializeColorMode(): JSX.Element;

Usage Examples:

// In your app's document head (Next.js _document.js)
import { InitializeColorMode } from 'theme-ui'

export default function Document() {
  return (
    <Html>
      <Head />
      <body>
        <InitializeColorMode />
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

// In Gatsby (handled automatically by gatsby-plugin-theme-ui)
// No manual setup required

Types

interface Theme {
  colors?: ColorTheme;
  fonts?: { [key: string]: string };
  fontSizes?: (string | number)[] | { [key: string]: string | number };
  fontWeights?: { [key: string]: string | number };
  lineHeights?: { [key: string]: string | number };
  space?: (string | number)[] | { [key: string]: string | number };
  sizes?: { [key: string]: string | number };
  radii?: { [key: string]: string | number };
  shadows?: { [key: string]: string };
  breakpoints?: Breakpoints;
  zIndices?: { [key: string]: number };
  styles?: ThemeStyles;
  [componentName: string]: any;
}

interface ColorTheme {
  [colorName: string]: string;
  modes?: {
    [modeName: string]: {
      [colorName: string]: string;
    };
  };
}

interface ThemeStyles {
  root?: ThemeUIStyleObject;
  [element: string]: ThemeUIStyleObject | undefined;
}

interface ThemeUIStyleObject {
  [property: string]: ResponsiveStyleValue<any>;
}

type ResponsiveStyleValue<T> = T | Array<T | null | undefined>;

interface Breakpoints extends Array<string> {
  [key: string]: string;
}

interface ThemeUIProviderProps {
  theme: Theme;
  children: React.ReactNode;
}

interface ColorModeOptions {
  initialColorModeName?: string;
  useColorSchemeMediaQuery?: boolean;
  useLocalStorage?: boolean;
}

interface VariantProps {
  variant?: string;
}

interface BaseStylesProps extends SxProp {
  children?: React.ReactNode;
  [key: string]: any;
}

interface ComponentVariants {
  [componentName: string]: {
    [variantName: string]: ThemeUIStyleObject;
  };
}