or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

components.mdhooks-utilities.mdindex.mdstyling-system.mdtheming.md
tile.json

styling-system.mddocs/

Styling System

The Theme UI styling system provides theme-aware styling through the sx prop, responsive design utilities, custom JSX runtime, and CSS-in-JS integration. It enables constraint-based design using theme scales and supports responsive breakpoints for mobile-first development.

Capabilities

JSX Function

The core JSX function that processes the sx prop and integrates with theme values for styling elements.

/**
 * Enhanced JSX function with sx prop support and theme integration
 * @param type - JSX element type or component
 * @param props - Element props including sx
 * @param children - Child elements
 * @returns JSX element with processed theme-aware styles
 */
function jsx(type: any, props: any, ...children: any[]): JSX.Element;

Usage Examples:

import { jsx } from 'theme-ui'

// Explicit jsx usage
const element = jsx('div', {
  sx: { color: 'primary', p: 3 }
}, 'Hello Theme UI')

// With custom pragma (automatic)
/** @jsxImportSource theme-ui */
const component = <div sx={{ color: 'primary', p: 3 }}>Hello</div>

Custom JSX Runtime

Theme UI provides custom JSX runtime entries for automatic sx prop processing without manual jsx imports.

// JSX Runtime Entries
import 'theme-ui/jsx-runtime'      // Production runtime
import 'theme-ui/jsx-dev-runtime'  // Development runtime with enhanced debugging

Usage Examples:

// In tsconfig.json or babel config
{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "theme-ui"
  }
}

// Or per-file pragma
/** @jsxImportSource theme-ui */
export default function Component() {
  return <div sx={{ bg: 'primary', p: 4 }}>Automatic sx processing</div>
}

The sx Prop

The sx prop accepts theme-aware style objects with support for responsive values, pseudo-selectors, and nested styles.

interface SxProp {
  /** Theme-aware style object supporting responsive values and theme lookups */
  sx?: ThemeUIStyleObject;
}

interface ThemeUIStyleObject {
  /** CSS properties with theme-aware values and responsive support */
  [property: string]: ResponsiveStyleValue<any>;
  
  /** Pseudo-selectors and nested styles */
  [selector: `&:${string}`]: ThemeUIStyleObject;
  [selector: `&[${string}]`]: ThemeUIStyleObject;
  [selector: `& ${string}`]: ThemeUIStyleObject;
}

type ResponsiveStyleValue<T> = T | Array<T | null | undefined>;

Usage Examples:

// Basic theme-aware styling
<Box sx={{
  color: 'primary',           // theme.colors.primary
  fontSize: 3,                // theme.fontSizes[3]
  margin: 2,                  // theme.space[2]
  fontFamily: 'heading'       // theme.fonts.heading
}} />

// Responsive values (mobile-first)
<Box sx={{
  fontSize: [2, 3, 4],        // 14px, 16px, 20px at breakpoints
  padding: [2, 3, 4, 5],      // 8px, 16px, 32px, 64px
  display: ['block', 'flex']   // block on mobile, flex on tablet+
}} />

// Pseudo-selectors and states
<Button sx={{
  bg: 'primary',
  '&:hover': {
    bg: 'secondary'
  },
  '&:focus': {
    outline: '2px solid',
    outlineColor: 'primary'
  },
  '&[disabled]': {
    opacity: 0.5
  }
}} />

// Nested selectors
<Card sx={{
  p: 3,
  '& h2': {
    color: 'heading',
    fontSize: 4
  },
  '& > p': {
    color: 'text',
    lineHeight: 'body'
  }
}} />

Responsive Design

Theme UI uses a mobile-first responsive approach with array-based responsive values and customizable breakpoints.

interface ResponsiveStyleValue<T> {
  /** Single value applied at all breakpoints */
  0: T;
  /** Array of values for responsive breakpoints (mobile-first) */
  1: Array<T | null | undefined>;
}

interface Breakpoints extends Array<string> {
  /** Named breakpoint aliases */
  [key: string]: string;
}

Usage Examples:

