CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-theme-ui

The Design Graph Framework - a library for creating themeable user interfaces based on constraint-based design principles

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

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;
  };
}

docs

components.md

hooks-utilities.md

index.md

styling-system.md

theming.md

tile.json