Typography

A semantic typography primitive for headings, body copy, and inline code.

Usage

import { Typography } from '@hareui/vue'

Build better interfaces

Typography that stays semantic

Composable by default

Small heading

HeroUI Typography uses React Aria Components Text as the primitive, with semantic typography types and render-prop polymorphism.

Smaller muted body copy for secondary descriptions.

pnpm add @heroui/react
<script setup lang="ts">import { Typography } from '@hareui/vue'</script><template>  <div class="flex max-w-xl flex-col gap-4">    <Typography type="h1">Build better interfaces</Typography>    <Typography type="h2">Typography that stays semantic</Typography>    <Typography type="h3">Composable by default</Typography>    <Typography type="h4">Small heading</Typography>    <Typography>      HeroUI Typography uses React Aria Components Text as the primitive, with semantic typography      types and render-prop polymorphism.    </Typography>    <Typography color="muted" type="body-sm">      Smaller muted body copy for secondary descriptions.    </Typography>    <Typography type="code">pnpm add @heroui/react</Typography>  </div></template>

Anatomy

Typography maps visual type values to semantic elements by default.

<Typography type="h1">Heading</Typography>
  • type picks both the visual style and, unless as is set, the rendered element: h1–h6 → <h1>–<h6>, body/body-sm/body-xs → <p>, code → <code>.
  • prose switches to a rich-content container (<div data-slot="prose">): children are plain HTML and receive HeroUI's default typography rhythm instead of the type styles. type, align, color, weight and truncate are ignored in this mode.

ui keys: base, prose.

Examples

Scale

h136px / 600 / 1.11 / tight

Build better interfaces

h230px / 600 / 1.17 / tight

Built for the intelligence age

h324px / 600 / 1.25 / tight

Pricing on your terms

h420px / 600 / 1.33 / tight

Apply to the startup program

h518px / 600 / 1.39 / tight
Card titles
h616px / 600 / 1.50 / tight
Smaller feature headers
body16px / 400 / 1.75

Primary body text used across documentation, marketing copy, and descriptions.

body-sm14px / 400 / 1.50

Secondary body, table cells, navigation, and sidebar items.

body-xs12px / 400 / 1.25

Captions, badges, helper text, and fine print.

code14px / mono
pnpm add @heroui/react
<script setup lang="ts">import { Typography } from '@hareui/vue'const scale = [  { label: 'h1', meta: '36px / 600 / 1.11 / tight', sample: 'Build better interfaces', type: 'h1' as const },  { label: 'h2', meta: '30px / 600 / 1.17 / tight', sample: 'Built for the intelligence age', type: 'h2' as const },  { label: 'h3', meta: '24px / 600 / 1.25 / tight', sample: 'Pricing on your terms', type: 'h3' as const },  { label: 'h4', meta: '20px / 600 / 1.33 / tight', sample: 'Apply to the startup program', type: 'h4' as const },  { label: 'h5', meta: '18px / 600 / 1.39 / tight', sample: 'Card titles', type: 'h5' as const },  { label: 'h6', meta: '16px / 600 / 1.50 / tight', sample: 'Smaller feature headers', type: 'h6' as const },  { label: 'body', meta: '16px / 400 / 1.75', sample: 'Primary body text used across documentation, marketing copy, and descriptions.', type: 'body' as const },  { label: 'body-sm', meta: '14px / 400 / 1.50', sample: 'Secondary body, table cells, navigation, and sidebar items.', type: 'body-sm' as const },  { label: 'body-xs', meta: '12px / 400 / 1.25', sample: 'Captions, badges, helper text, and fine print.', type: 'body-xs' as const },  { label: 'code', meta: '14px / mono', sample: 'pnpm add @heroui/react', type: 'code' as const },]</script><template>  <div class="flex w-full flex-col divide-y divide-border">    <div v-for="row in scale" :key="row.label" class="grid grid-cols-[160px_1fr] items-center gap-8 py-5">      <div class="flex shrink-0 flex-col gap-0.5">        <span class="text-sm font-semibold text-foreground">{{ row.label }}</span>        <span class="text-xs whitespace-nowrap text-muted">{{ row.meta }}</span>      </div>      <Typography :type="row.type">{{ row.sample }}</Typography>    </div>  </div></template>

Primitives

Dashboard

Convenience primitives are thin wrappers over Typography, so you can choose explicit composition without learning a second styling system.

Paragraph supports base, sm, and xs sizes.

