UTA DevHub
UI Development/UI Architecture/Foundation Components Guide

Design Token Integration

Deep dive into using design tokens for colors, typography, spacing, and shadows to ensure consistency across your component library.

Design Token Integration

Overview

Design tokens are the visual atoms of your design system - the smallest pieces of your visual language. They ensure consistency across your entire component library by centralizing design decisions into reusable values.

Why Design Tokens Matter

Design tokens provide:

  • Consistency: Single source of truth for design values
  • Maintainability: Update once, changes propagate everywhere
  • Theming: Easy switching between light/dark modes
  • Platform Unity: Same visual language across iOS and Android
  • Design-Dev Sync: Shared vocabulary between designers and developers

Token Categories

Our design system uses these primary token categories:

  1. Color Tokens: Brand colors, semantic colors, and surfaces
  2. Typography Tokens: Font families, sizes, weights, and line heights
  3. Spacing Tokens: Consistent spacing scale
  4. Radius Tokens: Border radius values
  5. Shadow Tokens: Elevation and depth
  6. Motion Tokens: Animation durations and easings

Color Token Usage

Color Token Structure

// core/shared/styles/theme/colors.ts
export const colors = {
  // Brand colors
  primary: {
    50: '#e3f2fd',
    100: '#bbdefb',
    200: '#90caf9',
    300: '#64b5f6',
    400: '#42a5f5',
    500: '#2196f3', // Main brand color
    600: '#1e88e5',
    700: '#1976d2',
    800: '#1565c0',
    900: '#0d47a1',
  },
  
  // Semantic colors
  success: {
    light: '#4caf50',
    main: '#2e7d32',
    dark: '#1b5e20',
  },
  
  error: {
    light: '#ef5350',
    main: '#d32f2f',
    dark: '#c62828',
  },
  
  // Text colors
  text: {
    primary: 'rgba(0, 0, 0, 0.87)',
    secondary: 'rgba(0, 0, 0, 0.60)',
    disabled: 'rgba(0, 0, 0, 0.38)',
    inverse: '#ffffff',
  },
  
  // Surface colors
  surface: {
    background: '#f5f5f5',
    paper: '#ffffff',
    elevated: '#ffffff',
  },
  
  // Border colors
  border: {
    default: 'rgba(0, 0, 0, 0.12)',
    focus: '#2196f3',
    error: '#d32f2f',
  },
};

Theme-Aware Colors

// Support for light/dark themes
const useThemeColors = () => {
  const isDark = useColorScheme() === 'dark';
  
  return {
    background: isDark ? colors.dark.background : colors.light.background,
    text: isDark ? colors.dark.text : colors.light.text,
    surface: isDark ? colors.dark.surface : colors.light.surface,
  };
};
 
// Component using theme-aware colors
export const ThemedCard = ({ children }) => {
  const colors = useThemeColors();
  
  return (
    <View style={{ backgroundColor: colors.surface }}>
      <Text style={{ color: colors.text }}>{children}</Text>
    </View>
  );
};

Typography Token Usage

Typography Token Structure

// core/shared/styles/theme/typography.ts
export const typography = {
  // Font families
  families: {
    regular: 'Inter-Regular',
    medium: 'Inter-Medium',
    semibold: 'Inter-SemiBold',
    bold: 'Inter-Bold',
    mono: 'JetBrainsMono-Regular',
  },
  
  // Font sizes
  sizes: {
    xs: 12,
    sm: 14,
    md: 16,
    lg: 18,
    xl: 20,
    '2xl': 24,
    '3xl': 30,
    '4xl': 36,
  },
  
  // Font weights
  weights: {
    normal: '400',
    medium: '500',
    semibold: '600',
    bold: '700',
  },
  
  // Line heights
  lineHeights: {
    tight: 1.25,
    normal: 1.5,
    relaxed: 1.75,
    loose: 2,
  },
  
  // Letter spacing
  letterSpacing: {
    tight: -0.5,
    normal: 0,
    wide: 0.5,
  },
};

Spacing Token Usage

Spacing Scale

