Glin UI
Primitive / Atom

Heading

Semantic heading primitive with independent style scaling.

Edit on GitHub

Engineering, 8 min read

How we cut cold starts from 900 ms to 90 ms

A walk through snapshotting, lazy imports and the one runtime flag that did most of the work.

MK
Maya KovacsPlatform team, Oct 7 2026

Installation

Install from
pnpm dlx @glinui/cli@latest add heading

Prefer the package?

Usage

Type scale

Six sizes, independent of the semantic level.

Quarterly review

size="display"

Quarterly review

size="h2"

Quarterly review

size="h3"

Quarterly review

size="lg"

Quarterly review

size="md"

Quarterly review

size="sm"
import { Heading } from "@glinui/ui"
const scale = ["display", "h2", "h3", "lg", "md", "sm"] as const
export function TypeScale() {
return (
<div className="flex w-full max-w-2xl flex-col divide-y divide-[var(--line-soft)] rounded-xl border border-[var(--line-soft)] bg-[var(--surface-1)] text-left">
{scale.map((size) => (
<div key={size} className="flex items-baseline justify-between gap-4 px-5 py-3">
<Heading level={2} size={size}>Quarterly review</Heading>
<code className="shrink-0 font-mono text-xs text-[var(--color-muted)]">size="{size}"</code>
</div>
))}
</div>
)
}

Variants

Outline, ghost and glass surfaces. Glass needs a colorful backdrop behind it.

Default

Outline

Ghost

Glass

import { Heading } from "@glinui/ui"
export function HeadingVariants() {
return (
<div data-glin-theme="dark" className="flex w-full flex-wrap items-center justify-center gap-4 rounded-xl bg-gradient-to-br from-indigo-600 via-purple-600 to-pink-500 p-8">
<Heading level={3} size="sm">Default</Heading>
<Heading level={3} size="sm" variant="outline">Outline</Heading>
<Heading level={3} size="sm" variant="ghost">Ghost</Heading>
<Heading level={3} size="sm" variant="glass">Glass</Heading>
</div>
)
}

In a layout

Card headings inside a blog index, level 2 for the section and level 3 for each post.

Latest from the blog

All posts
  • Designing a status page people actually read

    ALDesign, 5 min
  • Why we moved billing events to a queue

    JTBackend, 9 min
  • A checklist for accessible data tables

    RSFrontend, 6 min
import { Avatar, Heading, Link } from "@glinui/ui"
const posts = [
{ title: "Designing a status page people actually read", meta: "Design, 5 min", who: "AL" },
{ title: "Why we moved billing events to a queue", meta: "Backend, 9 min", who: "JT" },
{ title: "A checklist for accessible data tables", meta: "Frontend, 6 min", who: "RS" }
]
export function PostList() {
return (
<section aria-label="Latest posts" className="flex w-full max-w-2xl flex-col gap-4 text-left">
<div className="flex items-end justify-between gap-4">
<Heading level={2} size="md">Latest from the blog</Heading>
<Link href="/blog" variant="arrow" size="sm">All posts</Link>
</div>
<ul className="grid gap-3 sm:grid-cols-3">
{posts.map((post) => (
<li key={post.title} className="flex flex-col gap-3 rounded-xl border border-[var(--line-soft)] bg-[var(--surface-1)] p-4">
<Heading level={3} size="sm">{post.title}</Heading>
<div className="mt-auto flex items-center gap-2 text-xs text-[var(--color-muted)]">
<Avatar fallback={post.who} size="xs" />
{post.meta}
</div>
</li>
))}
</ul>
</section>
)
}

Glass (opt-in)

Glass is opt-in and needs a backdrop behind it. Switch the preview stage to Vivid or Photo to see the frosted surface.

Frosted heading

import { Heading } from "@glinui/ui"
export function Demo() {
return <Heading variant="glass">Frosted heading</Heading>
}

Variants

The `variant` prop applies a surface treatment, useful when a heading needs to sit on a glass card or a transparent overlay.

import { Heading } from "@glinui/ui"

