FairGarden Design

Section Header

Opens every band or module in a fixed order: what kind of thing this is (the eyebrow), what it says (the heading), why it matters (the lede) and where to go next ("See all").

import { SectionHeader } from '@fairgarden-private/design/components/SectionHeader'

A band header is an h2 in the section-head color; level="module" makes it an h3 item head in the text color. Pass headingId to name the band with aria-labelledby. The eyebrow is never the only heading and never takes the accent color. Pick the eyebrow rule or the trail, never both.

Kinds

Kinds

editorial (default) sets the eyebrow over its hairline: 14 px from the eyebrow to the rule, 19 px from the rule to the heading. A band that opens this way needs no page-seam hairline above it. trailed threads a display-serif kicker with the dashed trail and centres the heading below it. scene centres heading, lede and pill. anchored sits a sticker drawing on the heading. technical sets a mono section number and a caps label over a rule. topic puts a topic tag above the heading. Children form the action row.

Field guide

Birds of the tallgrass prairie

Forty species nest in the grass itself; here is how to find them.

Keep exploring

More from the trail

Every acre counts

Join the neighbors who keep this land open for good.

Our kitchen garden

03Specifications

Dimensions and weight

Conservation

Protecting working land

SectionHeaderKinds.tsx
import { Button } from '@fairgarden-private/design/components/Button'
import { Ground } from '@fairgarden-private/design/components/Ground'
import { SectionHeader } from '@fairgarden-private/design/components/SectionHeader'
import { Tag } from '@fairgarden-private/design/components/Tag'
import { Sticker } from '../sticker'
import styles from './kinds.module.css'

/** The six openers on one paper band. */
export function SectionHeaderKinds() {
  return (
    <Ground kind="band" preset="paper" className={styles.band}>
      <div className={styles.container}>
        <SectionHeader
          eyebrow="Field guide"
          heading="Birds of the tallgrass prairie"
          lede="Forty species nest in the grass itself; here is how to find them."
        />
        <SectionHeader kind="trailed" kicker="Keep exploring" heading="More from the trail" />
        <SectionHeader
          kind="scene"
          heading="Every acre counts"
          lede="Join the neighbors who keep this land open for good."
        >
          <Button variant="solid" size="lg">
            Donate Now
          </Button>
        </SectionHeader>
        <SectionHeader kind="anchored" art={<Sticker />} heading="Our kitchen garden">
          <Button>See the Menu</Button>
        </SectionHeader>
        <SectionHeader
          kind="technical"
          number="03"
          eyebrow="Specifications"
          heading="Dimensions and weight"
          level="module"
        />
        <SectionHeader kind="topic" topic={<Tag>Conservation</Tag>} heading="Protecting working land" />
      </div>
    </Ground>
  )
}

On grounds

On grounds

On a page ground the section head takes the ground's own hue at step 12 and the trail its accent. On the night band every text resolves to the light ink. "See all" is underlined at rest; on hover its label takes the link hover ink and its arrow the next weight. It sits below the lede at base and at the end of the heading row from 1024 px.

Stories

Rivers coming back

Three watersheds, ten years of work, and what the water says now.

See all stories

Next

Visit a preserve near you

See all preserves

Stay in touch

The field notes letter

On the night band every text takes the light ink; the trail and underlines stay green.

See all
SectionHeaderGrounds.tsx
import { Ground } from '@fairgarden-private/design/components/Ground'
import { SectionDivider } from '@fairgarden-private/design/components/SectionDivider'
import { SectionHeader } from '@fairgarden-private/design/components/SectionHeader'
import styles from './grounds.module.css'

