or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

index.mddocs/

@emotion/react Theming

@emotion/react provides CSS-in-JS theming utilities for React applications. It offers a comprehensive API for theme management through React Context, including a theme provider, theme consumer hook, higher-order component for theme injection, and direct context access.

Note: This functionality was previously available in the deprecated emotion-theming package, which was migrated to @emotion/react in version 11.0.0.

Package Information

  • Package Name: @emotion/react
  • Package Type: npm
  • Language: JavaScript with Flow types and TypeScript definitions
  • Installation: npm install @emotion/react

Core Imports

import { ThemeProvider, useTheme, withTheme, ThemeContext } from '@emotion/react';

For CommonJS:

const { ThemeProvider, useTheme, withTheme, ThemeContext } = require('@emotion/react');

Basic Usage

import React from 'react';
import { ThemeProvider, useTheme, withTheme } from '@emotion/react';

// Define your theme
const theme = {
  colors: {
    primary: '#007bff',
    secondary: '#6c757d'
  },
  spacing: {
    small: '8px',
    medium: '16px',
    large: '24px'
  }
};

// Using ThemeProvider to provide theme
function App() {
  return (
    <ThemeProvider theme={theme}>
      <Header />
      <Content />
    </ThemeProvider>
  );
}

// Using useTheme hook to consume theme
function Header() {
  const theme = useTheme();
  return (
    <header style={{ color: theme.colors.primary }}>
      My App
    </header>
  );
}

// Using withTheme HOC to inject theme as prop
const Content = withTheme(({ theme }) => (
  <main style={{ padding: theme.spacing.medium }}>
    Content here
  </main>
));

Capabilities

Theme Provider

React component that provides theme context to child components through React's Context API.

interface ThemeProviderProps {
  theme: object | ((outerTheme: object) => object);
  children: React.ReactNode;
}

declare const ThemeProvider: React.FC<ThemeProviderProps>;

Features:

  • Supports theme objects or theme functions for merging
  • Automatic theme merging when nested
  • Performance optimized with memoization
  • Validates theme objects in development mode

Usage with theme object:

const theme = { colors: { primary: '#007bff' } };

<ThemeProvider theme={theme}>
  <App />
</ThemeProvider>

Usage with theme function:

<ThemeProvider theme={(outerTheme) => ({ 
  ...outerTheme, 
  colors: { ...outerTheme.colors, primary: '#007bff' } 
})}>
  <App />
</ThemeProvider>

Theme Hook

React hook that returns the current theme from the nearest ThemeProvider.

declare function useTheme(): object;

Returns: The current theme object from ThemeContext

Usage:

function MyComponent() {
  const theme = useTheme();
  
  return (
    <div style={{ 
      color: theme.colors.primary,
      padding: theme.spacing.medium 
    }}>
      Themed content
    </div>
  );
}

Requirements: Must be used within a component tree that has a ThemeProvider ancestor.

Theme Higher-Order Component

Higher-order component that injects the current theme as a theme prop into the wrapped component.

declare function withTheme<C extends React.ComponentType<React.ComponentProps<C>>>(
  Component: C
): React.FC<DistributiveOmit<PropsOf<C>, 'theme'> & { theme?: Theme }>;

Parameters:

  • Component: React component that expects a theme prop

Returns: Enhanced component with theme automatically injected

Features:

  • Forwards refs using React.forwardRef
  • Preserves component static properties using hoist-non-react-statics
  • Sets appropriate displayName for debugging
  • TypeScript support with proper type inference

Usage:

// Component that expects theme prop
const Button = ({ theme, color, children, ...props }) => (
  <button 
    style={{ 
      backgroundColor: theme.colors[color],
      padding: theme.spacing.small 
    }}
    {...props}
  >
    {children}
  </button>
);

// Enhanced component with automatic theme injection
const ThemedButton = withTheme(Button);

// Usage - theme prop is automatically provided
<ThemedButton color="primary">Click me</ThemedButton>

