Claude Code Plugins

Community-maintained marketplace

Feedback
59
0

Mobile typography system for React Native and Flutter. Type scales, font weights, line heights, responsive typography, and dark mode support.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name mobile-typography
description Mobile typography system for React Native and Flutter. Type scales, font weights, line heights, responsive typography, and dark mode support.

Mobile Typography System

Design Principles

Mobile typography requires special consideration due to:

  • Variable screen sizes (375px - 428px+ width)
  • Viewing distance (closer than desktop)
  • Touch interaction (larger targets)
  • Outdoor usage (higher contrast needed)

React Native Type Scale

Typography Configuration

// typography.ts
export const typography = {
  // Font families
  fontFamily: {
    primary: 'System', // San Francisco (iOS) / Roboto (Android)
    secondary: 'System',
    monospace: 'Courier',
  },

  // Type scale (modular scale 1.25 for mobile)
  fontSize: {
    // Display & Headings
    displayLarge: 57,    // Hero titles
    displayMedium: 45,   // Page titles
    displaySmall: 36,    // Section headers

    // Headlines
    headlineLarge: 32,   // Featured content
    headlineMedium: 28,  // Cards headers
    headlineSmall: 24,   // List headers

    // Titles
    titleLarge: 22,      // Modal titles
    titleMedium: 16,     // List item titles
    titleSmall: 14,      // Subsection titles

    // Body
    bodyLarge: 16,       // Primary text
    bodyMedium: 14,      // Secondary text
    bodySmall: 12,       // Caption/helper

    // Labels
    labelLarge: 14,      // Buttons
    labelMedium: 12,     // Tabs
    labelSmall: 11,      // Badges
  },

  // Font weights
  fontWeight: {
    regular: '400' as const,
    medium: '500' as const,
    semibold: '600' as const,
    bold: '700' as const,
  },

  // Line heights (optimal for mobile reading)
  lineHeight: {
    tight: 1.1,      // Display text
    snug: 1.25,      // Headings
    normal: 1.5,     // Body text
    relaxed: 1.75,   // Long-form content
  },

  // Letter spacing (in percentage)
  letterSpacing: {
    tight: -0.5,
    normal: 0,
    wide: 0.5,
  },
};

StyleSheet Helper

// styles.ts
import { StyleSheet } from 'react-native';
import { typography } from './typography';

export const createTypographyStyles = () =>
  StyleSheet.create({
    // Display styles
    displayLarge: {
      fontSize: typography.fontSize.displayLarge,
      fontWeight: typography.fontWeight.regular,
      lineHeight: 64,
      letterSpacing: -0.5,
    },
    displayMedium: {
      fontSize: typography.fontSize.displayMedium,
      fontWeight: typography.fontWeight.regular,
      lineHeight: 52,
      letterSpacing: 0,
    },
    displaySmall: {
      fontSize: typography.fontSize.displaySmall,
      fontWeight: typography.fontWeight.regular,
      lineHeight: 44,
      letterSpacing: 0,
    },

    // Headline styles
    headlineLarge: {
      fontSize: typography.fontSize.headlineLarge,
      fontWeight: typography.fontWeight.regular,
      lineHeight: 40,
      letterSpacing: 0,
    },
    headlineMedium: {
      fontSize: typography.fontSize.headlineMedium,
      fontWeight: typography.fontWeight.regular,
      lineHeight: 36,
      letterSpacing: 0,
    },
    headlineSmall: {
      fontSize: typography.fontSize.headlineSmall,
      fontWeight: typography.fontWeight.semibold,
      lineHeight: 32,
      letterSpacing: 0,
    },

    // Title styles
    titleLarge: {
      fontSize: typography.fontSize.titleLarge,
      fontWeight: typography.fontWeight.medium,
      lineHeight: 28,
      letterSpacing: 0,
    },
    titleMedium: {
      fontSize: typography.fontSize.titleMedium,
      fontWeight: typography.fontWeight.medium,
      lineHeight: 24,
      letterSpacing: 0.15,
    },
    titleSmall: {
      fontSize: typography.fontSize.titleSmall,
      fontWeight: typography.fontWeight.medium,
      lineHeight: 20,
      letterSpacing: 0.1,
    },

    // Body styles
    bodyLarge: {
      fontSize: typography.fontSize.bodyLarge,
      fontWeight: typography.fontWeight.regular,
      lineHeight: 24,
      letterSpacing: 0.5,
    },
    bodyMedium: {
      fontSize: typography.fontSize.bodyMedium,
      fontWeight: typography.fontWeight.regular,
      lineHeight: 20,
      letterSpacing: 0.25,
    },
    bodySmall: {
      fontSize: typography.fontSize.bodySmall,
      fontWeight: typography.fontWeight.regular,
      lineHeight: 16,
      letterSpacing: 0.4,
    },

    // Label styles
    labelLarge: {
      fontSize: typography.fontSize.labelLarge,
      fontWeight: typography.fontWeight.medium,
      lineHeight: 20,
      letterSpacing: 0.1,
    },
    labelMedium: {
      fontSize: typography.fontSize.labelMedium,
      fontWeight: typography.fontWeight.medium,
      lineHeight: 16,
      letterSpacing: 0.5,
    },
    labelSmall: {
      fontSize: typography.fontSize.labelSmall,
      fontWeight: typography.fontWeight.medium,
      lineHeight: 16,
      letterSpacing: 0.5,
    },
  });

