# Section header (Caseroom component)

The head of a page section: a kicker in words, the heading, a line or two and an optional action. Black and white, dark mode, shadcn-compatible; React, Astro and plain HTML.

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

## 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`
- HTML: https://www.themes.dev/caseroom/r/html/section-header.html (with https://www.themes.dev/caseroom/r/html/caseroom.css)

Page: https://www.themes.dev/caseroom/components/section-header/ · Rules for agents: https://www.themes.dev/caseroom/AGENT.md

## Code

### section-header.astro

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

type Props = SectionHeaderContent & { class?: string };
const { title, kicker, description, align = 'start', id, as: Heading = 'h2', class: className } = Astro.props;
---

<header class={cn(c.root, className)}>
  <div class={align === 'center' ? c.center : c.start}>
    <div>
      {kicker && <p class={c.kicker}>{kicker}</p>}
      <Heading id={id} class={c.title}>{title}</Heading>
      {description && <p class={cn(c.description, align === 'center' && 'mx-auto')}>{description}</p>}
    </div>
    {Astro.slots.has('default') && <div class={c.action}><slot /></div>}
  </div>
</header>
```

### section-header.tsx

```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

```tsx
/** 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' };
```