/** The editorial header on tide, the trail kicker on paper, and a header in the night footer. */
export function SectionHeaderGrounds() {
  return (
    <div className={styles.page}>
      <Ground kind="band" preset="tide" className={styles.band} aria-labelledby="grounds-tide">
        <div className={styles.container}>
          <SectionHeader
            eyebrow="Stories"
            heading="Rivers coming back"
            headingId="grounds-tide"
            lede="Three watersheds, ten years of work, and what the water says now."
            seeAll={{ href: '#grounds', label: 'See all stories' }}
          />
        </div>
      </Ground>
      <Ground kind="band" preset="paper" className={styles.band}>
        <SectionDivider kind="page-seam" />
        <div className={styles.container}>
          <SectionHeader
            kind="trailed"
            kicker="Next"
            heading="Visit a preserve near you"
            seeAll={{ href: '#grounds', label: 'See all preserves' }}
          />
        </div>
      </Ground>
      <Ground kind="band" preset="night" render={<footer />} className={styles.band}>
        <div className={styles.container}>
          <SectionHeader
            eyebrow="Stay in touch"
            heading="The field notes letter"
            lede="On the night band every text takes the light ink; the trail and underlines stay green."
            seeAll={{ href: '#grounds' }}
          />
        </div>
      </Ground>
    </div>
  )
}

API Reference

The opener of a band or module. Keep the order eyebrow → heading → lede → action; pick the eyebrow rule or the trail, never both; left-align over reading content and centre only scene openers. On the night band and in fields every text resolves to --primary12; the eyebrow is never the accent. Prints with its rules, never at the foot of a page.

PropTypeDescription
art
React.ReactNode | undefined
eyebrow
React.ReactNode | undefined

What kind of thing this is: type-eyebrow caps in --primary12, over its hairline.

heading
React.ReactNode

The heading text: what the band or module says. Required: an eyebrow is never the only heading.

headingId
string | undefined

The heading’s id, for the band’s aria-labelledby.

kicker
React.ReactNode | undefined
kind
| 'editorial'
| 'trailed'
| 'scene'
| 'anchored'
| 'technical'
| 'topic'
| undefined

editorial (default): eyebrow, hairline, content (Audubon). With an eyebrow the header opens with its rule, so the band needs no page-seam hairline above it [D179].

lede
React.ReactNode | undefined

Why it matters: type-lead in --primary12, capped at --ds-measure-reading.

level
'band' | 'module' | null | undefined

band (default): an h2 in type-h2, the section head in --role-heading. module: an h3 in type-itemhead in --primary12 (an item head, not a section head [D60]).

number
React.ReactNode | undefined
primary
| 'ruby'
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'crimson'
| 'tomato'
| 'pink'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple'
| null
| undefined

Primary Radix scale: the eyebrow, lede, module heading and rules. Never defaulted; omitted, it inherits the band or field [D133].

secondary
| 'ruby'
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'crimson'
| 'tomato'
| 'pink'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple'
| 'amber'
| 'blue'
| 'cyan'
| 'grass'
| 'green'
| 'jade'
| 'lime'
| 'mint'
| 'orange'
| 'sky'
| 'teal'
| 'yellow'
| null
| undefined

Secondary Radix scale: the band heading and kicker (--role-heading), the trail and the “See all” underline (--role-accent) and its hover ink. Never defaulted.

seeAll
SectionHeaderSeeAll | undefined

Where to go next: below the lede at base, at the heading row’s end from --lg-n-above.

topic
React.ReactNode | undefined
children
React.ReactNode | undefined

The action row: the scene opener’s pill, or the anchored opener’s action.

sectionHeader
SectionHeaderKind

The six §11.8 builds.

type SectionHeaderKind = 'editorial' | 'trailed' | 'scene' | 'anchored' | 'technical' | 'topic'<
  'editorial' | 'trailed' | 'scene' | 'anchored' | 'technical' | 'topic' | null | undefined
>
SectionHeaderProps

Props for SectionHeader: div props, render, the kind with its parts, the level and the color axes.

