> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/kapishdima/fonttrio/llms.txt
> Use this file to discover all available pages before exploring further.

# Using Fonttrio with shadcn/ui

> Learn how to integrate Fonttrio font pairings with shadcn/ui components and apply custom typography across your component library.

Fonttrio is designed specifically for shadcn/ui projects. This guide shows you how to apply font pairings to shadcn/ui components, customize component typography, and follow best practices for a cohesive design system.

## Why Fonttrio Works with shadcn/ui

Fonttrio uses the same distribution system as shadcn/ui:

* **Registry-based installation** via the shadcn CLI
* **Next.js + Tailwind** as the foundation
* **CSS variables** for theming and customization
* **Copy-paste components** that you fully own and can modify

Because both use CSS variables, fonts integrate seamlessly with shadcn/ui's theming system.

## Prerequisites

Before integrating Fonttrio with shadcn/ui:

<Steps>
  <Step title="Install shadcn/ui">
    Set up shadcn/ui in your Next.js project.

    ```bash theme={null}
    npx shadcn@latest init
    ```
  </Step>

  <Step title="Install a Fonttrio Pairing">
    Add your chosen font pairing.

    ```bash theme={null}
    npx shadcn@latest add https://www.fonttrio.xyz/r/editorial.json
    ```
  </Step>

  <Step title="Apply Fonts to Layout">
    Add font variables to your root layout.

    ```tsx app/layout.tsx theme={null}
    import { editorial } from "@/registry/pairings/editorial";
    import "./globals.css";

    export default function RootLayout({ children }) {
      return (
        <html className={`
          ${editorial.heading.variable} 
          ${editorial.body.variable} 
          ${editorial.mono.variable}
        `}>
          <body>{children}</body>
        </html>
      );
    }
    ```
  </Step>
</Steps>

## Applying Fonts to Components

Once fonts are installed, they automatically apply to shadcn/ui components through CSS variables.

### Typography Components

Heading and text components inherit fonts from the typography scale:

```tsx theme={null}
import { Button } from "@/components/ui/button";
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";

export function Example() {
  return (
    <Card>
      <CardHeader>
        <CardTitle>Card Title</CardTitle>  {/* Uses --font-heading */}
      </CardHeader>
      <CardContent>
        <p>Card content text</p>  {/* Uses --font-body */}
      </CardContent>
    </Card>
  );
}
```

### Button Components

Buttons use body font by default:

```tsx theme={null}
import { Button } from "@/components/ui/button";

<Button>Click me</Button>  {/* Uses --font-body */}
```

Override with heading font for emphasis:

```tsx theme={null}
<Button className="font-[family-name:var(--font-heading)]">
  Bold CTA
</Button>
```

### Form Components

Input fields, labels, and form elements use body font:

```tsx theme={null}
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";

<div>
  <Label htmlFor="email">Email</Label>  {/* Uses --font-body */}
  <Input id="email" type="email" />     {/* Uses --font-body */}
  <Textarea placeholder="Message" />    {/* Uses --font-body */}
</div>
```

### Code Components

Code blocks and inline code use monospace font:

```tsx theme={null}
import { Badge } from "@/components/ui/badge";

<code className="font-[family-name:var(--font-mono)]">
  npm install
</code>

<pre className="font-[family-name:var(--font-mono)]">
  <code>const example = true;</code>
</pre>
```

<Note>
  If you've installed a Fonttrio pairing, the global CSS already applies `--font-mono` to `<code>` and `<pre>` elements, so you don't need to add classes manually.
</Note>

## Customizing Component Typography

You can customize how fonts apply to specific components.

### Modify Component Files

Since shadcn/ui components are copied into your project, you can edit them directly:

