Skip to content

Typography

The DS-Bridge typography system provides a consistent, scalable type hierarchy that works across all screen sizes and contexts.

Font Family

DS-Bridge uses Roboto as the primary font family, a modern, legible sans-serif typeface designed for optimal readability on screens.

Base Font

Roboto
typescript
typography.fontFamily.base =
  'Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, sans-serif'

Fallback Stack:

  1. Roboto (primary)
  2. -apple-system (iOS/macOS system font)
  3. BlinkMacSystemFont (macOS)
  4. Segoe UI (Windows)
  5. Helvetica Neue (fallback)
  6. Arial (universal fallback)
  7. sans-serif (generic)

Code Font

For code blocks and monospace text:

const example = 'Menlo, Monaco, Courier New';
typescript
typography.fontFamily.code =
  'Menlo, Monaco, "Courier New", monospace'

Font Weights

DS-Bridge provides five font weights for hierarchy and emphasis:

light (300)
Light weight for subtle headings
regular (400)
Regular weight for body text
medium (500)
Medium weight for emphasis
semibold (600)
Semibold for sub-headings
bold (700)
Bold weight for headings
typescript
export const fontWeight = {
  light: 300,
  regular: 400,
  medium: 500,
  semibold: 600,
  bold: 700,
};

Font Size Scale

A modular scale from extra small to 3xl:

xs (12px)
Extra small - captions, labels
sm (14px)
Small - secondary text, buttons
base (16px)
Base - body text, paragraphs
lg (18px)
Large - emphasized text, small headings
xl (20px)
Extra large - h4, prominent text
2xl (24px)
2X large - h3, section headings
3xl (30px)
3X large - h1/h2, hero text
typescript
export const fontSize = {
  xs: '12px',
  sm: '14px',
  base: '16px',
  lg: '18px',
  xl: '20px',
  '2xl': '24px',
  '3xl': '30px',
};

Line Height

Line height controls vertical rhythm and readability:

tight (1.2) - Headings
The quick brown fox
jumps over the lazy dog
normal (1.5) - Body text
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
relaxed (1.75) - Long-form content
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
typescript
export const lineHeight = {
  tight: 1.2,     // Headings
  normal: 1.5,    // UI elements, body text
  relaxed: 1.75,  // Long-form content, articles
};

Type Hierarchy

Headings

Heading 1 - 30px/Bold/1.2

Heading 2 - 24px/Bold/1.2

Heading 3 - 20px/Bold/1.2

Heading 4 - 18px/Bold/1.2

Heading 5 - 16px/Bold/1.2
Heading 6 - 16px/Semibold/1.2

Body Text

Body Large (16px/Regular/1.5)
This is the default body text size. It provides excellent readability for most content and is the foundation of the type system.

Body Small (14px/Regular/1.5)
This is secondary body text. Use it for supporting information, captions, or less prominent content.

Caption (12px/Regular/1.5)
This is caption text. Use it for labels, timestamps, and tertiary information.

Usage Examples

In Vue Components

vue
<template>
  <div>
    <h1 :style="headingStyles">Page Title</h1>
    <p :style="bodyStyles">This is body text with proper spacing.</p>
    <span :style="captionStyles">Updated 2 hours ago</span>
  </div>
</template>

<script setup>
import { tokens } from 'ds-bridge/tokens';
import { computed } from 'vue';

const headingStyles = computed(() => ({
  fontFamily: tokens.typography.fontFamily.base,
  fontSize: tokens.typography.fontSize['3xl'],
  fontWeight: tokens.typography.fontWeight.bold,
  lineHeight: tokens.typography.lineHeight.tight,
  color: tokens.colors.textHigh,
}));

const bodyStyles = computed(() => ({
  fontFamily: tokens.typography.fontFamily.base,
  fontSize: tokens.typography.fontSize.base,
  fontWeight: tokens.typography.fontWeight.regular,
  lineHeight: tokens.typography.lineHeight.normal,
  color: tokens.colors.textMedium,
}));