// core/shared/styles/theme/spacing.ts
export const spacing = {
  // Base unit: 4px
  xxs: 2,   // 2px
  xs: 4,    // 4px - base unit
  sm: 8,    // 8px
  md: 16,   // 16px - default
  lg: 24,   // 24px
  xl: 32,   // 32px
  '2xl': 48, // 48px
  '3xl': 64, // 64px
  '4xl': 80, // 80px
};
 
// Semantic spacing
export const semanticSpacing = {
  // Component spacing
  componentPadding: {
    small: spacing.sm,
    medium: spacing.md,
    large: spacing.lg,
  },
  
  // Layout spacing
  layoutMargin: {
    small: spacing.sm,
    medium: spacing.md,
    large: spacing.xl,
  },
  
  // Grid spacing
  gridGap: {
    small: spacing.xs,
    medium: spacing.sm,
    large: spacing.md,
  },
};

Radius Token Usage

// Border radius tokens
export const radii = {
  none: 0,
  sm: 4,
  md: 8,
  lg: 12,
  xl: 16,
  full: 9999, // For circular elements
};
 
// Usage in components
const cardStyles = {
  borderRadius: theme.radii.lg,
};
 
const avatarStyles = {
  borderRadius: theme.radii.full,
};
 
const chipStyles = {
  borderRadius: theme.radii.full,
};

Shadow Token Usage

// core/shared/styles/theme/shadows.ts
export const shadows = {
  // Elevation levels
  none: {
    shadowColor: 'transparent',
    shadowOffset: { width: 0, height: 0 },
    shadowOpacity: 0,
    shadowRadius: 0,
    elevation: 0,
  },
  
  sm: {
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.05,
    shadowRadius: 2,
    elevation: 2,
  },
  
  md: {
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 4,
  },
  
  lg: {
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 4 },
    shadowOpacity: 0.15,
    shadowRadius: 8,
    elevation: 8,
  },
  
  xl: {
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 8 },
    shadowOpacity: 0.2,
    shadowRadius: 16,
    elevation: 16,
  },
};

Token Organization Best Practices

File Structure

core/shared/styles/
├── theme/
│   ├── index.ts          # Main theme export
│   ├── colors.ts         # Color tokens
│   ├── typography.ts     # Typography tokens
│   ├── spacing.ts        # Spacing scale
│   ├── shadows.ts        # Shadow/elevation tokens
│   ├── radii.ts         # Border radius tokens
│   └── motion.ts        # Animation tokens
├── tokens.ts            # Token type definitions
└── utils.ts            # Token utilities

Creating Custom Tokens

// Extend existing tokens
const customColors = {
  ...theme.colors,
  brand: {
    primary: '#FF6B6B',
    secondary: '#4ECDC4',
  },
};
 
// Create semantic aliases
const semanticColors = {
  interactive: {
    default: theme.colors.primary[500],
    hover: theme.colors.primary[600],
    pressed: theme.colors.primary[700],
    disabled: theme.colors.gray[300],
  },
};
 
// Component-specific tokens
const buttonTokens = {
  sizes: {
    small: {
      padding: theme.spacing.sm,
      fontSize: theme.typography.sizes.sm,
    },
    medium: {
      padding: theme.spacing.md,
      fontSize: theme.typography.sizes.md,
    },
    large: {
      padding: theme.spacing.lg,
      fontSize: theme.typography.sizes.lg,
    },
  },
};

Token Validation

// Validate token usage in development
const validateToken = (value: any, tokenType: string) => {
  if (__DEV__) {
    const validTokens = Object.values(theme[tokenType]);
    if (!validTokens.includes(value)) {
      console.warn(
        `Invalid ${tokenType} token: ${value}. Use one of:`,
        validTokens
      );
    }
  }
  return value;
};
 
// Type-safe token access
const getToken = <T extends keyof typeof theme>(
  tokenType: T,
  tokenName: keyof typeof theme[T]
): typeof theme[T][keyof typeof theme[T]] => {
  return theme[tokenType][tokenName];
};

Summary

Design tokens are the foundation of a consistent design system. By using them properly:

  • Maintain Consistency: Every component uses the same visual language
  • Enable Theming: Switch themes by changing token values
  • Improve Maintainability: Update design decisions in one place
  • Enhance Developer Experience: Clear, predictable values
  • Support Accessibility: Built-in support for dynamic type and high contrast

Remember: If you find yourself hardcoding a value, there should be a token for it!

Next Steps