Popular Searches
Popular Course Categories
Popular Courses

Managing Colors, Typography, Spacing, and Design Tokens

Managing Colors, Typography, Spacing, and Design Tokens

UI Libraries, Themes, and Advanced Interface Design

Managing Colors, Typography, Spacing, and Design Tokens in React Native

Course: React Native Training

Topic: Managing Colors, Typography, Spacing, and Design Tokens

Course Link: React Native Training at JustAcademy

Demo Registration: Register for a Course Demo

JustAcademy Website: Visit JustAcademy


1. Introduction to Design Systems in React Native

Design is an important part of mobile application development. A well-designed application should have a consistent appearance across all screens, including login forms, dashboards, profile pages, product listings, and settings screens. Colors, typography, spacing, and component dimensions all contribute to this consistency.

When developers style each screen independently, the same blue color may be represented by different hexadecimal values, headings may use inconsistent font sizes, and similar components may have different padding. These differences make an application look unorganized and increase maintenance effort.

React Native developers can solve this problem by creating a shared design system. A design system defines reusable visual rules and values that can be applied throughout an application.

One important part of a design system is a collection of design tokens. Design tokens are named values representing visual decisions, such as primary colors, font sizes, spacing units, border radii, and shadows.

1.1 What Is a Design System?

A design system is a structured collection of design guidelines, reusable components, visual standards, and implementation rules. It helps developers and designers create consistent interfaces across an application.

A mobile application design system may include:

  • Colors: Primary, secondary, background, surface, text, border, success, warning, and error colors.
  • Typography: Font families, font sizes, weights, line heights, and text variants.
  • Spacing: Standard values for padding, margins, gaps, and layout separation.
  • Dimensions: Common component heights, widths, and minimum touch-target sizes.
  • Shape: Border radii and other shared shape properties.
  • Elevation: Shadows and visual separation for components that need depth.
  • Components: Reusable buttons, cards, input fields, dialogs, and navigation elements.
  • Accessibility rules: Contrast, readable text, clear labels, and usable interactions.

1.2 Why Design Consistency Matters

  • It creates a recognizable visual identity.
  • It improves readability and navigation.
  • It makes interfaces easier to understand.
  • It reduces duplicated styling values.
  • It simplifies global design changes.
  • It helps developers work consistently across screens.
  • It makes future component development more predictable.

2. Learning Objectives

After studying this topic, learners should be able to:

  • Explain the purpose of design systems and design tokens.
  • Manage reusable colors in React Native.
  • Define consistent typography styles.
  • Build a spacing scale for application layouts.
  • Organize design tokens into separate files.
  • Apply design tokens to reusable components.
  • Understand how themes support light and dark modes.
  • Improve accessibility through contrast and readable typography.
  • Maintain consistent styling across multiple screens.
  • Build and test a small design system for a React Native application.

3. Understanding Design Tokens

A design token is a named value that represents a reusable design decision. Instead of repeating raw values in many components, developers define them centrally and refer to them by name.

For example, rather than writing #2563eb in every button, card, and link, a developer can define a token named primary and use it wherever the primary color is required.

3.1 Example Without Design Tokens

import React from 'react';
import { View, Text, Pressable } from 'react-native';

export default function ExampleScreen() {
  return (
    <View style={{ padding: 16 }}>
      <Text style={{ color: '#2563eb', fontSize: 20 }}>
        Dashboard
      </Text>

      <Pressable
        style={{
          backgroundColor: '#2563eb',
          padding: 12,
          borderRadius: 8
        }}
      >
        <Text style={{ color: '#ffffff' }}>
          Continue
        </Text>
      </Pressable>
    </View>
  );
}

This example works, but the same values may become repeated across many screens. If the primary color changes, developers may need to find and update every occurrence.

3.2 Example With Design Tokens

// src/theme/tokens.js
const tokens = {
  colors: {
    primary: '#2563eb',
    onPrimary: '#ffffff',
    background: '#f8fafc',
    surface: '#ffffff',
    text: '#0f172a',
    mutedText: '#64748b',
    border: '#cbd5e1',
    error: '#dc2626'
  },
  spacing: {
    xs: 4,
    sm: 8,
    md: 16,
    lg: 24,
    xl: 32
  },
  typography: {
    small: 12,
    body: 16,
    subtitle: 18,
    title: 24
  },
  radius: {
    sm: 4,
    md: 8,
    lg: 16
  }
};

export default tokens;

These tokens can be imported into screens and components. The exact values are examples; a real application should choose values that suit its design requirements.