```tsx components/ui/card.tsx theme={null}
const Card = React.forwardRef<HTMLDivElement, CardProps>(
  ({ className, ...props }, ref) => (
    <div
      ref={ref}
      className={cn(
        "rounded-lg border bg-card text-card-foreground shadow-sm",
        "font-[family-name:var(--font-body)]", // Explicitly set body font
        className
      )}
      {...props}
    />
  )
)

const CardTitle = React.forwardRef<HTMLParagraphElement, CardTitleProps>(
  ({ className, ...props }, ref) => (
    <h3
      ref={ref}
      className={cn(
        "text-2xl font-semibold leading-none tracking-tight",
        "font-[family-name:var(--font-heading)]", // Explicitly set heading font
        className
      )}
      {...props}
    />
  )
)
```

### Create Font-Aware Variants

Add font variants to component APIs using `cva`:

```tsx components/ui/button.tsx theme={null}
import { cva, type VariantProps } from "class-variance-authority";

const buttonVariants = cva(
  "inline-flex items-center justify-center...",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground...",
        outline: "border border-input...",
      },
      size: {
        default: "h-10 px-4 py-2",
        sm: "h-9 px-3",
        lg: "h-11 px-8",
      },
      font: {
        body: "font-[family-name:var(--font-body)]",
        heading: "font-[family-name:var(--font-heading)]",
        mono: "font-[family-name:var(--font-mono)]",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "default",
      font: "body",
    },
  }
);
```

Use in components:

```tsx theme={null}
<Button font="heading">Bold CTA</Button>
<Button font="mono">Technical Action</Button>
```

### Create Typography Utilities

Define reusable typography classes:

```css app/globals.css theme={null}
@layer utilities {
  .font-heading {
    font-family: var(--font-heading);
  }

  .font-body {
    font-family: var(--font-body);
  }

  .font-mono {
    font-family: var(--font-mono);
  }
}
```

Or extend Tailwind config:

```js tailwind.config.js theme={null}
module.exports = {
  theme: {
    extend: {
      fontFamily: {
        heading: "var(--font-heading)",
        body: "var(--font-body)",
        mono: "var(--font-mono)",
      },
    },
  },
}
```

Use in components:

```tsx theme={null}
<h1 className="font-heading">Heading</h1>
<p className="font-body">Body text</p>
<code className="font-mono">Code</code>
```

## Component-Specific Examples

### Accordion

```tsx theme={null}
import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from "@/components/ui/accordion";

<Accordion type="single" collapsible>
  <AccordionItem value="item-1">
    <AccordionTrigger className="font-heading text-lg">
      Styled with heading font
    </AccordionTrigger>
    <AccordionContent className="font-body">
      Content uses body font for readability.
    </AccordionContent>
  </AccordionItem>
</Accordion>
```

### Tabs

```tsx theme={null}
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";

<Tabs defaultValue="tab1">
  <TabsList>
    <TabsTrigger value="tab1" className="font-heading">Features</TabsTrigger>
    <TabsTrigger value="tab2" className="font-heading">Pricing</TabsTrigger>
  </TabsList>
  <TabsContent value="tab1" className="font-body">
    Feature description text...
  </TabsContent>
</Tabs>
```

### Dialog

```tsx theme={null}
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog";

<Dialog>
  <DialogContent>
    <DialogHeader>
      <DialogTitle className="font-heading">Dialog Title</DialogTitle>
      <DialogDescription className="font-body">
        This description uses the body font.
      </DialogDescription>
    </DialogHeader>
  </DialogContent>
</Dialog>
```

### Badge

```tsx theme={null}
import { Badge } from "@/components/ui/badge";

{/* Default: uses body font */}
<Badge>New</Badge>

{/* Monospace for technical badges */}
<Badge className="font-mono">v2.0.1</Badge>

{/* Heading font for emphasis */}
<Badge className="font-heading font-bold">Featured</Badge>
```

### Select

```tsx theme={null}
import { Select, SelectTrigger, SelectContent, SelectItem, SelectValue } from "@/components/ui/select";

<Select>
  <SelectTrigger className="font-body">
    <SelectValue placeholder="Choose option" />
  </SelectTrigger>
  <SelectContent>
    <SelectItem value="option1" className="font-body">Option 1</SelectItem>
    <SelectItem value="option2" className="font-body">Option 2</SelectItem>
  </SelectContent>
</Select>
```