const captionStyles = computed(() => ({
  fontFamily: tokens.typography.fontFamily.base,
  fontSize: tokens.typography.fontSize.xs,
  fontWeight: tokens.typography.fontWeight.regular,
  lineHeight: tokens.typography.lineHeight.normal,
  color: tokens.colors.textLow,
}));
</script>

With CSS Custom Properties

css
/* Typography using design tokens */
h1 {
  font-family: var(--ds-font-family-base);
  font-size: var(--ds-font-size-3xl);
  font-weight: var(--ds-font-weight-bold);
  line-height: var(--ds-line-height-tight);
  color: var(--ds-color-text-high);
}

p {
  font-family: var(--ds-font-family-base);
  font-size: var(--ds-font-size-base);
  font-weight: var(--ds-font-weight-regular);
  line-height: var(--ds-line-height-normal);
  color: var(--ds-color-text-medium);
}

code {
  font-family: var(--ds-font-family-code);
  font-size: var(--ds-font-size-sm);
}

Typography Patterns

Emphasis Hierarchy

vue
<template>
  <div>
    <!-- High emphasis -->
    <h2 :style="{ color: tokens.colors.textHigh }">
      Main Heading
    </h2>

    <!-- Medium emphasis -->
    <p :style="{ color: tokens.colors.textMedium }">
      Body text with normal emphasis
    </p>

    <!-- Low emphasis -->
    <span :style="{ color: tokens.colors.textLow }">
      Supporting information
    </span>
  </div>
</template>

Responsive Typography

vue
<script setup>
import { tokens } from 'ds-bridge/tokens';
import { computed, onMounted, ref } from 'vue';

const isMobile = ref(false);

onMounted(() => {
  isMobile.value = window.innerWidth < 768;
});

const responsiveHeading = computed(() => ({
  fontSize: isMobile.value
    ? tokens.typography.fontSize['2xl']
    : tokens.typography.fontSize['3xl'],
}));
</script>

<template>
  <h1 :style="responsiveHeading">
    Responsive Heading
  </h1>
</template>

Best Practices

DO

✅ Use the type scale consistently

css
/* Use defined sizes */
font-size: var(--ds-font-size-lg);

✅ Match font weight to emphasis

css
/* Bold for headings */
h1 { font-weight: var(--ds-font-weight-bold); }

/* Regular for body */
p { font-weight: var(--ds-font-weight-regular); }

✅ Use appropriate line heights

css
/* Tight for headings */
h1 { line-height: var(--ds-line-height-tight); }

/* Relaxed for long-form */
article p { line-height: var(--ds-line-height-relaxed); }

DON'T

❌ Use arbitrary font sizes

css
/* Bad - non-standard size */
font-size: 17px;

/* Good - use scale */
font-size: var(--ds-font-size-lg);

❌ Mix multiple font families

css
/* Bad - inconsistent */
.title { font-family: 'Arial'; }
.body { font-family: 'Helvetica'; }

/* Good - consistent */
font-family: var(--ds-font-family-base);

❌ Use extreme line heights

css
/* Bad - too tight */
line-height: 1.0;

/* Good - use scale */
line-height: var(--ds-line-height-tight);

Accessibility

Readable Font Sizes

  • Minimum body text: 16px (base)
  • Minimum interactive elements: 14px (sm)
  • Never use fonts smaller than 12px (xs)

Sufficient Line Height

  • Body text: 1.5 (normal) minimum
  • Headings: 1.2 (tight) minimum
  • Long-form content: 1.75 (relaxed) recommended

Color Contrast

Ensure text meets WCAG 2.1 AAA standards:

vue
<!-- High contrast for readability -->
<p :style="{
  color: tokens.colors.textHigh,
  backgroundColor: tokens.colors.surface
}">
  Highly readable text
</p>

Figma Integration

Typography tokens map to Figma text styles:

Code TokenFigma Text Style
fontSize.baseTypography/Sizes/font-size-16
fontSize.smTypography/Sizes/font-size-14
fontWeight.mediumTypography/Weights/fw-medium-500
fontFamily.baseTypography/body-font-family

Learn More


Questions about typography? Check out the style guide for more patterns.

Built with Vue 3, Vuetify 3, and TypeScript