3.3 Advantages of Design Tokens

Advantage Description
Consistency Components use shared visual values instead of unrelated values.
Maintainability Changes can be made centrally.
Scalability New screens can reuse established design rules.
Readability Names such as primary and spacing.md explain intent better than raw numbers.
Theme support Different token sets can support light and dark themes.
Collaboration Designers and developers can share a common vocabulary.

4. Managing Colors in React Native

Colors communicate brand identity, hierarchy, status, and interaction. A consistent color system helps users recognize primary actions, read information clearly, and distinguish errors from success messages.

4.1 Common Color Categories

Color Token Purpose Example
Primary Main brand color and primary actions #2563eb
Secondary Supporting actions and accents #64748b
Background Main screen background #f8fafc
Surface Cards, panels, and raised content areas #ffffff
Text Main readable text #0f172a
Muted Text Secondary descriptions and hints #64748b
Border Separators and input outlines #cbd5e1
Success Successful actions and confirmations #15803d
Warning Warnings requiring attention #b45309
Error Validation errors and destructive actions #b91c1c

4.2 Creating a Centralized Color File

A dedicated color file prevents color values from being scattered throughout the application.

// src/theme/colors.js
const colors = {
  primary: '#2563eb',
  primaryPressed: '#1d4ed8',
  onPrimary: '#ffffff',

  secondary: '#64748b',
  background: '#f8fafc',
  surface: '#ffffff',

  text: '#0f172a',
  mutedText: '#64748b',
  border: '#cbd5e1',

  success: '#15803d',
  warning: '#b45309',
  error: '#b91c1c'
};

export default colors;

4.3 Using Color Tokens

import React from 'react';
import {
  View,
  Text,
  Pressable,
  StyleSheet
} from 'react-native';
import colors from './src/theme/colors';

export default function ColorExample() {
  return (
    <View style={styles.container}>
      <Text style={styles.heading}>
        Welcome
      </Text>

      <Pressable style={styles.button}>
        <Text style={styles.buttonText}>
          Get Started
        </Text>
      </Pressable>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: colors.background
  },
  heading: {
    color: colors.text,
    fontSize: 24,
    fontWeight: '700',
    marginBottom: 16
  },
  button: {
    backgroundColor: colors.primary,
    padding: 14,
    borderRadius: 8,
    alignItems: 'center'
  },
  buttonText: {
    color: colors.onPrimary,
    fontSize: 16,
    fontWeight: '600'
  }
});

In this example, colors are imported from a shared file. If the brand's primary color changes, the developer can update the token without editing every component that uses it.

4.4 Color Formats in React Native

React Native supports common color formats, including hexadecimal values, RGB, RGBA, and named colors.

// Hexadecimal
backgroundColor: '#2563eb'

// RGB
backgroundColor: 'rgb(37, 99, 235)'

// RGBA with transparency
backgroundColor: 'rgba(37, 99, 235, 0.2)'

// Named color
backgroundColor: 'white'

Hexadecimal values are common in design systems because they are compact and easy to compare with design specifications. RGBA can be useful for overlays and transparent surfaces.

4.5 Color Best Practices

  • Define brand and semantic colors centrally.
  • Use semantic names such as success, error, and background rather than names based only on appearance.
  • Use consistent text and background combinations.
  • Do not rely on color alone to communicate an error or status.
  • Check text contrast and interactive control visibility.
  • Avoid introducing nearly identical colors without a clear purpose.
  • Test colors on real devices and under different brightness conditions.

5. Understanding Color Contrast and Accessibility

Color contrast is the difference in luminance between foreground content and its background. Adequate contrast helps people read text and identify interface controls.

5.1 Contrast Guidelines

  • For normal text, WCAG guidance generally recommends a contrast ratio of at least 4.5:1.
  • For large text, WCAG guidance generally recommends at least 3:1.
  • Important icons and visual information needed to understand a control should have sufficient contrast against adjacent colors.
  • Color should not be the only indicator of validation or status.

For example, an error message should include explanatory text such as "Enter a valid email address" rather than relying only on a red border.

5.2 Example of an Accessible Error Message

import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import colors from './src/theme/colors';

export default function ErrorMessage() {
  return (
    <View style={styles.container}>
      <Text style={styles.errorTitle}>
        Unable to continue
      </Text>
      <Text style={styles.errorDescription}>
        Enter a valid email address and try again.
      </Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    padding: 12,
    borderRadius: 8,
    backgroundColor: '#fef2f2'
  },
  errorTitle: {
    color: colors.error,
    fontSize: 16,
    fontWeight: '700'
  },
  errorDescription: {
    color: colors.text,
    marginTop: 4,
    fontSize: 14
  }
});