Typography.Code
<script setup lang="ts">import { Typography } from '@hareui/vue'</script><template>  <div class="flex max-w-xl flex-col gap-4">    <Typography type="h1">      Dashboard    </Typography>    <Typography>      Convenience primitives are thin wrappers over Typography, so you can choose explicit      composition without learning a second styling system.    </Typography>    <Typography color="muted" type="body-sm">      Paragraph supports base, sm, and xs sizes.    </Typography>    <Typography type="code">      Typography.Code    </Typography>  </div></template>
  • Typography.Heading level={1..6} maps to type="h1" through type="h6".
  • Typography.Paragraph size="base" | "sm" | "xs" maps to type="body", "body-sm" and "body-xs".
  • Typography.Code maps to type="code".
  • Typography.Prose maps to the prose prop, which styles rich content passed as regular HTML children.

Prose

<script setup lang="ts">import { Typography } from '@hareui/vue'</script><template>  <Typography class="flex max-w-xl flex-col gap-3" prose>    <h1>Prose title</h1>    <p>      Prose is for authored content where the markup is already semantic and HeroUI applies the      default typography rhythm.    </p>    <h2>Section title</h2>    <p>      Inline code like <code>render</code> receives the same code treatment as the Typography      primitive.    </p>  </Typography></template>

Render Props

H1 visual style, h2 semantic element

The render prop can swap the underlying element while preserving HeroUI props and styles.
<script setup lang="ts">import { Typography } from '@hareui/vue'</script><template>  <div class="flex max-w-xl flex-col gap-4">    <Typography as="h2" type="h1">      H1 visual style, h2 semantic element    </Typography>    <Typography as="span">      The render prop can swap the underlying element while preserving HeroUI props and styles.    </Typography>  </div></template>

Use the as prop when you need to customize the rendered element.

Customization

Tailwind CSS

Changelog

Faster search results

Queries now return in under 200ms thanks to an improved index.

<script setup lang="ts">import { Typography } from '@hareui/vue'</script><template>  <div class="flex max-w-md flex-col gap-2 rounded-xl border border-border/80 bg-surface-secondary p-4">    <Typography class="text-xs font-medium tracking-wide text-accent uppercase" type="body-xs">      Changelog    </Typography>    <Typography class="font-semibold tracking-tight text-foreground" type="h4">      Faster search results    </Typography>    <Typography class="text-sm leading-relaxed text-muted" type="body-sm">      Queries now return in under 200ms thanks to an improved index.    </Typography>  </div></template>

Global theme override

Override the typography theme app-wide with createHareUI:

app.use(createHareUI({
  ui: {
    typography: {
      variants: {
        type: {
          h1: { base: 'font-extrabold tracking-tight' },
          code: { base: 'rounded-md bg-default-100 font-mono dark:bg-default-50/20' },
        },
      },
    },
  },
}))

Styling Reference

Each rendered element carries the same data-slot string as HeroUI (typography for the default mode, prose for prose mode), so selectors translate 1:1.

ui keydata-slotDescription
basetypographyBase typography primitive
proseproseRich prose container

HeroUI follows BEM for its modifier classes (HareUI renders utilities, not BEM classes, so style through class, ui or createHareUI):

  • .typography--h1 through .typography--h6, .typography--body, .typography--body-sm, .typography--body-xs, .typography--code → the type prop
  • .typography--align-start, --align-center, --align-end, --align-justify → the align prop
  • .typography--color-default, --color-muted → the color prop
  • .typography--weight-normal, --weight-medium, --weight-semibold, --weight-bold → the weight prop
  • .typography--truncate → the truncate prop

API Reference

Props

PropTypeDefaultDescription
asAsTag | Component-The element or component to render as, overriding the element implied by type (equivalent to HeroUI's render prop).
type"body" | "h2" | "h3" | "code" | "h1" | "h4" | "h5" | "h6" | "body-sm" | "body-xs""body"Semantic typography style.
align"center" | "start" | "end" | "justify""start"Text alignment.
color"default" | "muted""default"Text color.
weight"bold" | "medium" | "normal" | "semibold"-Font weight override.
truncatebooleanfalseTruncates the text to one line with ellipsis.
prosebooleanfalseRenders a rich prose container instead: children are plain HTML (headings, paragraphs, links, lists, code, …) and receive HeroUI's default typography rhythm. type, align, color, weight and truncate are ignored in this mode.
uiComponentSlots<{ slots: { base: string; prose: string[]; }; variants: { type: { h1: { base: string; }; h2: { base: string; }; h3: { base: string; }; h4: { base: string; }; h5: { base: string; }; h6: { base: string; }; body: { base: string; }; 'body-sm': { base: string; }; 'body-xs': { base: string; }; code: { base: string; }; }; align: { start: { base: string; }; center: { base: string; }; end: { base: string; }; justify: { base: string; }; }; color: { default: { base: string; }; muted: { base: string; }; }; weight: { normal: { base: string; }; medium: { base: string; }; semibold: { base: string; }; bold: { base: string; }; }; truncate: { true: { base: string; }; }; }; defaultVariants: { type: string; align: string; color: string; }; }>-Per-slot class overrides.

Slots

SlotPropsDescription
defaultanyTypography content.

On this page

No Headings