Usage Examples

// Components
import { createTypographyStyles } from './styles';

const styles = createTypographyStyles();

function ProfileHeader({ name, bio }: { name: string; bio: string }) {
  return (
    <View style={styles.container}>
      <Text style={styles.headlineMedium}>{name}</Text>
      <Text style={styles.bodyMedium}>{bio}</Text>
    </View>
  );
}

function Button({ label }: { label: string }) {
  return (
    <TouchableOpacity style={buttonStyles.button}>
      <Text style={styles.labelLarge}>{label}</Text>
    </TouchableOpacity>
  );
}

function Card({ title, subtitle }: { title: string; subtitle: string }) {
  return (
    <View style={cardStyles.card}>
      <Text style={styles.titleMedium}>{title}</Text>
      <Text style={styles.bodySmall}>{subtitle}</Text>
    </View>
  );
}

Flutter Type Scale

Typography Configuration

// typography.dart
import 'package:flutter/material.dart';

class AppTypography {
  // Font families
  static const String fontFamilyPrimary = 'System';
  static const String fontFamilySecondary = 'System';

  // Text styles
  static const TextStyle displayLarge = TextStyle(
    fontSize: 57,
    fontWeight: FontWeight.w400,
    letterSpacing: -0.25,
    height: 1.12, // 64px line height
  );

  static const TextStyle displayMedium = TextStyle(
    fontSize: 45,
    fontWeight: FontWeight.w400,
    height: 1.16, // 52px line height
  );

  static const TextStyle displaySmall = TextStyle(
    fontSize: 36,
    fontWeight: FontWeight.w400,
    height: 1.22, // 44px line height
  );

  static const TextStyle headlineLarge = TextStyle(
    fontSize: 32,
    fontWeight: FontWeight.w400,
    height: 1.25, // 40px line height
  );

  static const TextStyle headlineMedium = TextStyle(
    fontSize: 28,
    fontWeight: FontWeight.w400,
    height: 1.29, // 36px line height
  );

  static const TextStyle headlineSmall = TextStyle(
    fontSize: 24,
    fontWeight: FontWeight.w600,
    height: 1.33, // 32px line height
  );

  static const TextStyle titleLarge = TextStyle(
    fontSize: 22,
    fontWeight: FontWeight.w500,
    height: 1.27, // 28px line height
  );

  static const TextStyle titleMedium = TextStyle(
    fontSize: 16,
    fontWeight: FontWeight.w500,
    height: 1.5, // 24px line height
    letterSpacing: 0.15,
  );