Always verify the contrast of the final foreground and background color combinations rather than assuming a color is accessible based on its name.

6. Managing Typography in React Native

Typography refers to the appearance and arrangement of text. It includes font family, font size, font weight, line height, letter spacing, and text alignment. Good typography creates a clear information hierarchy and improves readability.

React Native uses the Text component to display text. Text styling is applied through properties such as fontSize, fontWeight, fontFamily, lineHeight, and letterSpacing.

6.1 Common Typography Properties

Property Purpose Example
fontSize Controls the size of text fontSize: 16
fontWeight Controls the thickness of characters fontWeight: '700'
fontFamily Selects a supported font family fontFamily: 'Arial'
lineHeight Controls the height of a line of text lineHeight: 24
letterSpacing Adjusts spacing between characters letterSpacing: 0.3
textAlign Controls horizontal text alignment textAlign: 'center'
fontStyle Sets normal or italic text styling fontStyle: 'italic'
textTransform Changes capitalization where supported textTransform: 'uppercase'

6.2 Creating a Typography Token File

A typography file defines shared text styles for headings, subtitles, body text, captions, and labels. This avoids repeating font values across the application.

// src/theme/typography.js
const typography = {
  display: {
    fontSize: 32,
    lineHeight: 40,
    fontWeight: '700'
  },
  heading: {
    fontSize: 24,
    lineHeight: 32,
    fontWeight: '700'
  },
  subtitle: {
    fontSize: 18,
    lineHeight: 26,
    fontWeight: '600'
  },
  body: {
    fontSize: 16,
    lineHeight: 24,
    fontWeight: '400'
  },
  bodySmall: {
    fontSize: 14,
    lineHeight: 21,
    fontWeight: '400'
  },
  caption: {
    fontSize: 12,
    lineHeight: 18,
    fontWeight: '400'
  },
  button: {
    fontSize: 16,
    lineHeight: 22,
    fontWeight: '600'
  }
};

export default typography;

These font sizes and line heights are examples. Adjust them according to the application's brand, content, supported languages, and accessibility requirements.

6.3 Using Typography Tokens

import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import typography from './src/theme/typography';
import colors from './src/theme/colors';

export default function TypographyExample() {
  return (
    <View style={styles.container}>
      <Text style={styles.heading}>
        Account Dashboard
      </Text>

      <Text style={styles.subtitle}>
        Your account overview
      </Text>

      <Text style={styles.body}>
        View your details, recent activity, and preferences.
      </Text>

      <Text style={styles.caption}>
        Last updated today
      </Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    padding: 20,
    backgroundColor: colors.background
  },
  heading: {
    ...typography.heading,
    color: colors.text,
    marginBottom: 8
  },
  subtitle: {
    ...typography.subtitle,
    color: colors.text,
    marginBottom: 12
  },
  body: {
    ...typography.body,
    color: colors.mutedText
  },
  caption: {
    ...typography.caption,
    color: colors.mutedText,
    marginTop: 12
  }
});

The spread operator copies the properties from each typography token into the relevant style object. Additional properties can then be added or overridden for that specific component.

6.4 Creating a Reusable Text Component

React Native does not provide unrestricted, browser-style inheritance of text properties through a View hierarchy. A reusable text component can help establish a consistent default style for commonly used text elements.

// src/components/AppText.js
import React from 'react';
import { Text, StyleSheet } from 'react-native';
import colors from '../theme/colors';
import typography from '../theme/typography';

const variants = {
  heading: typography.heading,
  subtitle: typography.subtitle,
  body: typography.body,
  bodySmall: typography.bodySmall,
  caption: typography.caption
};

export default function AppText({
  children,
  variant = 'body',
  color = colors.text,
  style,
  ...rest
}) {
  const selectedVariant = variants[variant] || variants.body;

  return (
    <Text
      {...rest}
      style={[
        styles.base,
        selectedVariant,
        { color },
        style
      ]}
    >
      {children}
    </Text>
  );
}

const styles = StyleSheet.create({
  base: {
    includeFontPadding: false
  }
});

Example usage:

<AppText variant="heading">Welcome</AppText>
<AppText variant="subtitle">Account Overview</AppText>
<AppText variant="body">Manage your profile and preferences.</AppText>
<AppText variant="caption" color="#64748b">Updated recently</AppText>

In this component, the supplied style is applied last, allowing a screen to override specific styles when necessary. Use overrides thoughtfully to preserve the overall typography system.

