Custom Fonts

Font Property Architecture

This design system enforces complete decoupling of visual fonts from the primitive files. Everything resolves through two standard CSS variables defined at the document root:

--font-display

Used for display elements (brand logos, headings, titles).

--font-body

Used for body, paragraph copy, list texts, buttons, and form inputs.

Step 1 · Declare in Stylesheet

In your consumer application's root stylesheet (e.g., global.css), you can load local fonts or fallback declarations:

/* global.css */
:root {
  --font-display: 'Cinzel', serif;
  --font-body: 'Mulish', sans-serif;
}

Step 2 · Declare in ThemeProvider

If you are using the theme configuration manager, you can feed custom font names directly to the ThemeProvider element. The provider will automatically inject Google Font dependencies and resolve them on the document:

import { ThemeProvider } from "@shavin/ui";

export default function App({ children }) {
  return (
    <ThemeProvider 
      accentColor="grass" 
      radius="medium" 
      displayFont="Fraunces" 
      bodyFont="Outfit"
    >
      {children}
    </ThemeProvider>
  );
}

Local next/font Mapping (Next.js App Router)

For Next.js projects, use the standard next/font utility to optimize layout shift, mapping the output CSS variable names directly:

// app/layout.tsx
import { Inter, Fraunces } from 'next/font/google';

const displayFont = Fraunces({
  subsets: ['latin'],
  variable: '--font-display',
});

const bodyFont = Inter({
  subsets: ['latin'],
  variable: '--font-body',
});

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={`${displayFont.variable} ${bodyFont.variable}`}>
      <body>{children}</body>
    </html>
  );
}
Configure Theme
Theme
Accent Color
Custom
Gray Family
Appearance
Radius
Scaling
Panel Style
Heading Font
Body Font