Skip to main content

Theming

Reshaped provides a comprehensive theming system that allows you to customize the visual appearance of your application. The theme system is built on design tokens and supports multiple color modes out of the box.

Theme Provider

Wrap your application with the Reshaped component to enable theming:
import { Reshaped } from 'reshaped';
import 'reshaped/themes/reshaped/theme.css';

function App() {
  return (
    <Reshaped theme="reshaped" defaultColorMode="light">
      {/* Your app content */}
    </Reshaped>
  );
}

Available Props

The Reshaped component accepts the following theming-related props:
PropTypeDescription
themestring | string[]Theme name(s) to use (controlled mode)
defaultThemestring | string[]Default theme name(s) (uncontrolled mode)
colorMode'light' | 'dark'Color mode (controlled mode)
defaultColorMode'light' | 'dark'Default color mode (uncontrolled mode)
scopedbooleanEnable scoped theming for nested providers
Use controlled mode (theme, colorMode) when you want to manage the theme state yourself. Use uncontrolled mode (defaultTheme, defaultColorMode) to let Reshaped manage the state internally.

Built-in Themes

Reshaped includes several pre-built themes:
  • reshaped - The default Reshaped theme
  • slate - A modern, muted color palette
  • figma - Inspired by Figma’s design system
Import theme CSS files to use them:
import 'reshaped/themes/reshaped/theme.css'; // Default theme
import 'reshaped/themes/slate/theme.css';    // Slate theme
import 'reshaped/themes/figma/theme.css';    // Figma theme

Color Modes

Reshaped supports light and dark color modes. Each theme automatically adapts to the current color mode.

Using the useTheme Hook

Access and control the theme and color mode using the useTheme hook:
import { useTheme } from 'reshaped';

function ThemeToggle() {
  const { colorMode, setColorMode, theme, setTheme } = useTheme();

  return (
    <Button
      onClick={() => setColorMode(colorMode === 'light' ? 'dark' : 'light')}
    >
      Toggle to {colorMode === 'light' ? 'Dark' : 'Light'} Mode
    </Button>
  );
}

useTheme Return Values

PropertyTypeDescription
themestring | string[]Current theme name(s)
setTheme(theme: string | string[]) => voidUpdate the theme
rootThemestring | string[]Root provider’s theme
setRootTheme(theme: string | string[]) => voidUpdate the root theme
colorMode'light' | 'dark'Current color mode
setColorMode(mode: 'light' | 'dark') => voidUpdate the color mode
invertColorMode() => voidToggle between light and dark

Nested Themes

You can nest Theme components to apply different themes to specific parts of your application:
import { Reshaped, Theme } from 'reshaped';

function App() {
  return (
    <Reshaped theme="reshaped" defaultColorMode="light">
      <div>
        <p>This uses the reshaped theme</p>
        
        <Theme name="slate">
          <p>This uses the slate theme</p>
        </Theme>
        
        <Theme colorMode="inverted">
          <p>This uses the opposite color mode</p>
        </Theme>
      </div>
    </Reshaped>
  );
}
Use colorMode="inverted" to automatically flip the color mode within a specific section.

Design Tokens

Reshaped themes are built on design tokens defined in CSS custom properties. Each theme includes tokens for:
  • Colors - Background, foreground, border colors with semantic naming
  • Typography - Font families, sizes, weights, and line heights
  • Spacing - Base unit system (4px by default)
  • Radius - Border radius values (small, medium, large)
  • Shadows - Elevation shadows (raised, overlay)
  • Duration - Animation durations (rapid, fast, medium, slow)
  • Easing - Animation timing functions

Example Theme Tokens

[data-rs-theme~="reshaped"] {
  /* Typography */
  --rs-font-family-body: Inter, -apple-system, sans-serif;
  --rs-font-size-body-2: 1rem;
  --rs-line-height-body-2: 1.5rem;
  --rs-font-weight-medium: 500;
  
  /* Spacing */
  --rs-unit-base: 4px;
  --rs-unit-x4: 16px;
  
  /* Colors */
  --rs-color-background-primary: #5a58f2;
  --rs-color-foreground-neutral: #14181f;
  
  /* Border radius */
  --rs-radius-small: 4px;
  --rs-radius-medium: 8px;
  --rs-radius-large: 12px;
  
  /* Duration */
  --rs-duration-fast: 200ms;
  --rs-duration-medium: 300ms;
}

Scoped Theming

When using Reshaped in a context where it’s not at the application root, enable scoped mode:
import { Reshaped } from 'reshaped';

function WidgetInExistingApp() {
  return (
    <Reshaped theme="reshaped" defaultColorMode="light" scoped>
      {/* Your widget content */}
    </Reshaped>
  );
}
Scoped mode adds additional wrapper elements. Only use it when necessary.

Custom Themes

You can create custom themes by defining your own design tokens. Theme definitions use a JSON structure:
{
  "fontFamily": {
    "body": {
      "family": "Your Font, sans-serif"
    }
  },
  "color": {
    "backgroundPrimary": {
      "hex": "#5a58f2",
      "hexDark": "#524fea"
    }
  },
  "unit": {
    "base": { "px": 4 }
  }
}
Theme JSON files are transformed into CSS custom properties that components consume.

TypeScript Support

All theme-related APIs are fully typed:
import type { ColorMode, Theme } from 'reshaped';

interface ThemeSettings {
  theme: Theme;
  colorMode: ColorMode;
}

const settings: ThemeSettings = {
  theme: 'reshaped',
  colorMode: 'dark',
};

Best Practices

  1. Place the provider at the root - Wrap your entire app with Reshaped for consistent theming
  2. Import theme CSS once - Import theme stylesheets in your main app file
  3. Use controlled mode for persistence - Sync colorMode with localStorage or user preferences
  4. Leverage semantic colors - Use token-based colors instead of hardcoding values
  5. Test both color modes - Ensure your UI works well in light and dark modes

Build docs developers (and LLMs) love