// Default breakpoints: [40em, 52em, 64em]
const theme = {
  breakpoints: ['40em', '52em', '64em', '80em'], // sm, md, lg, xl
}

// Responsive styling
<Box sx={{
  width: ['100%', '50%', '33.333%', '25%'], // Full, half, third, quarter
  padding: [1, 2, 3, 4],                    // 4px, 8px, 16px, 32px
  display: ['block', null, 'flex'],         // block mobile/tablet, flex desktop+
  flexDirection: [null, null, 'row', 'column'] // only applies at lg and xl
}} />

// Named breakpoints
<Text sx={{
  fontSize: {
    _: 2,      // base (mobile)
    sm: 3,     // small screens
    md: 4,     // medium screens
    lg: 5      // large screens
  }
}} />

CSS Utilities

Theme UI provides utility functions for working with styles and theme values outside of React components.

/**
 * Convert theme-aware style objects to CSS
 * @param styles - Style object with theme references
 * @returns Function that accepts theme and returns CSS object
 */
function css(styles: ThemeUIStyleObject): (theme: Theme) => CSSObject;

/**
 * Get nested values from objects using dot notation
 * @param object - Object to search
 * @param key - Dot-notation key path
 * @param fallback - Fallback value if key not found
 * @returns Retrieved value or fallback
 */
function get(object: object, key: string, fallback?: any): any;

Usage Examples:

import { css, get } from 'theme-ui'

// Generate CSS from theme-aware styles
const styles = css({
  color: 'primary',
  fontSize: 3,
  '&:hover': {
    color: 'secondary'
  }
})

// Use with emotion or other CSS-in-JS
const StyledDiv = styled.div(styles)

// Get theme values programmatically
const primaryColor = get(theme, 'colors.primary', '#000')
const fontSize3 = get(theme, 'fontSizes.3', '16px')
const nestedValue = get(theme, 'components.Button.primary.backgroundColor')

System Props

Many Theme UI components support system props for quick styling without the sx prop.

interface SystemProps {
  // Margin
  m?: ResponsiveStyleValue<string | number>;
  margin?: ResponsiveStyleValue<string | number>;
  mt?: ResponsiveStyleValue<string | number>;
  mr?: ResponsiveStyleValue<string | number>;
  mb?: ResponsiveStyleValue<string | number>;
  ml?: ResponsiveStyleValue<string | number>;
  mx?: ResponsiveStyleValue<string | number>;
  my?: ResponsiveStyleValue<string | number>;
  
  // Padding
  p?: ResponsiveStyleValue<string | number>;
  padding?: ResponsiveStyleValue<string | number>;
  pt?: ResponsiveStyleValue<string | number>;
  pr?: ResponsiveStyleValue<string | number>;
  pb?: ResponsiveStyleValue<string | number>;
  pl?: ResponsiveStyleValue<string | number>;
  px?: ResponsiveStyleValue<string | number>;
  py?: ResponsiveStyleValue<string | number>;
  
  // Colors
  color?: ResponsiveStyleValue<string>;
  bg?: ResponsiveStyleValue<string>;
  backgroundColor?: ResponsiveStyleValue<string>;
  
  // Typography
  fontSize?: ResponsiveStyleValue<string | number>;
  fontFamily?: ResponsiveStyleValue<string>;
  fontWeight?: ResponsiveStyleValue<string | number>;
  lineHeight?: ResponsiveStyleValue<string | number>;
  
  // Layout
  width?: ResponsiveStyleValue<string | number>;
  height?: ResponsiveStyleValue<string | number>;
  minWidth?: ResponsiveStyleValue<string | number>;
  maxWidth?: ResponsiveStyleValue<string | number>;
  minHeight?: ResponsiveStyleValue<string | number>;
  maxHeight?: ResponsiveStyleValue<string | number>;
}

Usage Examples:

// System props for quick styling
<Box 
  p={4}                    // padding: theme.space[4]
  m={[2, 3]}              // responsive margin
  bg="primary"            // background: theme.colors.primary
  color="white"           // color: theme.colors.white
  fontSize={[2, 3, 4]}    // responsive font size
  width="100%"            // width: 100%
  maxWidth={500}          // maxWidth: 500px
