Skip to content
Caseroom

Components · Layout

Section header

The head of a page section: a kicker in words, the heading, a line or two and an optional action.

71% of the 2,062 sites in The UI Index have a header (1,458 sites).

Changelog

What shipped this month

Twelve releases, two new components and a faster build.

Pricing

One plan per team size

Start free and pay when the second person joins.

Both previews render the same markup; the HTML tab below is that markup without a framework.

Install

React
npx shadcn@latest add https://www.themes.dev/caseroom/r/section-header.json
Astro
npx shadcn@latest add https://www.themes.dev/caseroom/r/astro/section-header.json

Or copy the files below into your project. They need clsx, tailwind-merge, and the Caseroom theme. The HTML needs only the compiled CSS.

section-header.tsx
import type { ReactNode } from 'react';
import { cn } from '@/lib/utils';
import { sectionHeader as c, type SectionHeaderContent } from './section-header.variants';

export type SectionHeaderProps = SectionHeaderContent & { className?: string; children?: ReactNode };

/** The head of a page section: kicker, heading, a line or two, and an optional action. */
export function SectionHeader({ title, kicker, description, align = 'start', id, as: Heading = 'h2', className, children }: SectionHeaderProps) {
  return (
    <header className={cn(c.root, className)}>
      <div className={align === 'center' ? c.center : c.start}>
        <div>
          {kicker && <p className={c.kicker}>{kicker}</p>}
          <Heading id={id} className={c.title}>{title}</Heading>
          {description && <p className={cn(c.description, align === 'center' && 'mx-auto')}>{description}</p>}
        </div>
        {children && <div className={c.action}>{children}</div>}
      </div>
    </header>
  );
}
section-header.variants.ts
/** The head of a page section (a "section header" in The UI Index): an optional kicker in words (never a number), the
 *  heading, one or two lines, and an optional action at the end. start: on the page's left edge, the action beside
 *  the text from a wide container. center: centred, the text kept to two lines' measure. */
export const sectionHeader = {
  root: '@container w-full',
  start: 'flex flex-col gap-4 @2xl:flex-row @2xl:items-end @2xl:justify-between',
  center: 'mx-auto flex max-w-2xl flex-col items-center gap-4 text-center',
  kicker: 'text-sm font-medium text-muted-foreground',
  title: 'mt-2 text-3xl font-semibold tracking-[-0.03em] text-balance @2xl:text-4xl',
  description: 'mt-3 max-w-xl text-base text-pretty text-muted-foreground',
  action: 'shrink-0',
};
export type SectionHeaderContent = { title: string; kicker?: string; description?: string; align?: 'start' | 'center'; id?: string; as?: 'h2' | 'h3' };