export function HeadingVariantDemo() {
  return (
    <div className="space-y-2">
      <Heading variant="default">Default Heading</Heading>
      <Heading variant="glass">Glass Heading</Heading>
      <Heading variant="outline">Outline Heading</Heading>
      <Heading variant="ghost">Ghost Heading</Heading>
    </div>
  )
}

Sizes

import { Heading } from "@glinui/ui"

export function HeadingSizeDemo() {
  return (
    <div className="space-y-2">
      <Heading size="sm">Small heading</Heading>
      <Heading size="md">Medium heading</Heading>
      <Heading size="lg">Large heading</Heading>
    </div>
  )
}

Independent Level and Size

The key feature of `Heading` is that semantic level and visual size are fully independent. An `h3` can visually appear as large as a page title, and an `h1` can be styled small for compact interfaces, all without breaking document outline order.

import { Heading } from "@glinui/ui"

export function HeadingIndependentDemo() {
  return (
    <div className="space-y-4">
      {/* Visually large, semantically an h3 */}
      <Heading level={3} size="lg">
        Large h3, section title styled like a hero heading
      </Heading>

      {/* Visually small, semantically an h1, e.g., page header in a compact layout */}
      <Heading level={1} size="sm">
        Small h1, compact page title
      </Heading>

      {/* h4 at default md size, standard subsection */}
      <Heading level={4} size="md">
        Default h4 subsection
      </Heading>
    </div>
  )
}

Full Level Range

import { Heading } from "@glinui/ui"

export function HeadingLevelsDemo() {
  return (
    <div className="space-y-1">
      <Heading level={1}>h1, Page title</Heading>
      <Heading level={2}>h2, Section</Heading>
      <Heading level={3}>h3, Subsection</Heading>
      <Heading level={4}>h4, Group</Heading>
      <Heading level={5}>h5, Detail</Heading>
      <Heading level={6}>h6, Caption-level</Heading>
    </div>
  )
}

Display, h2 and h3 sizes

display is fluid (clamp), weight 300, tracking -0.03em with balanced wrapping.

import { Heading } from "@glinui/ui"

export function Demo() {
  return (
    <div className="grid gap-4">
      <Heading level={1} size="display">Identity for every agent</Heading>
      <Heading level={2} size="h2">Section heading</Heading>
      <Heading level={3} size="h3">Subsection</Heading>
    </div>
  )
}

Accessibility

  • Preserves semantic heading hierarchy with configurable level.
  • Always use headings in a logical, non-skipping order (h1 → h2 → h3) to maintain a coherent document outline for screen readers.
  • The `level` prop controls the rendered HTML tag, never override this with CSS `display` tricks that break semantics.
  • Decoupling `level` from `size` lets you meet visual design requirements without compromising heading hierarchy.
  • Avoid using multiple `level={1}` headings on a single page; pages should have exactly one `<h1>`.

Reduced Motion

No motion-dependent behavior.

`Heading` is a static text primitive with no animation. No reduced-motion considerations apply.

API Reference

PropTypeRequiredDefaultDescription
levelHeadingLevelNo2Semantic heading tag level.
variant"default" | "glass" | "outline" | "ghost"NodefaultSurface treatment.
size"sm" | "md" | "lg" | "display" | "h2" | "h3"NomdTypographic scale independent of level.

Source

Import directly from the package or browse the source on GitHub. Click any file to view it.

Import

import { Heading } from "@glinui/ui"

Source Files

Dependencies

@glinui/ui

Generated API Snapshot

Beta

Auto-extracted from TypeScript source in packages/ui/src/components/heading.tsx. This section is in beta and may lag behind hand-curated docs. Regenerate with pnpm --filter @glinui/docs api:generate.

Generated: 2026-10-08T01:41:21.546Z · Full index: /docs/api-metadata

Primary Props Type

HeadingProps

HeadingProps

PropTypeRequiredDefaultDescription
levelHeadingLevelNo2-
size"sm" | "md" | "lg" | "display" | "h2" | "h3"No"md"Variant option from headingVariants.
variant"default" | "glass" | "outline" | "ghost"No"default"Variant option from headingVariants.