/>

// Combining system props with sx
<Button
  variant="primary"
  p={3}
  m={2}
  sx={{
    borderRadius: 'full',
    '&:hover': {
      transform: 'scale(1.05)'
    }
  }}
>
  Enhanced Button
</Button>

Theme-Aware Styling

All styling in Theme UI is theme-aware, automatically looking up values from the theme object and supporting design system constraints.

interface ThemeScale {
  /** Design system scale (colors, space, fontSizes, etc.) */
  [key: string]: any;
  [index: number]: any;
}

interface ThemeLookup {
  /** Theme scale reference by key */
  scale: string;
  /** Property name for CSS output */
  property: string;
  /** Transform function for values */
  transform?: (value: any, scale: ThemeScale) => any;
}

Usage Examples:

// Theme scales
const theme = {
  colors: {
    primary: '#007acc',
    secondary: '#ff6b6b',
    text: '#333',
    background: '#fff'
  },
  space: [0, 4, 8, 16, 32, 64, 128, 256],
  fontSizes: [12, 14, 16, 20, 24, 32, 48, 64],
  radii: {
    none: 0,
    sm: 2,
    md: 4,
    lg: 8,
    full: 9999
  }
}

// Automatic theme lookups
<Box sx={{
  color: 'primary',        // theme.colors.primary
  bg: 'secondary',         // theme.colors.secondary
  p: 3,                    // theme.space[3] = 16px
  fontSize: 4,             // theme.fontSizes[4] = 24px
  borderRadius: 'md',      // theme.radii.md = 4px
  boxShadow: 'card'        // theme.shadows.card
}} />

// Fallback to raw values when not in theme
<Box sx={{
  color: '#custom',        // Raw hex color
  padding: '1rem',         // Raw CSS value
  fontSize: '18px'         // Raw pixel value
}} />

Types

interface SxProp {
  sx?: ThemeUIStyleObject;
}

interface ThemeUIStyleObject {
  [property: string]: ResponsiveStyleValue<any>;
}

type ResponsiveStyleValue<T> = T | Array<T | null | undefined>;

interface CSSObject {
  [property: string]: any;
}

interface ThemeUICSSObject extends CSSObject {
  [property: string]: ResponsiveStyleValue<any>;
}

interface SystemProps {
  m?: ResponsiveStyleValue<string | number>;
  margin?: ResponsiveStyleValue<string | number>;
  mt?: ResponsiveStyleValue<string | number>;
  mr?: ResponsiveStyleValue<string | number>;
  mb?: ResponsiveStyleValue<string | number>;
  ml?: ResponsiveStyleValue<string | number>;
  mx?: ResponsiveStyleValue<string | number>;
  my?: ResponsiveStyleValue<string | number>;
  p?: ResponsiveStyleValue<string | number>;
  padding?: ResponsiveStyleValue<string | number>;
  pt?: ResponsiveStyleValue<string | number>;
  pr?: ResponsiveStyleValue<string | number>;
  pb?: ResponsiveStyleValue<string | number>;
  pl?: ResponsiveStyleValue<string | number>;
  px?: ResponsiveStyleValue<string | number>;
  py?: ResponsiveStyleValue<string | number>;
  color?: ResponsiveStyleValue<string>;
  bg?: ResponsiveStyleValue<string>;
  backgroundColor?: ResponsiveStyleValue<string>;
  fontSize?: ResponsiveStyleValue<string | number>;
  fontFamily?: ResponsiveStyleValue<string>;
  fontWeight?: ResponsiveStyleValue<string | number>;
  lineHeight?: ResponsiveStyleValue<string | number>;
  width?: ResponsiveStyleValue<string | number>;
  height?: ResponsiveStyleValue<string | number>;
  minWidth?: ResponsiveStyleValue<string | number>;
  maxWidth?: ResponsiveStyleValue<string | number>;
  minHeight?: ResponsiveStyleValue<string | number>;
  maxHeight?: ResponsiveStyleValue<string | number>;
}

interface Breakpoints extends Array<string> {
  [key: string]: string;
}