CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-theme-ui

The Design Graph Framework - a library for creating themeable user interfaces based on constraint-based design principles

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

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;
}

docs

components.md

hooks-utilities.md

index.md

styling-system.md

theming.md

tile.json