VayuUI
Design System

Typography

Master Vayu UI's typography system with semantic font families and size scales for consistent, readable text.

Typography

Good typography is invisible — readers focus on your content, not the font. Vayu UI's typography system makes it easy to create consistent, readable text across your entire application.

The Three Font Tiers

Vayu UI uses three font families, each with a specific purpose:

TierFontCSS VariableTailwind ClassUsage
PrimaryOswald--font-primaryfont-primaryHeadings, labels, navigation
SecondaryMulish--font-secondaryfont-secondaryBody text, descriptions, captions
TertiaryGeist Mono--font-tertiaryfont-tertiaryCode, technical values, keyboard shortcuts

Primary Font: Oswald

Oswald is a condensed, bold sans-serif perfect for headlines and UI labels. It commands attention without being overwhelming.

Oswald Heading

Used for emphasis and hierarchy

// Page title
<h1 className="font-primary text-h1">Dashboard</h1>

// Section heading
<h2 className="font-primary text-h2">Recent Activity</h2>

// Navigation label
<span className="font-primary text-h5">Settings</span>

// Badge or label
<span className="font-primary text-h6 uppercase">New</span>

Secondary Font: Mulish

Mulish is a clean, rounded sans-serif designed for extended reading. Use it for all body text and descriptions.

Mulish is optimized for readability. Its rounded terminals and open apertures make it comfortable to read at any size, from small captions to large paragraphs.

// Body paragraph
<p className="font-secondary text-para">
  This is a paragraph of body text. It's easy to read and works well for extended content.
</p>

// Description text
<p className="font-secondary text-para text-muted-content">
  Enter your email address to receive updates about your account.
</p>

// Caption
<span className="font-secondary text-h6 text-muted-content">
  Last updated 5 minutes ago
</span>

Tertiary Font: Geist Mono

Geist Mono is a modern monospace font for code snippets, keyboard shortcuts, and technical values.

const greeting = "Hello, World!";

// Inline code
<code className="font-tertiary text-para">npm install vayu-ui</code>

// Code block
<pre className="font-tertiary text-para bg-muted p-4 rounded-surface">
  {`function greet(name) {

return \`Hello, \${name}!\`;
}`}
</pre>

// Keyboard shortcut
<kbd className="font-tertiary text-h6 bg-muted px-2 py-0.5 rounded-control">
  ⌘K
</kbd>

// Technical value
<span className="font-tertiary text-para">2024-01-15T14:30:00Z</span>

Semantic Size Scale

Vayu UI provides semantic text sizes. Instead of using arbitrary sizes like text-2xl, use semantic sizes that convey meaning.

The Size Scale

ClassSizeComputedUsage
text-h11.875rem30pxHero headings, page titles
text-h21.5rem24pxSection headings
text-h31.25rem20pxCard headings, subsections
text-h41.125rem18pxForm labels, important inline text
text-h51rem16pxNavigation links, button text
text-h60.875rem14pxSecondary labels, captions
text-para0.875rem14pxBody copy, paragraphs

Size Hierarchy Preview

Heading 130px — Hero titles
Heading 224px — Sections
Heading 320px — Cards, subsections
Heading 418px — Form labels
Heading 516px — Nav, buttons
Heading 614px — Captions, small labels
Paragraph text for body content and descriptions.14px — Body text

Dashboard Overview

Welcome back! Here's what's happening with your projects today.

Recent Activity

New user signup2 minutes ago
Deployment completed15 minutes ago

Quick Stats

1,234Users
567Projects
89%Uptime

Do's and Don'ts

Using Semantic Sizes

Do ✅Don't ❌
text-h1 for page titlestext-3xl for page titles
text-h2 for section headingstext-2xl for section headings
text-para for body texttext-base or text-sm for body
Let the system define hierarchyManually adjust font sizes

Why Semantic Sizes Matter

// ✅ Good: Semantic sizes convey meaning
<h1 className="text-h1 font-primary">Page Title</h1>
<h2 className="text-h2 font-primary">Section</h2>
<p className="text-para font-secondary">Body content</p>

// ❌ Bad: Arbitrary sizes don't convey meaning
<h1 className="text-3xl font-primary">Page Title</h1>
<h2 className="text-2xl font-primary">Section</h2>
<p className="text-sm font-secondary">Body content</p>

When you use semantic sizes:

  • Consistency is automatic across your app
  • Updates are easy (change one variable, update everywhere)
  • Accessibility is built in (proper hierarchy for screen readers)
  • Dark mode works seamlessly

Combining Fonts and Sizes

The Golden Combinations

ElementFontSizeFull Class
Page TitlePrimaryh1font-primary text-h1
Section HeadingPrimaryh2font-primary text-h2
Card TitlePrimaryh3font-primary text-h3
Form LabelPrimaryh4font-primary text-h4
Button TextPrimaryh5font-primary text-h5
NavigationPrimaryh5font-primary text-h5
CaptionPrimaryh6font-primary text-h6
Body TextSecondaryparafont-secondary text-para
DescriptionSecondaryparafont-secondary text-para text-muted-content
CodeTertiaryparafont-tertiary text-para