## Dark Mode Considerations

Fonttrio pairings work seamlessly with shadcn/ui's dark mode:

```tsx theme={null}
import { ThemeProvider } from "@/components/theme-provider";
import { editorial } from "@/registry/pairings/editorial";

export default function RootLayout({ children }) {
  return (
    <html 
      className={`
        ${editorial.heading.variable} 
        ${editorial.body.variable} 
        ${editorial.mono.variable}
      `}
      suppressHydrationWarning
    >
      <body>
        <ThemeProvider attribute="class" defaultTheme="system">
          {children}
        </ThemeProvider>
      </body>
    </html>
  );
}
```

### Adjusting Font Weight for Dark Mode

Some fonts may need lighter weights in dark mode:

```css app/globals.css theme={null}
@layer base {
  h1 {
    font-family: var(--font-heading);
    font-weight: 700;
  }

  .dark h1 {
    font-weight: 600;  /* Lighter in dark mode */
  }

  .dark body, .dark p {
    font-weight: 400;  /* Ensure readability */
  }
}
```

## Best Practices

### 1. Maintain Consistency

Use the same fonts for similar UI elements:

```tsx theme={null}
// Good: Consistent button text
<Button>Submit</Button>
<Button>Cancel</Button>

// Avoid: Mixing fonts arbitrarily
<Button className="font-heading">Submit</Button>
<Button className="font-mono">Cancel</Button>
```

### 2. Respect Component Semantics

Use heading fonts for titles, body fonts for content:

```tsx theme={null}
// Good
<CardTitle className="font-heading">Title</CardTitle>
<CardDescription className="font-body">Description</CardDescription>

// Avoid
<CardTitle className="font-mono">Title</CardTitle>
```

### 3. Test with Real Content

Test components with actual text, not placeholder content:

```tsx theme={null}
// Test with realistic lengths
<CardTitle>Understanding the Impact of Typography on User Experience</CardTitle>
<CardDescription>
  Typography plays a crucial role in how users perceive and interact with
  your application. Choosing the right fonts can improve readability and
  establish visual hierarchy.
</CardDescription>
```

### 4. Consider Font Fallbacks

Ensure graceful degradation:

```tsx theme={null}
import { Inter } from "next/font/google";

const inter = Inter({
  subsets: ["latin"],
  display: "swap",
  fallback: ["system-ui", "arial"],  // Fallback fonts
});
```

### 5. Use Monospace Appropriately

Reserve monospace fonts for code and technical content:

```tsx theme={null}
// Good uses
<code className="font-mono">npm install</code>
<Badge className="font-mono">v1.0.0</Badge>
<Input className="font-mono" type="text" placeholder="API Key" />

// Avoid
<Button className="font-mono">Click me</Button>
<CardTitle className="font-mono">Welcome</CardTitle>
```

## Building a Design System

Create a comprehensive design system with Fonttrio + shadcn/ui:

### Define Typography Tokens

```ts lib/design-tokens.ts theme={null}
export const typography = {
  fonts: {
    heading: "var(--font-heading)",
    body: "var(--font-body)",
    mono: "var(--font-mono)",
  },
  sizes: {
    xs: "0.75rem",
    sm: "0.875rem",
    base: "1rem",
    lg: "1.125rem",
    xl: "1.25rem",
    "2xl": "1.5rem",
    "3xl": "1.875rem",
    "4xl": "2.25rem",
  },
  weights: {
    light: 300,
    normal: 400,
    medium: 500,
    semibold: 600,
    bold: 700,
  },
  lineHeights: {
    tight: "1.2",
    normal: "1.5",
    relaxed: "1.65",
    loose: "1.75",
  },
};
```

### Create Reusable Typography Components

```tsx components/typography/heading.tsx theme={null}
import { cn } from "@/lib/utils";
import { typography } from "@/lib/design-tokens";

interface HeadingProps extends React.HTMLAttributes<HTMLHeadingElement> {
  level?: 1 | 2 | 3 | 4 | 5 | 6;
  as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
}

export function Heading({ 
  level = 1, 
  as, 
  className, 
  children,
  ...props 
}: HeadingProps) {
  const Tag = as || `h${level}` as const;
  
  return (
    <Tag
      className={cn(
        "font-heading scroll-m-20",
        className
      )}
      {...props}
    >
      {children}
    </Tag>
  );
}
```