type SectionHeaderProps = (
  | {
      kind?: 'editorial';
      eyebrow?: React.ReactNode;
      kicker?: undefined;
      art?: undefined;
      number?: undefined;
      topic?: undefined;
    }
  | {
      kind: 'trailed';
      kicker: React.ReactNode;
      eyebrow?: undefined;
      art?: undefined;
      number?: undefined;
      topic?: undefined;
    }
  | {
      kind: 'scene';
      eyebrow?: undefined;
      kicker?: undefined;
      art?: undefined;
      number?: undefined;
      topic?: undefined;
    }
  | {
      kind: 'anchored';
      art: React.ReactNode;
      eyebrow?: undefined;
      kicker?: undefined;
      number?: undefined;
      topic?: undefined;
    }
  | {
      kind: 'technical';
      number: React.ReactNode;
      eyebrow: React.ReactNode;
      kicker?: undefined;
      art?: undefined;
      topic?: undefined;
    }
  | {
      kind: 'topic';
      topic: React.ReactNode;
      eyebrow?: undefined;
      kicker?: undefined;
      art?: undefined;
      number?: undefined;
    }
) & {
  /**
   * `band` (default): an `h2` in `type-h2`, the section head in
   * `--role-heading`. `module`: an `h3` in `type-itemhead` in `--primary12`
   * (an item head, not a section head [D60]).
   */
  level?: 'band' | 'module' | null;
  /**
   * Primary Radix scale: the eyebrow, lede, module heading and rules. Never
   * defaulted; omitted, it inherits the band or field [D133].
   */
  primary?:
    | 'ruby'
    | 'olive'
    | 'sage'
    | 'slate'
    | 'sand'
    | 'gray'
    | 'mauve'
    | 'brown'
    | 'bronze'
    | 'gold'
    | 'red'
    | 'crimson'
    | 'tomato'
    | 'pink'
    | 'plum'
    | 'indigo'
    | 'iris'
    | 'violet'
    | 'purple'
    | null;
  /**
   * Secondary Radix scale: the band heading and kicker (`--role-heading`),
   * the trail and the "See all" underline (`--role-accent`) and its hover
   * ink. Never defaulted.
   */
  secondary?:
    | 'ruby'
    | 'olive'
    | 'sage'
    | 'slate'
    | 'sand'
    | 'gray'
    | 'mauve'
    | 'brown'
    | 'bronze'
    | 'gold'
    | 'red'
    | 'crimson'
    | 'tomato'
    | 'pink'
    | 'plum'
    | 'indigo'
    | 'iris'
    | 'violet'
    | 'purple'
    | 'amber'
    | 'blue'
    | 'cyan'
    | 'grass'
    | 'green'
    | 'jade'
    | 'lime'
    | 'mint'
    | 'orange'
    | 'sky'
    | 'teal'
    | 'yellow'
    | null;
  /** The heading text: what the band or module says. Required: an eyebrow is never the only heading. */
  heading: React.ReactNode;
  /** The heading's `id`, for the band's `aria-labelledby`. */
  headingId?: string;
  /** Why it matters: `type-lead` in `--primary12`, capped at `--ds-measure-reading`. */
  lede?: React.ReactNode;
  /** Where to go next: below the lede at base, at the heading row's end from `--lg-n-above`. */
  seeAll?: SectionHeaderSeeAll;
  /** The action row: the scene opener's pill, or the anchored opener's action. */
  children?: React.ReactNode;
}
SectionHeaderSeeAll

The “See all” link: a standalone link in type-label caps with a trailing arrow.

type SectionHeaderSeeAll = {
  /** The destination; a short absolute URL also prints after the label (§7.6). */
  href: string;
  /** Authored in sentence case; the CSS sets the caps. Default "See all". */
  label?: React.ReactNode;
  /** Base UI `render`, e.g. `<NextLink href="/trails" />`. */
  render?: ReactElement;
}

Specification: DESIGN-SYSTEM.md §11.8 (section header and eyebrow), §3.5 (the chapter stack) and §4.7.1 (the trail ornament).