6.5 Font Families and Custom Fonts

Applications can use system fonts or custom fonts. Custom fonts may help establish a brand identity, but they require correct asset configuration and platform testing.

  • Choose fonts that are readable at small sizes.
  • Verify that the chosen font supports the languages your application displays.
  • Configure custom font assets according to your React Native or Expo setup.
  • Check that the required font weights are available.
  • Test text wrapping, alignment, and line height on both Android and iOS.

6.6 Typography Best Practices

  • Establish a clear hierarchy between headings, body text, and captions.
  • Use consistent font sizes and weights for similar roles.
  • Choose suitable line heights for readable paragraphs.
  • Avoid too many font families and font weights.
  • Allow text to wrap naturally instead of relying on fixed heights.
  • Keep font scaling enabled unless there is a specific, carefully considered reason not to.
  • Test longer translations and increased system text sizes.

7. Managing Spacing in React Native

Spacing controls the distance between elements and the space inside components. Consistent spacing makes interfaces easier to scan and prevents screens from appearing crowded or disorganized.

In React Native, spacing is commonly managed through properties such as padding, margin, gap, rowGap, and columnGap, depending on the supported React Native version and layout requirements.

7.1 Padding vs. Margin vs. Gap

Property Meaning Typical Use
padding Space inside an element, between its border and content Adding space inside a button or card
margin Space outside an element Separating a heading from the next section
gap Space between items in a layout Separating buttons or cards in a row or column
rowGap Spacing between layout rows Creating vertical gaps in a wrapped grid
columnGap Spacing between layout columns Creating horizontal gaps between columns

7.2 Creating a Spacing Scale

A spacing scale defines a limited set of reusable spacing values. Teams can use the scale throughout the application instead of selecting unrelated numbers for every component.

// src/theme/spacing.js
const spacing = {
  none: 0,
  xs: 4,
  sm: 8,
  md: 16,
  lg: 24,
  xl: 32,
  xxl: 48
};

export default spacing;

The values above are an example of a scale based on increments of four. A design team may choose a different scale to suit its layout system.

7.3 Using Spacing Tokens

import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import spacing from './src/theme/spacing';
import colors from './src/theme/colors';

export default function SpacingExample() {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>Profile</Text>

      <View style={styles.card}>
        <Text>Account details appear here.</Text>
      </View>

      <View style={styles.notice}>
        <Text>Your profile is up to date.</Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: spacing.lg,
    backgroundColor: colors.background
  },
  title: {
    fontSize: 24,
    fontWeight: '700',
    marginBottom: spacing.md,
    color: colors.text
  },
  card: {
    backgroundColor: colors.surface,
    padding: spacing.md,
    borderRadius: 12,
    marginBottom: spacing.md
  },
  notice: {
    padding: spacing.sm,
    backgroundColor: '#dbeafe',
    borderRadius: 8
  }
});

7.4 Designing Consistent Layouts

Spacing should communicate relationships between elements. Related items should usually have smaller gaps, while separate sections can have larger gaps.

  • Use small gaps between an input label and its input field.
  • Use moderate spacing between fields in a form.
  • Use larger spacing between major sections.
  • Use consistent internal padding for cards and buttons.
  • Avoid using large empty spaces to compensate for unclear layout structure.
  • Test layouts with long text and different device sizes.

7.5 Example of a Form Using Spacing Tokens

import React, { useState } from 'react';
import { View, TextInput, Text, StyleSheet } from 'react-native';
import spacing from './src/theme/spacing';
import colors from './src/theme/colors';

export default function SearchForm() {
  const [query, setQuery] = useState('');

  return (
    <View style={styles.container}>
      <Text style={styles.label}>Search Courses</Text>

      <TextInput
        value={query}
        onChangeText={setQuery}
        placeholder="Enter a course name"
        style={styles.input}
      />

      <Text style={styles.helper}>
        Enter a keyword to find relevant courses.
      </Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    padding: spacing.lg
  },
  label: {
    fontSize: 16,
    fontWeight: '600',
    marginBottom: spacing.xs,
    color: colors.text
  },
  input: {
    borderWidth: 1,
    borderColor: colors.border,
    borderRadius: 8,
    paddingHorizontal: spacing.md,
    paddingVertical: spacing.sm,
    fontSize: 16,
    color: colors.text
  },
  helper: {
    fontSize: 12,
    lineHeight: 18,
    color: colors.mutedText,
    marginTop: spacing.xs
  }
});

8. Managing Border Radius, Dimensions, and Elevation

