Skip to main content

Quickstart Guide

This guide will walk you through creating a simple themed button component using Theme UI. You’ll learn the fundamentals of the sx prop, theme values, and variant styling.
This guide assumes you’ve already installed Theme UI and set up the ThemeUIProvider in your application.

Create Your First Themed Component

1

Create a theme file

First, let’s create a theme with button styles. Create or update your theme.js file:
theme.js
export default {
  // Font scales
  fonts: {
    body: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif',
  },
  fontSizes: [
    12, 14, 16, 20, 24, 32, 48, 64
  ],
  fontWeights: {
    body: 400,
    bold: 700,
  },
  
  // Spacing scale
  space: [
    0, 4, 8, 16, 32, 64, 128, 256
  ],
  
  // Color palette
  colors: {
    text: '#000',
    background: '#fff',
    primary: '#07c',
    secondary: '#639',
    muted: '#f6f6f9',
  },
  
  // Button variants
  buttons: {
    primary: {
      color: 'white',
      bg: 'primary',
      fontWeight: 'bold',
      '&:hover': {
        bg: 'secondary',
      },
    },
    secondary: {
      color: 'text',
      bg: 'muted',
    },
  },
}
This theme defines:
  • Font and spacing scales that components can reference by index
  • A color palette with semantic names
  • Button variants with different styles
2

Add the ThemeUIProvider

Wrap your application with the provider. If you haven’t done this yet:
App.jsx
import { ThemeUIProvider } from 'theme-ui'
import theme from './theme'
import Button from './Button'

export default function App() {
  return (
    <ThemeUIProvider theme={theme}>
      <div>
        <h1>My Themed App</h1>
        <Button />
      </div>
    </ThemeUIProvider>
  )
}
3

Create a custom button component

Create a new file called Button.jsx and add the JSX pragma at the top:
Button.jsx
/** @jsxImportSource theme-ui */

export default function Button() {
  return (
    <button
      sx={{
        // Reference theme values
        color: 'white',
        bg: 'primary',
        border: 0,
        borderRadius: 4,
        
        // Use spacing scale
        px: 3,  // theme.space[3] = 16px
        py: 2,  // theme.space[2] = 8px
        
        // Use font scale
        fontSize: 2,  // theme.fontSizes[2] = 16px
        fontWeight: 'bold',
        
        // Add interactivity
        cursor: 'pointer',
        '&:hover': {
          bg: 'secondary',
        },
      }}
    >
      Click Me
    </button>
  )
}
Don’t forget the /** @jsxImportSource theme-ui */ pragma! Without it, the sx prop won’t work.
4

Use responsive styles

Make your button responsive by using arrays for style values:
Button.jsx
/** @jsxImportSource theme-ui */

export default function Button() {
  return (
    <button
      sx={{
        color: 'white',
        bg: 'primary',
        border: 0,
        borderRadius: 4,
        
        // Responsive padding: small on mobile, larger on desktop
        px: [2, 3, 4],  // 8px, 16px, 32px
        py: [1, 2, 3],  // 4px, 8px, 16px
        
        // Responsive font size
        fontSize: [1, 2, 3],  // 14px, 16px, 20px
        fontWeight: 'bold',
        
        cursor: 'pointer',
        '&:hover': {
          bg: 'secondary',
        },
      }}
    >
      Click Me
    </button>
  )
}
The array syntax applies styles mobile-first:
  • First value: all viewports
  • Second value: first breakpoint and up (typically 40em/640px)
  • Third value: second breakpoint and up (typically 52em/832px)
5

Use theme variants

Instead of defining all styles inline, reference the button variant from your theme:
Button.jsx
/** @jsxImportSource theme-ui */

export default function Button({ variant = 'primary', children }) {
  return (
    <button
      sx={{
        // Apply the variant from theme.buttons
        variant: `buttons.${variant}`,
        
        // Add base styles
        appearance: 'none',
        display: 'inline-block',
        textAlign: 'center',
        lineHeight: 'inherit',
        textDecoration: 'none',
        fontSize: 'inherit',
        px: 3,
        py: 2,
        border: 0,
        borderRadius: 4,
        cursor: 'pointer',
      }}
    >
      {children || 'Click Me'}
    </button>
  )
}
Now you can use different button styles:
<Button variant="primary">Primary Button</Button>
<Button variant="secondary">Secondary Button</Button>

Using Theme UI Components

Theme UI also provides pre-built components. Here’s how to use the built-in Button component:
/** @jsxImportSource theme-ui */
import { Button } from 'theme-ui'

export default function App() {
  return (
    <div>
      <Button>Primary Button</Button>
      <Button variant="secondary" sx={{ ml: 2 }}>
        Secondary Button
      </Button>
    </div>
  )
}
The built-in Button component:
  • Automatically references theme.buttons variants
  • Supports the sx prop for custom overrides
  • Includes default styles for common button properties
  • Uses variant="primary" by default
You can use the sx prop on Theme UI components to override or extend variant styles.

Complete Example

Here’s a complete working example with a theme, provider, and themed button:
export default {
  fonts: {
    body: 'system-ui, sans-serif',
  },
  fontSizes: [12, 14, 16, 20, 24, 32],
  space: [0, 4, 8, 16, 32, 64],
  colors: {
    text: '#000',
    background: '#fff',
    primary: '#07c',
    secondary: '#639',
    muted: '#f6f6f9',
  },
  buttons: {
    primary: {
      color: 'white',
      bg: 'primary',
      '&:hover': {
        bg: 'secondary',
      },
    },
    secondary: {
      color: 'text',
      bg: 'muted',
    },
  },
}

Key Concepts Learned

  1. The sx prop: Apply styles that reference your theme
  2. Theme values: Use semantic names and scale indices instead of hard-coded values
  3. Variants: Define reusable style patterns in your theme
  4. Responsive styles: Use arrays for mobile-first responsive design
  5. JSX pragma: Enable the sx prop with /** @jsxImportSource theme-ui */

Next Steps

Now that you’ve built your first themed component, explore more features:

Color Modes

Add dark mode support to your application

Components

Explore Theme UI’s built-in components

Theming

Learn about the theme specification

Responsive Styles

Master responsive design patterns

Build docs developers (and LLMs) love