Complete Example

export function BlogPost({ title, date, excerpt, content }) {
  return (
    <article className="bg-surface text-surface-content rounded-surface p-6">
      {/* Page title */}
      <h1 className="font-primary text-h1 mb-2">{title}</h1>

      {/* Meta info */}
      <div className="flex items-center gap-4 mb-6">
        <time className="font-secondary text-h6 text-muted-content">{date}</time>
        <span className="font-tertiary text-h6 text-muted-content">5 min read</span>
      </div>

      {/* Excerpt (lead paragraph) */}
      <p className="font-secondary text-para text-surface-content mb-6">{excerpt}</p>

      {/* Main content */}
      <div className="prose">
        <p className="font-secondary text-para mb-4">{content}</p>
      </div>

      {/* Code example */}
      <pre className="font-tertiary text-para bg-muted p-4 rounded-surface mt-6">
        <code>npm install vayu-ui</code>
      </pre>
    </article>
  );
}

Text Colors

Combine typography with Vayu UI's color system for proper contrast.

Standard Text Colors

ClassUsageWhen to Use
text-surface-contentPrimary textHeadlines, important content
text-muted-contentSecondary textDescriptions, captions, placeholders
text-brandBrand accentLinks, active states
text-destructiveError textValidation errors, warnings
text-successSuccess textConfirmations, completed states

Example with Colors

<div className="bg-surface rounded-surface p-6">
  {/* Primary text */}
  <h2 className="font-primary text-h2 text-surface-content mb-2">Account Settings</h2>

  {/* Secondary text */}
  <p className="font-secondary text-para text-muted-content mb-4">
    Manage your account preferences and security settings.
  </p>

  {/* Form label */}
  <label className="font-primary text-h4 text-surface-content block mb-2">Email Address</label>

  {/* Input with placeholder */}
  <input
    className="font-secondary text-para bg-surface border border-field rounded-control px-3 py-2 placeholder:text-muted-content"
    placeholder="Enter your email..."
  />

  {/* Helper text */}
  <p className="font-secondary text-h6 text-muted-content mt-1">
    We'll never share your email with anyone.
  </p>
</div>

Font Loading

Vayu UI expects these fonts to be loaded. Add them to your project's font configuration:

Using Next.js Font Optimization

// app/layout.tsx
import { Oswald, Mulish, Geist_Mono } from 'next/font/google';

const oswald = Oswald({
  subsets: ['latin'],
  variable: '--font-primary',
});

const mulish = Mulish({
  subsets: ['latin'],
  variable: '--font-secondary',
});

const geistMono = Geist_Mono({
  subsets: ['latin'],
  variable: '--font-tertiary',
});

export default function RootLayout({ children }) {
  return (
    <html className={`${oswald.variable} ${mulish.variable} ${geistMono.variable}`}>
      <body>{children}</body>
    </html>
  );
}

Using CSS @font-face

/* In your global CSS */
@font-face {
  font-family: 'Oswald';
  src: url('/fonts/Oswald.woff2') format('woff2');
  font-weight: 400 700;
  font-display: swap;
}

@font-face {
  font-family: 'Mulish';
  src: url('/fonts/Mulish.woff2') format('woff2');
  font-weight: 400 700;
  font-display: swap;
}

@font-face {
  font-family: 'Geist Mono';
  src: url('/fonts/GeistMono.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}

Quick Reference

Typography Cheat Sheet

// Page structure
<h1 className="font-primary text-h1">Page Title</h1>
<h2 className="font-primary text-h2">Section</h2>
<h3 className="font-primary text-h3">Card Title</h3>
<h4 className="font-primary text-h4">Form Label</h4>
<h5 className="font-primary text-h5">Button / Nav</h5>
<h6 className="font-primary text-h6">Caption</h6>
<p className="font-secondary text-para">Body text</p>
<code className="font-tertiary text-para">code</code>

// With colors
<h1 className="font-primary text-h1 text-surface-content">Title</h1>
<p className="font-secondary text-para text-muted-content">Description</p>
<a className="font-secondary text-para text-brand">Link</a>
<span className="font-tertiary text-h6">⌘K</span>

CSS Variables

/* Font families */
--font-primary: 'Oswald', sans-serif;
--font-secondary: 'Mulish', sans-serif;
--font-tertiary: 'Geist Mono', monospace;

/* Font sizes */
--text-h1: 1.875rem; /* 30px */
--text-h2: 1.5rem; /* 24px */
--text-h3: 1.25rem; /* 20px */
--text-h4: 1.125rem; /* 18px */
--text-h5: 1rem; /* 16px */
--text-h6: 0.875rem; /* 14px */
--text-para: 0.875rem; /* 14px */

On this page