Colors, typography, and spacing are core design tokens, but many design systems also centralize other visual values. Border radius, component dimensions, and elevation help create a consistent appearance.

8.1 Border Radius Tokens

// src/theme/radius.js
const radius = {
  none: 0,
  sm: 4,
  md: 8,
  lg: 16,
  xl: 24,
  pill: 999
};

export default radius;

Use a consistent radius scale for input fields, cards, buttons, badges, and dialogs. Very large values should be used intentionally, such as for pill-shaped controls.

8.2 Dimensions and Touch Targets

Some components benefit from shared height or minimum-size values. For example, a team may establish a standard minimum height for form inputs and primary buttons.

// src/theme/dimensions.js
const dimensions = {
  inputMinHeight: 48,
  buttonMinHeight: 48,
  iconSize: 24,
  avatarSmall: 32,
  avatarMedium: 48,
  avatarLarge: 72
};

export default dimensions;

These values are illustrative. Ensure interactive elements have sufficient usable touch area and remain comfortable to activate on mobile devices.

8.3 Elevation and Shadows

Elevation visually separates cards, menus, and dialogs from their backgrounds. React Native supports shadow-related styles, but platform behavior differs between iOS and Android.

import { StyleSheet } from 'react-native';

const styles = StyleSheet.create({
  card: {
    backgroundColor: '#ffffff',
    borderRadius: 12,
    padding: 16,

    // Android
    elevation: 3,

    // iOS
    shadowColor: '#000000',
    shadowOffset: {
      width: 0,
      height: 2
    },
    shadowOpacity: 0.12,
    shadowRadius: 5
  }
});

Use shadows sparingly. Excessive elevation can make a screen visually noisy and may create inconsistent results across platforms.

9. Organizing a Complete Theme Structure

As an application grows, separating tokens by category makes them easier to locate and maintain. A common approach is to keep colors, typography, spacing, radius, and dimensions in a theme directory.

9.1 Suggested Folder Structure

src/
  theme/
    colors.js
    typography.js
    spacing.js
    radius.js
    dimensions.js
    themes.js
    index.js
  components/
    AppText.js
    PrimaryButton.js
    CustomCard.js
  screens/
    HomeScreen.js
    ProfileScreen.js
    SettingsScreen.js
App.js

9.2 Creating a Shared Theme Object

// src/theme/themes.js
import colors from './colors';
import typography from './typography';
import spacing from './spacing';
import radius from './radius';
import dimensions from './dimensions';

const lightTheme = {
  colors,
  typography,
  spacing,
  radius,
  dimensions
};

export default lightTheme;

This theme object groups the design tokens together. It is a custom project structure, not a special React Native API. Components can access the values through imports or through a theme context created by the application.

9.3 Creating a Theme Index

// src/theme/index.js
export { default as colors } from './colors';
export { default as typography } from './typography';
export { default as spacing } from './spacing';
export { default as radius } from './radius';
export { default as dimensions } from './dimensions';
export { default as lightTheme } from './themes';

Now a component can import several design values from a single module:

import {
  colors,
  typography,
  spacing,
  radius
} from '../theme';

10. Implementing Light and Dark Themes

Modern applications often provide light and dark appearance modes. A light theme typically uses light backgrounds and dark text, while a dark theme uses dark surfaces and light text.

Rather than changing individual styles across every screen, developers can define separate theme token sets and choose the appropriate set at runtime.

10.1 Create Light and Dark Color Tokens

// src/theme/themes.js
export const lightColors = {
  primary: '#2563eb',
  onPrimary: '#ffffff',
  background: '#f8fafc',
  surface: '#ffffff',
  text: '#0f172a',
  mutedText: '#475569',
  border: '#cbd5e1',
  error: '#b91c1c'
};

export const darkColors = {
  primary: '#93c5fd',
  onPrimary: '#172554',
  background: '#0f172a',
  surface: '#1e293b',
  text: '#f8fafc',
  mutedText: '#cbd5e1',
  border: '#475569',
  error: '#fca5a5'
};

The light and dark tokens should represent equivalent semantic roles. Review contrast carefully because colors that work on a light background may not work on a dark background.

10.2 Select the System Color Scheme

React Native provides the useColorScheme hook to read the system's current appearance preference. The following example uses that preference to select a theme.

import React from 'react';
import {
  View,
  Text,
  StyleSheet,
  useColorScheme
} from 'react-native';

import {
  lightColors,
  darkColors
} from './src/theme/themes';