```tsx components/typography/text.tsx theme={null}
import { cn } from "@/lib/utils";

interface TextProps extends React.HTMLAttributes<HTMLParagraphElement> {
  size?: "sm" | "base" | "lg";
  variant?: "body" | "mono";
}

export function Text({ 
  size = "base", 
  variant = "body",
  className, 
  children,
  ...props 
}: TextProps) {
  const fontClass = variant === "mono" ? "font-mono" : "font-body";
  
  return (
    <p
      className={cn(
        fontClass,
        size === "sm" && "text-sm",
        size === "base" && "text-base",
        size === "lg" && "text-lg",
        className
      )}
      {...props}
    >
      {children}
    </p>
  );
}
```

Use in components:

```tsx theme={null}
import { Heading } from "@/components/typography/heading";
import { Text } from "@/components/typography/text";

<div>
  <Heading level={1}>Page Title</Heading>
  <Text size="lg">Introduction paragraph...</Text>
  <Heading level={2}>Section Title</Heading>
  <Text>Section content...</Text>
  <Text variant="mono" size="sm">Technical note</Text>
</div>
```

## Troubleshooting

### Fonts Not Applying to Components

If shadcn/ui components don't show your fonts:

1. Verify font variables are in the `<html>` element, not `<body>`
2. Check that `globals.css` is imported before component usage
3. Inspect in DevTools to see which font is actually applied
4. Ensure Tailwind isn't purging the font classes (check `tailwind.config.js`)

### Component Styles Overriding Fonts

If component styles override your fonts:

1. Use `!important` sparingly: `className="!font-heading"`
2. Increase specificity by editing the component file directly
3. Check the component's default className prop for conflicting font settings

### Fonts Look Different Than Preview Site

If your implementation doesn't match the Fonttrio preview:

1. Verify you're using the same typography scale (check `globals.css`)
2. Ensure font weights are loading correctly (check Network tab)
3. Compare line height and letter spacing values
4. Check that you're not overriding font settings with Tailwind classes

## Example: Complete Component Integration

Here's a full example of a Card component with proper typography:

```tsx components/feature-card.tsx theme={null}
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";

interface FeatureCardProps {
  title: string;
  description: string;
  version: string;
  codeExample: string;
}

export function FeatureCard({ 
  title, 
  description, 
  version, 
  codeExample 
}: FeatureCardProps) {
  return (
    <Card>
      <CardHeader>
        <div className="flex items-start justify-between">
          <CardTitle className="font-heading text-2xl">
            {title}
          </CardTitle>
          <Badge className="font-mono text-xs">
            {version}
          </Badge>
        </div>
        <CardDescription className="font-body text-base leading-relaxed">
          {description}
        </CardDescription>
      </CardHeader>
      <CardContent>
        <pre className="font-mono text-sm bg-muted p-4 rounded-md overflow-x-auto">
          <code>{codeExample}</code>
        </pre>
        <Button className="font-body mt-4 w-full">
          Learn More
        </Button>
      </CardContent>
    </Card>
  );
}
```

Usage:

```tsx theme={null}
<FeatureCard
  title="Typography Scale"
  description="Each pairing includes a complete typography scale from h1 through body text, with carefully tuned sizes, weights, and spacing."
  version="v2.0"
  codeExample={`const scale = {
  h1: { size: "2.25rem", weight: 700 },
  body: { size: "1rem", lineHeight: "1.65" },
};`}
/>
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Browse Pairings" icon="eye" href="/guides/browsing-pairings">
    Explore all 49 curated font pairings with live previews.
  </Card>

  <Card title="Customize Typography" icon="sliders" href="/guides/customizing-typography">
    Fine-tune font sizes, weights, and spacing for your design.
  </Card>
</CardGroup>
