Skip to Content
Docs🎨 ⏐ ThemeingGetting Started

Getting Started

Reablocks theming is seamlessly integrated into the Tailwind CSS configuration, allowing for a highly customizable design system. This approach leverages Tailwind’s utility-first CSS to offer you an extensive range of design tokens such as colors, border radii, shadows, and font sizes. In addition, Reablocks provides a set of pre-defined Storybook blocks that can be used to quickly build and customize your UI components in a Storybook environment.

Integrating Reablocks Theme in Your Application

To get started with Reablocks theming, you first need to incorporate the ThemeProvider into the root of your application. This provider applies the selected theme across all your components, ensuring a consistent look and feel.

  • Basic Theme Example
import { ThemeProvider, theme } from 'reablocks'; export const App = () => ( <ThemeProvider theme={theme}> <YourComponents /> </ThemeProvider> );

Result: In this example, the darkTheme from Reablocks is applied to your application. Simply wrap your component hierarchy with the ThemeProvider, and the theme is automatically applied.

Extending the Reablocks Theme

Reablocks allows you to extend its themes to customize according to your design requirements. You can modify existing styles or add new ones to fit your application’s unique design language.

  • Customizing Theme Example
import { ThemeProvider, theme, extendTheme, PartialReablocksTheme } from 'reablocks'; const customTheme: PartialReablocksTheme = { components: { button: { base: 'bg-lime-600 text-gray-300', variants: { filled: 'bg-lime-600 hover:bg-lime-700', outline: 'bg-transparent border-lime-600 border', text: 'bg-transparent border-0' }, sizes: { small: 'p-2', medium: 'p-3', large: 'p-4' } } } };

You can extend the colors, variants, and sizes of applicable components with any custom values. This allows you to create properties that are specific to your app’s design system.

const customTheme: PartialReablocksTheme = { components: { button: { base: 'bg-lime-600 text-gray-300', variants: { ... destructive: 'bg-red-600 hover:bg-red-700', }, sizes: { ... xxl: 'p-6', } } } };

By using the extendTheme function, you can merge your customizations with the base theme, resulting in a coherent design system that still benefits from Reablocks’ foundation.

export const App = () => ( <ThemeProvider theme={extendTheme(theme, customTheme)}> <YourComponents /> </ThemeProvider> );

Result: This example demonstrates how to create a customTheme that extends the darkTheme.

 

Switching themes

Simply switch the class or the data-theme attribute on the html element to change the theme.

<html class='theme-dark'> // or class='theme-light' ... </html>

Defining Reablocks Tokens with TailwindCSS

Reablocks themes can further leverage TailwindCSS’s configuration to define custom design tokens. This allows for an even deeper level of customization, integrating seamlessly with your TailwindCSS setup.

Already on the Unify design system in Figma? Skip the hand-rolled tokens and use the Unify Theme instead — a three-level token system (primitives → semantic aliases → Tailwind utilities) with per-component detail tokens and pre-styled component themes, exported directly from your Figma file via the Reablocks Figma Plugin  for end-to-end design-to-code sync. (If you’re not on the Unify Figma library, stay on this page — Unify won’t give you much without it.)

  • Reablocks Tokens for dart/light themes