export default function ThemeExample() {
  const scheme = useColorScheme();
  const colors = scheme === 'dark' ? darkColors : lightColors;

  return (
    <View style={[
      styles.container,
      { backgroundColor: colors.background }
    ]}>
      <Text style={[
        styles.title,
        { color: colors.text }
      ]}>
        Theme Example
      </Text>

      <Text style={[
        styles.description,
        { color: colors.mutedText }
      ]}>
        This screen follows the system appearance preference.
      </Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    justifyContent: 'center'
  },
  title: {
    fontSize: 24,
    fontWeight: '700',
    marginBottom: 12
  },
  description: {
    fontSize: 16,
    lineHeight: 24
  }
});

10.3 Important Theme Considerations

  • Use semantic token names instead of hardcoding light-theme colors in every component.
  • Check contrast in both themes.
  • Review status colors, borders, icons, input placeholders, and disabled controls.
  • Test the transition when the system appearance changes.
  • Consider whether the application should follow the system setting or allow a manual theme preference.
  • Persist a manually selected preference only when the application needs to remember it between launches.

11. Applying Design Tokens to Reusable Components

A design system becomes most useful when its tokens are applied to reusable interface components. This allows buttons, cards, and inputs to share common colors, typography, spacing, and border styles.

11.1 Reusable Button Using Tokens

import React from 'react';
import {
  Pressable,
  Text,
  StyleSheet
} from 'react-native';

import colors from '../theme/colors';
import spacing from '../theme/spacing';
import radius from '../theme/radius';
import typography from '../theme/typography';

export default function PrimaryButton({
  title,
  onPress,
  disabled = false
}) {
  return (
    <Pressable
      onPress={onPress}
      disabled={disabled}
      accessibilityRole="button"
      accessibilityState={{ disabled }}
      style={[
        styles.button,
        disabled && styles.disabled
      ]}
    >
      <Text style={styles.label}>{title}</Text>
    </Pressable>
  );
}

const styles = StyleSheet.create({
  button: {
    minHeight: 48,
    paddingHorizontal: spacing.md,
    paddingVertical: spacing.sm,
    backgroundColor: colors.primary,
    borderRadius: radius.md,
    alignItems: 'center',
    justifyContent: 'center'
  },
  label: {
    ...typography.button,
    color: colors.onPrimary
  },
  disabled: {
    opacity: 0.5
  }
});

11.2 Reusable Card Using Tokens

import React from 'react';
import { View, Text, StyleSheet } from 'react-native';

import colors from '../theme/colors';
import spacing from '../theme/spacing';
import radius from '../theme/radius';
import typography from '../theme/typography';

export default function InfoCard({ title, description }) {
  return (
    <View style={styles.card}>
      <Text style={styles.title}>{title}</Text>
      <Text style={styles.description}>{description}</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  card: {
    padding: spacing.md,
    borderRadius: radius.lg,
    backgroundColor: colors.surface,
    borderWidth: 1,
    borderColor: colors.border
  },
  title: {
    ...typography.subtitle,
    color: colors.text,
    marginBottom: spacing.sm
  },
  description: {
    ...typography.body,
    color: colors.mutedText
  }
});

11.3 Why This Approach Is Useful

  • Components share the same primary color and typography rules.
  • Padding and border radii remain consistent.
  • Design changes can be made centrally.
  • Reusable components become easier to review and maintain.
  • Teams can add new components without inventing new styling rules each time.

12. Common Mistakes When Managing Design Tokens

Mistake Why It Is a Problem Recommended Solution
Repeating raw color values Similar colors become inconsistent across screens. Create semantic color tokens and reuse them.
Using too many font sizes Text hierarchy becomes difficult to understand. Define a small, purposeful typography scale.
Using arbitrary spacing Layouts look inconsistent and are harder to maintain. Use a documented spacing scale.
Hardcoding light colors in every component Dark mode becomes difficult to implement. Use semantic theme tokens for surfaces, text, borders, and states.
Overriding tokens everywhere The shared design system loses consistency. Allow local overrides only when a real design requirement exists.
Using fixed heights for text containers Text may be clipped when it wraps or scales. Prefer flexible layouts and test larger text sizes.
Ignoring contrast Text and controls may become difficult to perceive. Check contrast ratios and test the complete interface.
Defining tokens without documentation Developers may use the wrong token for a component. Document each token's purpose and intended usage.
Using unclear names Names such as blue2 or space5 do not explain intent. Prefer semantic names such as primary, surface, and spacing.md.
Testing only on one device Font scaling and layout behavior may differ elsewhere. Test on multiple screen sizes, platforms, and accessibility settings.