Theme Context

React Context that provides direct access to the theme for advanced use cases.

declare const ThemeContext: React.Context<Theme>;

Usage:

import React from 'react';
import { ThemeContext } from '@emotion/react';

function AdvancedComponent() {
  const theme = React.useContext(ThemeContext);
  
  return (
    <div style={{ color: theme.colors.primary }}>
      Direct context access
    </div>
  );
}

When to use:

  • Custom hooks that need theme access
  • Components that need conditional theme consumption
  • Advanced theming patterns and abstractions

Theme Integration

CSS Prop Integration

The css prop can access theme through function interpolation:

import { css } from '@emotion/react';

function ThemedComponent() {
  return (
    <div
      css={theme => ({
        color: theme.colors.primary,
        padding: theme.spacing.medium,
        backgroundColor: theme.colors.background
      })}
    >
      Themed with css prop
    </div>
  );
}

ClassNames Component Integration

The ClassNames component provides theme in its render prop:

import { ClassNames } from '@emotion/react';

function ThemedWithClassNames() {
  return (
    <ClassNames>
      {({ css, theme }) => (
        <div
          className={css`
            color: ${theme.colors.primary};
            padding: ${theme.spacing.medium};
          `}
        >
          Themed with ClassNames
        </div>
      )}
    </ClassNames>
  );
}

Global Component Integration

The Global component can use theme in global styles:

import { Global } from '@emotion/react';

function GlobalThemedStyles() {
  return (
    <Global
      styles={theme => ({
        html: {
          backgroundColor: theme.colors.background,
          color: theme.colors.text
        },
        'h1, h2, h3': {
          color: theme.colors.primary
        }
      })}
    />
  );
}

Types

// Extensible theme interface
export interface Theme {}

// ThemeProvider props
interface ThemeProviderProps {
  theme: Partial<Theme> | ((outerTheme: Theme) => Theme);
  children?: React.ReactNode;
}

// useTheme hook type
declare function useTheme(): Theme;

// withTheme HOC type
type withTheme = <C extends React.ComponentType<React.ComponentProps<C>>>(
  component: C
) => React.FC<DistributiveOmit<PropsOf<C>, 'theme'> & { theme?: Theme }>;

// ThemeContext type
declare const ThemeContext: React.Context<Theme>;

// Helper types
type PropsOf<C extends keyof JSX.IntrinsicElements | React.JSXElementConstructor<any>> = 
  JSX.LibraryManagedAttributes<C, React.ComponentPropsWithRef<C>>;

type DistributiveOmit<T, K extends keyof any> = T extends any ? Omit<T, K> : never;

Error Handling

The library performs validation in development mode:

ThemeProvider validation:

  • Theme functions must return objects
  • Theme props must be plain objects (not arrays or null)
  • Throws descriptive errors for invalid theme types

Common errors:

// ❌ Invalid - theme function returning non-object
<ThemeProvider theme={() => null}>

// ❌ Invalid - theme prop as array
<ThemeProvider theme={['red', 'blue']}>

// ✅ Valid - theme object
<ThemeProvider theme={{ color: 'red' }}>

// ✅ Valid - theme function returning object
<ThemeProvider theme={(outer) => ({ ...outer, color: 'red' })}>

Migration Guide

From emotion-theming to @emotion/react:

  1. Update imports:

    // Before
    import { ThemeProvider, useTheme, withTheme } from 'emotion-theming';
    
    // After  
    import { ThemeProvider, useTheme, withTheme, ThemeContext } from '@emotion/react';
  2. No API changes required - the functionality is identical, with the addition of ThemeContext export

  3. Update package.json:

    {
      "dependencies": {
        "@emotion/react": "^11.0.0"
      }
    }
  4. Remove emotion-theming dependency:

    npm uninstall emotion-theming

The migration is a simple import path change with no functional differences, plus access to additional integration features with other @emotion/react components.