/* Color tokens */ :root, :host { --reablocks-theme: dark; /* Primary colors */ --primary: var(--color-blue-500); --primary-active: var(--color-blue-500); --primary-hover: var(--color-blue-400); --primary-inactive: var(--color-blue-200); /* Secondary colors */ --secondary: var(--color-charade); --secondary-active: var(--color-charade); --secondary-hover: var(--color-gray-700); --secondary-inactive: var(--color-gray-600); /* Success colors */ --success: var(--color-green-500); --success-active: var(--color-green-500); --success-hover: var(--color-green-400); --success-background: var(--color-green-950); /* Error colors */ --error: var(--color-red-500); --error-active: var(--color-red-500); --error-hover: var(--color-red-400); --error-background: var(--color-red-950); /* Warning colors */ --warning: var(--color-orange-500); --warning-active: var(--color-orange-500); --warning-hover: var(--color-orange-400); --warning-background: var(--color-orange-950); /* Info colors */ --info: var(--color-blue-500); --info-active: var(--color-blue-500); --info-hover: var(--color-blue-400); --info-background: var(--color-blue-950); /* Panel colors */ --panel: var(--color-black-pearl); --panel-accent: var(--color-charade); /* Surface colors */ --surface: var(--color-charade); --surface-accent: var(--color-blue-500); /* Text colors */ --text-primary: var(--color-athens-gray); --text-secondary: var(--color-waterloo); /* Custom Backgrounds */ --bottom-border-glow: radial-gradient( circle at center, var(--color-anakiwa) 0, blue, transparent 100% ); --button-gradient: linear-gradient( 283deg, #0808a5 0%, rgba(8, 8, 165, 0) 100% ); --button-gradient-hover: linear-gradient( 283deg, #44f 0%, rgba(23, 23, 255, 0.1) 100% ); --button-gradient-focus: linear-gradient( 283deg, #0d0dd2 0%, rgba(23, 23, 255, 0.1) 100% ); &.theme-light, &[data-theme="light"] { --reablocks-theme: light; /* Primary colors */ --primary: var(--color-blue-500); --primary-active: var(--color-blue-500); --primary-hover: var(--color-blue-600); --primary-inactive: var(--color-gray-500); /* Secondary colors */ --secondary: var(--color-blue-200); --secondary-active: var(--color-blue-200); --secondary-hover: var(--color-blue-300); --secondary-inactive: var(--color-waterloo); /* Success colors */ --success: var(--color-green-500); --success-active: var(--color-green-500); --success-hover: var(--color-green-600); --success-background: var(--color-green-100); /* Error colors */ --error: var(--color-red-500); --error-active: var(--color-red-400); --error-hover: var(--color-red-600); --error-background: var(--color-red-100); /* Warning colors */ --warning: var(--color-orange-500); --warning-active: var(--color-orange-500); --warning-hover: var(--color-orange-600); --warning-background: var(--color-orange-100); /* Info colors */ --info: var(--color-blue-500); --info-active: var(--color-blue-500); --info-hover: var(--color-blue-600); --info-background: var(--color-blue-100); /* Panel colors */ --panel: var(--color-white); --panel-accent: var(--color-mystic); /* Surface colors */ --surface: var(--color-gray-300); --surface-accent: var(--color-blue-500); /* Text colors */ --text-primary: var(--color-vulcan); --text-secondary: var(--color-gray-700); } }

These tokens are used to define the colors for the dark and light themes.

  • TailwindCSS Configuration Example
/* Custom variants */ @custom-variant dark (&:where(.theme-dark, .theme-dark *, [data-theme=dark], [data-theme=dark] *)); @custom-variant light (&:where(.theme-light, .theme-light *, [data-theme=light], [data-theme=light] *)); @custom-variant disabled-within (&:has(input:is(:disabled), textarea:is(:disabled), button:is(:disabled))); /* Define theme tokens */ @theme { /* Fonts */ --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; --font-mono: Fira Code, monospace; /* Font sizes */ --text-xs: 0.625rem; /* 10px */ --text-xs--line-height: 1rem; --text-sm: 0.75rem; /* 12px */ --text-sm--line-height: 1rem; --text-base: 0.875rem; /* 14px */ --text-base--line-height: 1.25rem; --text-lg: 1rem; /* 16px */ --text-lg--line-height: 1.5rem; /* Primary colors */ --color-primary: var(--primary); --color-primary-active: var(--primary-active); --color-primary-hover: var(--primary-hover); --color-primary-inactive: var(--primary-inactive); /* Secondary colors */ --color-secondary: var(--secondary); --color-secondary-active: var(--secondary-active); --color-secondary-hover: var(--secondary-hover); --color-secondary-inactive: var(--secondary-inactive); /* Success colors */ --color-success: var(--success); --color-success-active: var(--success-active); --color-success-hover: var(--success-hover); --color-success-background: var(--success-background); /* Error colors */ --color-error: var(--error); --color-error-active: var(--error-active); --color-error-hover: var(--error-hover); --color-error-background: var(--error-background); /* Warning colors */ --color-warning: var(--warning); --color-warning-active: var(--warning-active); --color-warning-hover: var(--warning-hover); --color-warning-background: var(--warning-background); /* Info colors */ --color-info: var(--info); --color-info-active: var(--info-active); --color-info-hover: var(--info-hover); --color-info-background: var(--info-background); /* Panel colors */ --color-panel: var(--panel); --color-panel-accent: var(--panel-accent); /* Surface colors */ --color-surface: var(--surface); --color-surface-accent: var(--surface-accent); /* Text colors */ --color-text-primary: var(--text-primary); --color-text-secondary: var(--text-secondary); /* Base colors */ --color-white: #ffffff; --color-black: #000000; /* Gray scale */ --color-gray-*: initial; --color-gray-100: #f7f7fa; --color-gray-200: #e6e6f0; --color-gray-300: #c9c9d6; --color-gray-400: #77778c; --color-gray-500: #5c5c73; --color-gray-600: #3d3d4d; --color-gray-700: #242433; --color-gray-800: #1e1e2e; --color-gray-900: #11111f; --color-gray-950: #02020f; /* Magenta */ --color-magenta-*: initial; --color-magenta-100: #fae5f6; --color-magenta-200: #f1bfe9; --color-magenta-300: #e480d3; --color-magenta-400: #d740be; --color-magenta-500: #c900a8; --color-magenta-600: #ab018f; --color-magenta-700: #8c0276; --color-magenta-800: #6e025c; --color-magenta-900: #4f0343; --color-magenta-950: #31042a; /* Pink */ --color-pink-*: initial; --color-pink-100: #fde5f1; --color-pink-200: #f9bfdb; --color-pink-300: #f480b7; --color-pink-400: #ee4094; --color-pink-500: #de006b; --color-pink-600: #bb015a; --color-pink-700: #98014a; --color-pink-800: #740239; --color-pink-900: #510229; --color-pink-950: #2e0318; /* Lime */ --color-lime-*: initial; --color-lime-100: #f4fae5; --color-lime-200: #e3f3bf; --color-lime-300: #c6e880; --color-lime-400: #aadc40; --color-lime-500: #8ed000; --color-lime-600: #78b001; --color-lime-700: #628f01; --color-lime-800: #4c6f02; --color-lime-900: #364e02; --color-lime-950: #202e03; /* Teal */ --color-teal-*: initial; --color-teal-100: #e5fbf9; --color-teal-200: #bff6f0; --color-teal-300: #80ede0; --color-teal-400: #40e5d1; --color-teal-500: #00dcc2; --color-teal-600: #00c2ab; --color-teal-700: #019a88; --color-teal-800: #017365; --color-teal-900: #024b42; --color-teal-950: #02231f; /* Cyan */ --color-cyan-*: initial; --color-cyan-100: #e5f9fe; --color-cyan-200: #bff0fb; --color-cyan-300: #80e2f8; --color-cyan-400: #40d3f4; --color-cyan-500: #00c5f0; --color-cyan-600: #01a7cb; --color-cyan-700: #0289a6; --color-cyan-800: #036b82; --color-cyan-900: #044d5d; --color-cyan-950: #052f38; /* Violet */ --color-violet-*: initial; --color-violet-100: #f0e8fd; --color-violet-200: #dac5f9; --color-violet-300: #b58bf3; --color-violet-400: #9152ee; --color-violet-500: #6c18e8; --color-violet-600: #5b14c5; --color-violet-700: #4b10a1; --color-violet-800: #3a0d7e; --color-violet-900: #2a095b; --color-violet-950: #190537; /* Purple */ --color-purple-*: initial; --color-purple-100: #f3e5fc; --color-purple-200: #e2bff7; --color-purple-300: #c580f0; --color-purple-400: #a840e8; --color-purple-500: #8b00e0; --color-purple-600: #7501bc; --color-purple-700: #5f0298; --color-purple-800: #490274; --color-purple-900: #330350; --color-purple-950: #1d042d; /* Red */ --color-red-*: initial; --color-red-100: #fce5e6; --color-red-200: #f7bfc1; --color-red-300: #f08083; --color-red-400: #e84045; --color-red-500: #e00007; --color-red-600: #b70006; --color-red-700: #8e0005; --color-red-800: #660104; --color-red-900: #3d0103; --color-red-950: #200204; /* Orange */ --color-orange-*: initial; --color-orange-100: #fef3e5; --color-orange-200: #fde1bf; --color-orange-300: #fbc280; --color-orange-400: #f8a340; --color-orange-500: #f68500; --color-orange-600: #cb6e00; --color-orange-700: #9f5701; --color-orange-800: #743f01; --color-orange-900: #482802; --color-orange-950: #251602; /* Yellow */ --color-yellow-*: initial; --color-yellow-100: #fff9e5; --color-yellow-200: #fff1bf; --color-yellow-300: #ffe380; --color-yellow-400: #ffd440; --color-yellow-500: #ffc600; --color-yellow-600: #d2a300; --color-yellow-700: #a58001; --color-yellow-800: #785e01; --color-yellow-900: #4b3b02; --color-yellow-950: #261f03; /* Green */ --color-green-*: initial; --color-green-100: #eef8e9; --color-green-200: #d5efc8; --color-green-300: #aadf91; --color-green-400: #80ce5b; --color-green-500: #55be24; --color-green-600: #469d1d; --color-green-700: #377c16; --color-green-800: #275c10; --color-green-900: #183b09; --color-green-950: #091a02; /* Blue */ --color-blue-*: initial; --color-blue-100: #e7efff; --color-blue-200: #c3d7ff; --color-blue-300: #87aeff; --color-blue-400: #4c86ff; --color-blue-500: #105eff; --color-blue-600: #0d4ed2; --color-blue-700: #0a3da6; --color-blue-800: #082d79; --color-blue-900: #051c4c; --color-blue-950: #041028; /* Named colors */ --color-black-pearl: #02020f; --color-athens-gray: #f7f7fa; --color-mystic: #e6e6f0; --color-vulcan: #11111f; --color-charade: #242433; --color-waterloo: #77778c; --color-anakiwa: #93b6ff; } /* Static theme tokens - emits CSS custom properties for runtime access */ @theme static { /* Fonts */ --font-sans: Inter, sans-serif; --font-mono: Fira Code, monospace; /* Font sizes */ --text-xs: 0.625rem; /* 10px */ --text-xs--line-height: 1rem; --text-sm: 0.75rem; /* 12px */ --text-sm--line-height: 1rem; --text-base: 0.875rem; /* 14px */ --text-base--line-height: 1.25rem; --text-lg: 1rem; /* 16px */ --text-lg--line-height: 1.5rem; /* Spacing */ --spacing: 0.25rem; /* Border radius */ --radius-xs: 0.125rem; --radius-sm: 0.25rem; --radius-md: 0.375rem; --radius-lg: 0.5rem; --radius-xl: 0.75rem; --radius-2xl: 1rem; --radius-3xl: 1.5rem; --radius-4xl: 2rem; /* Shadows */ --shadow-2xs: 0 1px rgb(0 0 0 / 0.05); --shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.05); --shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25); }

Result: In this configuration, we extend the default TailwindCSS theme to include custom colors for primary and secondary palettes. The custom variants are used to apply the theme dark or light to elements.

 

Creating a reusable component with a custom theme

You can also pass a theme directly to any component as a prop. This will override the theme for that component, but not its children. This is useful if you want to create a reusable component with a theme that differs from the global theme.

import { tooltipTheme, TooltipTheme, extendComponentTheme } from 'reablocks'; const customTheme = extendComponentTheme<TooltipTheme>(tooltipTheme, { base: 'rounded bg-green-800 text-white font-bold p-3 text-base' }); export const CustomTooltip = () => ( <Tooltip theme={customTheme} content="Hi there">Hover me</Tooltip> );
Last updated on