13. Troubleshooting Design System Issues

13.1 A Color Change Does Not Appear

  • Confirm that the component imports the correct color token.
  • Check whether a local style overrides the token.
  • Review the order of styles in an array because later styles take precedence.
  • Confirm that the edited file is the one used by the screen.
  • Restart the development server if the issue appears to be caused by stale development state.

13.2 Typography Looks Different on Android and iOS

  • Verify that the font family is available and configured correctly.
  • Check whether the expected font weight exists.
  • Review line height and font padding behavior.
  • Test text wrapping and vertical alignment on both platforms.
  • Avoid assuming that all fonts render identically on every device.

13.3 Spacing Appears Inconsistent

  • Inspect component-level padding and margin.
  • Look for repeated raw numbers instead of spacing tokens.
  • Check the parent layout's gap, alignment, and flex properties.
  • Review conditional styles and style-array order.
  • Compare related components using the same spacing rules.

13.4 Dark Mode Has Poor Contrast

  • Verify that every semantic token has a suitable dark-theme value.
  • Check text, placeholders, borders, icons, and disabled states.
  • Ensure that components use the selected theme rather than hardcoded light-theme values.
  • Test error and success messages in both themes.
  • Review contrast with an accessibility checker.

14. Best Practices for Managing Design Tokens

  • Use semantic names: Prefer primary, background, and mutedText over names tied only to a visual color.
  • Keep the system focused: Avoid creating unnecessary tokens for values that are rarely reused.
  • Document intended usage: Explain when a token should be used.
  • Keep related values together: Organize colors, typography, spacing, radius, and dimensions logically.
  • Use reusable components: Apply tokens through common buttons, cards, inputs, and text components.
  • Plan for themes: Separate semantic roles from the actual values used in a particular theme.
  • Prioritize accessibility: Verify contrast, readable text, and layout behavior with increased font sizes.
  • Test on multiple platforms: Confirm that the design works on target Android and iOS devices.
  • Review changes carefully: A token change can affect many screens, so test important components after updating it.
  • Maintain consistency: Establish guidelines for when a component may use a custom style instead of the shared tokens.

15. Mini Project: Build a Reusable Design System

Project Objective: Create a small React Native design system that centralizes colors, typography, spacing, border radii, and component dimensions. Apply the system to a sample dashboard screen.

15.1 Project Requirements

  • A centralized color palette.
  • A typography scale with headings, subtitles, body text, and captions.
  • A spacing scale for margins, padding, and layout gaps.
  • A shared border-radius scale.
  • A reusable text component.
  • A reusable primary button.
  • A reusable information card.
  • A dashboard screen using all shared components.
  • Optional light and dark themes.
  • Accessibility and cross-platform testing.

15.2 Suggested Folder Structure

src/
  theme/
    colors.js
    typography.js
    spacing.js
    radius.js
    dimensions.js
    themes.js
    index.js
  components/
    AppText.js
    PrimaryButton.js
    InfoCard.js
  screens/
    DashboardScreen.js
App.js

15.3 Implementation Steps

  1. Create the theme folder and add the shared token files.
  2. Define semantic colors for text, surfaces, borders, and status messages.
  3. Create typography styles for headings, subtitles, body text, and captions.
  4. Define a spacing scale and border-radius values.
  5. Create a reusable AppText component using the typography tokens.
  6. Create a PrimaryButton component using color, spacing, and radius tokens.
  7. Create an InfoCard component using the same design system.
  8. Build a dashboard screen using the reusable components.
  9. Add an optional dark theme with matching semantic token names.
  10. Test readability, spacing, and layout on Android and iOS where available.
  11. Review the design system for duplicated or unused values.

15.4 Expected Outcome

By completing this project, learners should understand how to organize visual values, apply tokens to reusable components, and make consistent design changes throughout a React Native application.

16. Practical Exercises

  1. Create a centralized color palette containing primary, secondary, background, surface, text, border, success, and error colors.
  2. Replace hardcoded color values in a sample screen with imported tokens.
  3. Create a typography file containing heading, subtitle, body, and caption styles.
  4. Build a reusable AppText component that accepts a variant prop.
  5. Create a spacing scale and apply it to a form and dashboard card.
  6. Define border-radius tokens for buttons, cards, and inputs.
  7. Build a shared theme object containing all design token categories.
  8. Implement light and dark color palettes using the same semantic keys.
  9. Check text contrast and test the interface with larger system font sizes.
  10. Build the mini project and document your design decisions.

