VisorVisor
ComponentsTypography

Heading

A semantic heading component (h1–h6) with independent size and weight variants. Decouples visual presentation from semantic level.

Levels

Each level renders the corresponding HTML heading element (<h1> through <h6>) with an auto-mapped visual size.

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5
Heading 6

Size Override

The size prop lets you decouple visual size from semantic level — an <h3> can look like an <h1>.

h3 that looks like h1

h1 that looks like h5

Weights

Normal Weight

Medium Weight

Semibold Weight

Bold Weight

Installation

npx visor add heading

This copies two files into your project:

  • components/ui/heading/heading.tsx — the component
  • components/ui/heading/heading.module.css — the styles

Usage

import { Heading } from '@/components/ui/heading/heading';

export default function Example() {
  return <Heading level={1}>Page Title</Heading>;
}

API Reference

HeadingProps

PropTypeDefaultDescription
level1 | 2 | 3 | 4 | 5 | 62Semantic heading level, controls which HTML element is rendered (h1–h6).
size'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'Visual size override. Auto-mapped from level if not set.
weight'normal' | 'medium' | 'semibold' | 'bold''semibold'Font weight of the heading.
classNamestringAdditional CSS class names to merge onto the element.

The component also accepts all standard HTML heading attributes.

Accessibility

  • Always use headings in a logical hierarchy — don't skip levels (e.g. h1h3). Use the size prop to adjust visual appearance without changing the semantic level.
  • Every page should have exactly one <h1>. Use level={1} for the main page title only.
  • Screen readers navigate by heading structure. Meaningful, descriptive heading text improves navigation for keyboard and AT users.
  • Avoid using Heading purely for visual styling — use Text instead if semantics don't apply.

Em accent

Editorial headings often accent one phrase with brand color — rendered as non-italic, colored text via <em>. This is a recurring pattern across Visor consumers and has a Visor-sanctioned answer: one theme-level rule, applied once.

The pattern: Add this rule to your theme or global stylesheet:

em {
  color: var(--text-link);
  font-style: normal;
}

Then use bare <em> in any heading (or body text):

<Heading level={1}>Build faster <em>with Visor</em></Heading>

Why --text-link: It's the most universally available accent token — all Visor themes define it, it passes contrast against typical heading backgrounds, and it maps intuitively to "highlighted" text. You can swap it for any token that fits your theme:

TokenWhen to use
--text-linkDefault recommendation — themed link/accent color
--accentBare intent alias; resolves to your theme's accent hue
--primaryBare intent alias; resolves to your theme's primary hue

Scope the rule to headings if needed: If font-style: normal on all <em> would conflict with your body copy, scope it:

h1 em, h2 em, h3 em, h4 em, h5 em, h6 em {
  color: var(--text-link);
  font-style: normal;
}

This rule is intentionally not built into @loworbitstudio/visor-core — it's an opt-in convention. Visor doesn't reset <em> globally; you apply it once in the stylesheet that owns your theme.

Customization

After copying the component, you own it completely. Common customizations:

// Add a gradient or custom color
<Heading level={1} style={{ background: 'linear-gradient(...)', WebkitBackgroundClip: 'text' }}>
  Gradient Title
</Heading>

// Combine with a custom class for one-off styles
<Heading level={2} className="my-section-title">Section</Heading>