Docs
Systhema Design (opens in new tab)
Unreleased

Heading

Heading.h1 to Heading.h6 with token text styles.

On this page

Heading renders a real <h1> to <h6> element with the matching token text style and the heading color. Use it for every title on a page, so the document outline and the visual hierarchy come from the same place.

Heading

Design tokens, shipped as code

One set of tokens drives the type scale, so every heading level stays in step with your Figma file.

import { Heading, Paragraph } from '@systhemaui/next'

export default function Demo() {
  return (
    <div className="max-w-xl">
      <Heading.h2>Design tokens, shipped as code</Heading.h2>
      <Paragraph type="lead" className="mt-4">
        One set of tokens drives the type scale, so every heading level stays in step with your
        Figma file.
      </Paragraph>
    </div>
  )
}

ImportLink to this section

import { Heading } from '@systhemaui/next'

In a React app without Next.js, import it from @systhemaui/react. The API is the same.

Variants and tagsLink to this section

Each level has a shorthand: Heading.h1, Heading.h2, Heading.h3, Heading.h4, Heading.h5 and Heading.h6. Every shorthand renders that element with the text-h1 to text-h6 text style and the color-heading color. The sizes below come from the default tokens.

Heading levels

Heading level 1

Heading level 2

Heading level 3

Heading level 4

Heading level 5
Heading level 6
import { Heading } from '@systhemaui/next'

export default function Demo() {
  return (
    <div className="flex flex-col gap-3">
      <Heading.h1>Heading level 1</Heading.h1>
      <Heading.h2>Heading level 2</Heading.h2>
      <Heading.h3>Heading level 3</Heading.h3>
      <Heading.h4>Heading level 4</Heading.h4>
      <Heading.h5>Heading level 5</Heading.h5>
      <Heading.h6>Heading level 6</Heading.h6>
    </div>
  )
}

The base component takes the level as the tag prop instead. tag defaults to 'h1', so a bare <Heading> is a page title.

ExamplesLink to this section

Level from dataLink to this section

Use tag when the level is not known until render time, for example when a CMS field or a parent component decides it. The text style follows the tag.

Level from data

Getting started

Install the packages

Run the first sync

import { Heading, type HeadingProps } from '@systhemaui/next'

const sections: { title: string; level: NonNullable<HeadingProps['tag']> }[] = [
  { title: 'Getting started', level: 'h3' },
  { title: 'Install the packages', level: 'h4' },
  { title: 'Run the first sync', level: 'h4' },
]

export default function Demo() {
  return (
    <div className="flex flex-col gap-3">
      {sections.map((section) => (
        <Heading key={section.title} tag={section.level}>
          {section.title}
        </Heading>
      ))}
    </div>
  )
}

Eyebrow and supporting textLink to this section

A label paragraph above the heading and a lead paragraph below it is the most common title block in the templates.

Title block

Release 1.7

Publish each locale on its own schedule

Per-locale publishing keeps a translation in draft while the original goes live.

import { Heading, Paragraph } from '@systhemaui/next'

export default function Demo() {
  return (
    <div className="flex max-w-xl flex-col gap-3">
      <Paragraph type="label">Release 1.7</Paragraph>
      <Heading.h2>Publish each locale on its own schedule</Heading.h2>
      <Paragraph type="lead">
        Per-locale publishing keeps a translation in draft while the original goes live.
      </Paragraph>
    </div>
  )
}

Scroll revealLink to this section

Heading adds the animationClasses from your Systhema config (for example aos animate-fadeinup), so it fades in when it scrolls into view. Pass disableAnimation to render it without them, for instance above the fold or inside a component that animates as a whole.

import { Heading } from '@systhemaui/next'

export function PageTitle() {
  return <Heading.h1 disableAnimation>Pricing</Heading.h1>
}

PropsLink to this section

Heading and its shorthands also take every attribute of a heading element (id, className, aria-*) and forward a ref to it. The shorthands accept the same props without tag.

PropTypeDefaultDescription
tagHeadingTag-
classNamestring-
disableAnimationboolean-
…and all <h1> attributes

HTML and CSSLink to this section

Without React, write the element with the text style and color classes. Each level has its own text-h* class, and color-heading takes the heading color from the active color system:

<h2 class="text-h2 color-heading">Design tokens, shipped as code</h2>
<h3 class="text-h3 color-heading">Install the packages</h3>

The text-h1 to text-h6 classes set the font family, size, weight, letter spacing and line height from the typography and font tokens. The full class list is on Typography.

Next.jsLink to this section

@systhemaui/next re-exports Heading from @systhemaui/react unchanged. It is a server-compatible component.

AccessibilityLink to this section

  • Pick the level from the document outline, not from the size you want: one h1 per page, and no skipped levels. The page templates, hero titles and Lexical headings all render real <Heading.hN> elements, so the outline holds across CMS content.
  • To make a heading look smaller than its level, add a smaller text style (<Heading.h2 className="text-h4">) instead of changing the tag. The text-h* classes are emitted from h1 to h6, so a smaller style overrides a larger one, but not the other way round.

See Headings in the accessibility overview.