17. Interview Questions and Answers

Q1. What are design tokens?

Answer: Design tokens are named values representing reusable design decisions, such as colors, font sizes, spacing, border radii, and dimensions.

Q2. Why are design tokens important in React Native?

Answer: They help maintain visual consistency, reduce duplicated values, simplify global updates, and make design rules easier to understand.

Q3. What is a design system?

Answer: A design system is a collection of design guidelines, reusable components, visual standards, and implementation rules used to create consistent interfaces.

Q4. How should colors be managed in a React Native project?

Answer: Store semantic color values in a shared theme file and import them into components instead of repeating raw color values throughout the application.

Q5. What is semantic color naming?

Answer: Semantic naming describes the purpose of a color, such as primary, background, surface, error, or success, rather than describing only its appearance.

Q6. What is a typography scale?

Answer: A typography scale is a defined collection of font sizes, weights, and line heights for different text roles, such as headings, body text, and captions.

Q7. What is the purpose of lineHeight?

Answer: The lineHeight property controls the vertical spacing occupied by a line of text and can improve readability and alignment.

Q8. What is the difference between padding and margin?

Answer: Padding creates space inside an element between its border and content. Margin creates space outside an element.

Q9. What is a spacing scale?

Answer: A spacing scale is a predefined set of spacing values that can be reused for padding, margins, and gaps throughout the application.

Q10. Why should design tokens be separated into files?

Answer: Separate files make tokens easier to locate, reuse, test, and maintain as the project grows.

Q11. How can a React Native application support dark mode?

Answer: Define separate light and dark theme values using the same semantic keys, then select the appropriate theme based on the system preference or the user's chosen setting.

Q12. What is the purpose of useColorScheme?

Answer: The useColorScheme hook reads the current system appearance preference and can help an application select its light or dark theme.

Q13. Why is color contrast important?

Answer: Adequate contrast helps users read text and identify important interface elements, including users with low vision or color-perception differences.

Q14. Why should font scaling be considered?

Answer: Users may increase their system text size for readability. A flexible layout and appropriate font scaling help the application remain usable at larger text sizes.

Q15. What is the benefit of reusable text components?

Answer: They apply consistent typography and color styles across screens and allow shared text styling to be updated centrally.

Q16. Can design tokens improve maintainability?

Answer: Yes. Centralized tokens reduce duplicated styling values and allow common visual decisions to be updated in one place.

Q17. Why should design tokens be documented?

Answer: Documentation explains the purpose and intended use of each token, helping developers apply the design system consistently.

Q18. What should be tested after changing a token?

Answer: Test the affected components and screens for color contrast, typography, spacing, layout, theme behavior, and platform differences.

18. Quick Revision Notes

  • A design system provides shared visual rules and reusable components.
  • Design tokens are named values for reusable design decisions.
  • Color tokens define primary, secondary, background, surface, text, and status colors.
  • Typography tokens standardize font sizes, weights, and line heights.
  • Spacing tokens keep padding, margins, and gaps consistent.
  • Radius and dimension tokens standardize component shapes and sizes.
  • Reusable components apply tokens consistently across screens.
  • Semantic token names make design intent clearer.
  • Light and dark themes can use separate values with matching semantic keys.
  • Contrast, readable text, and font scaling are important accessibility considerations.
  • Always test changes across target devices and platforms.

19. Final Checklist

  • Understand design systems and design tokens.
  • Create a centralized color palette.
  • Define a typography scale.
  • Create and use a spacing scale.
  • Define border-radius and component dimension tokens.
  • Organize tokens in a clear folder structure.
  • Apply tokens to reusable buttons, cards, and text components.
  • Implement and test light and dark themes if required.
  • Check contrast and support larger text sizes.
  • Test the design system across the target platforms.

20. Conclusion

Managing colors, typography, spacing, and design tokens is an essential part of building maintainable React Native applications. A well-organized design system gives developers a common set of visual rules and reduces inconsistent styling across screens.

Centralized color palettes make brand updates easier, typography tokens improve text hierarchy, and spacing scales keep layouts organized. Additional tokens for border radii and dimensions help standardize reusable components. When these tokens are applied consistently, the application becomes easier to maintain and expand.

By combining design tokens with reusable components, accessibility checks, theme support, and cross-platform testing, developers can create interfaces that are consistent, readable, and adaptable to different devices and user preferences.

Continue Learning: Explore React Native Training at JustAcademy

Register for a Demo: Register for a Course Demo

Visit JustAcademy: https://www.justacademy.co/

whatsapp