  static const TextStyle titleSmall = TextStyle(
    fontSize: 14,
    fontWeight: FontWeight.w500,
    height: 1.43, // 20px line height
    letterSpacing: 0.1,
  );

  static const TextStyle bodyLarge = TextStyle(
    fontSize: 16,
    fontWeight: FontWeight.w400,
    height: 1.5, // 24px line height
    letterSpacing: 0.5,
  );

  static const TextStyle bodyMedium = TextStyle(
    fontSize: 14,
    fontWeight: FontWeight.w400,
    height: 1.43, // 20px line height
    letterSpacing: 0.25,
  );

  static const TextStyle bodySmall = TextStyle(
    fontSize: 12,
    fontWeight: FontWeight.w400,
    height: 1.33, // 16px line height
    letterSpacing: 0.4,
  );

  static const TextStyle labelLarge = TextStyle(
    fontSize: 14,
    fontWeight: FontWeight.w500,
    height: 1.43, // 20px line height
    letterSpacing: 0.1,
  );

  static const TextStyle labelMedium = TextStyle(
    fontSize: 12,
    fontWeight: FontWeight.w500,
    height: 1.33, // 16px line height
    letterSpacing: 0.5,
  );

  static const TextStyle labelSmall = TextStyle(
    fontSize: 11,
    fontWeight: FontWeight.w500,
    height: 1.45, // 16px line height
    letterSpacing: 0.5,
  );
}

// Material 3 Theme with typography
ThemeData buildTheme() {
  return ThemeData(
    textTheme: TextTheme(
      displayLarge: AppTypography.displayLarge,
      displayMedium: AppTypography.displayMedium,
      displaySmall: AppTypography.displaySmall,
      headlineLarge: AppTypography.headlineLarge,
      headlineMedium: AppTypography.headlineMedium,
      headlineSmall: AppTypography.headlineSmall,
      titleLarge: AppTypography.titleLarge,
      titleMedium: AppTypography.titleMedium,
      titleSmall: AppTypography.titleSmall,
      bodyLarge: AppTypography.bodyLarge,
      bodyMedium: AppTypography.bodyMedium,
      bodySmall: AppTypography.bodySmall,
      labelLarge: AppTypography.labelLarge,
      labelMedium: AppTypography.labelMedium,
      labelSmall: AppTypography.labelSmall,
    ),
  );
}

Usage Examples

// Widgets
class ProfileHeader extends StatelessWidget {
  final String name;
  final String bio;

  const ProfileHeader({required this.name, required this.bio});

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(name, style: Theme.of(context).textTheme.displayMedium),
        SizedBox(height: 8),
        Text(bio, style: Theme.of(context).textTheme.bodyMedium),
      ],
    );
  }
}

class StyledButton extends StatelessWidget {
  final String label;

  const StyledButton({required this.label});

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () {},
      child: Text(
        label,
        style: Theme.of(context).textTheme.labelLarge,
      ),
    );
  }
}

Responsive Typography

React Native

import { Dimensions, StyleSheet } from 'react-native';

const { width } = Dimensions.get('window');

// Base dimensions for scaling
const baseWidth = 390; // iPhone 14

// Scale factor helper
const scale = (size: number) => {
  return Math.round((size * width) / baseWidth);
};

export const responsiveTypography = StyleSheet.create({
  // Scales proportionally with screen width
  displayLarge: {
    fontSize: scale(57),
    fontWeight: '400',
    lineHeight: scale(64),
  },
  headlineMedium: {
    fontSize: scale(28),
    fontWeight: '400',
    lineHeight: scale(36),
  },
  bodyMedium: {
    fontSize: scale(14),
    fontWeight: '400',
    lineHeight: scale(20),
  },
});

Flutter

class ResponsiveText extends StatelessWidget {
  final String text;
  final TextStyle style;

  const ResponsiveText({
    required this.text,
    required this.style,
  });

  @override
  Widget build(BuildContext context) {
    final screenWidth = MediaQuery.of(context).size.width;
    final scaleFactor = screenWidth / 390; // Base width

    return Text(
      text,
      style: style.copyWith(
        fontSize: style.fontSize! * scaleFactor.clamp(0.85, 1.15),
      ),
    );
  }
}

Dark Mode Typography

React Native

// Dark mode color adjustments for typography
export const darkThemeColors = {
  text: {
    // High contrast for dark backgrounds
    primary: '#FFFFFF',      // 100% opacity
    secondary: '#E3E3E3',    // 87% opacity
    tertiary: '#A0A0A0',     // 60% opacity
    disabled: '#4F4F4F',     // 38% opacity
  },
  background: {
    primary: '#121212',
    secondary: '#1E1E1E',
  },
};

// Apply to styles
const darkStyles = StyleSheet.create({
  headlineMedium: {
    fontSize: 28,
    fontWeight: '400',
    color: darkThemeColors.text.primary,
  },
  bodyMedium: {
    fontSize: 14,
    fontWeight: '400',
    color: darkThemeColors.text.secondary,
  },
  caption: {
    fontSize: 12,
    fontWeight: '400',
    color: darkThemeColors.text.tertiary,
  },
});

Flutter

class DarkThemeColors {
  static const Color textPrimary = Color(0xFFFFFFFF);
  static const Color textSecondary = Color(0xFFE3E3E3);
  static const Color textTertiary = Color(0xFFA0A0A0);
  static const Color textDisabled = Color(0xFF4F4F4F);

  static ThemeData buildDarkTheme() {
    return ThemeData(
      brightness: Brightness.dark,
      textTheme: TextTheme(
        displayMedium: AppTypography.displayMedium.copyWith(
          color: textPrimary,
        ),
        bodyMedium: AppTypography.bodyMedium.copyWith(
          color: textSecondary,
        ),
        bodySmall: AppTypography.bodySmall.copyWith(
          color: textTertiary,
        ),
      ),
    );
  }
}

Best Practices

DO's

// ✅ Use appropriate text style hierarchy
<Text style={styles.headlineMedium}>Page Title</Text>
<Text style={styles.bodyMedium}>Description</Text>

// ✅ Maintain consistent line height for readability
<Text style={[styles.bodyLarge, { lineHeight: 24 }]}>
  Long-form content with proper spacing
</Text>

// ✅ Use medium/semibold for emphasis (not bold)
<Text style={[styles.titleMedium, { fontWeight: '600' }]}>
  Important Information
</Text>

// ✅ Respect minimum readable size (12px)
<Text style={styles.bodySmall}>Caption text</Text>

DON'Ts

// ❌ Don't use arbitrary font sizes
<Text style={{ fontSize: 23 }}>Wrong</Text>

// ❌ Don't use bold for body text
<Text style={{ fontWeight: '700' }}>Hard to read</Text>

// ❌ Don't use font size below 11px
<Text style={{ fontSize: 10 }}>Too small</Text>

// ❌ Don't ignore line height
<Text style={{ lineHeight: 1 }}>Cramped text</Text>

Type Scale Reference

Style React Native Flutter Usage
Display
displayLarge 57px 57px Hero titles
displayMedium 45px 45px Page titles
displaySmall 36px 36px Section headers
Headline
headlineLarge 32px 32px Featured content
headlineMedium 28px 28px Card headers
headlineSmall 24px 24px List headers
Title
titleLarge 22px 22px Modal titles
titleMedium 16px 16px List items
titleSmall 14px 14px Subsections
Body
bodyLarge 16px 16px Primary text
bodyMedium 14px 14px Secondary text
bodySmall 12px 12px Captions
Label
labelLarge 14px 14px Buttons
labelMedium 12px 12px Tabs
labelSmall 11px 11px Badges

Font Weight Reference

Name Value Usage
Regular 400 Body text, display
Medium 500 Emphasis, buttons
Semibold 600 Headings, titles
Bold 700 Strong emphasis (rare)

Line Height Reference

Name Ratio Usage
Tight 1.1 Display text
Snug 1.25 Headings
Normal 1.5 Body text (recommended)
Relaxed 1.75 Long-form content