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,073 sites in The UI Index have a header (1,473 sites).
Used in UI Pro: Features, FAQ, Call to action, Content, Split, Logo wall, Stats, Media, Testimonials, Posts, Changelog, Gallery, Team, Services, Steps section, Work, Integrations, Feature tabs, Timeline, Values, Careers, Comparison
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.
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/ ui/ r/ section-header.json - Astro
- npx shadcn@
latest add https:// www.themes.dev/ ui/ r/ astro/ section-header.json
Or copy the files below into your project. They need clsx, tailwind-merge, and the themes.dev UI theme. The HTML needs only the compiled CSS.
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>
);
}/** 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' };---
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>/** 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' };<div class="grid w-full max-w-4xl gap-14">
<header class="@container w-full">
<div class="flex flex-col gap-4 @2xl:flex-row @2xl:items-end @2xl:justify-between">
<div>
<p class="text-sm font-medium text-muted-foreground">Changelog</p>
<h2 class="mt-2 text-3xl font-semibold tracking-[-0.03em] text-balance @2xl:text-4xl">What shipped this month</h2>
<p class="mt-3 max-w-xl text-base text-pretty text-muted-foreground">Twelve releases, two new components and a faster build.</p>
</div>
<div class="shrink-0">
<a href="#" class="inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,background-color,border-color,transform] select-none active:scale-[0.97] aria-busy:cursor-progress disabled:pointer-events-none disabled:opacity-50 aria-busy:disabled:opacity-80 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border border-input bg-background hover:bg-accent hover:text-accent-foreground active:bg-pressed h-9 px-4">
All releases
</a>
</div>
</div>
</header>
<header class="@container w-full">
<div class="mx-auto flex max-w-2xl flex-col items-center gap-4 text-center">
<div>
<p class="text-sm font-medium text-muted-foreground">Pricing</p>
<h2 class="mt-2 text-3xl font-semibold tracking-[-0.03em] text-balance @2xl:text-4xl">One plan per team size</h2>
<p class="mt-3 max-w-xl text-base text-pretty text-muted-foreground mx-auto">Start free and pay when the second person joins.</p>
</div>
</div>
</header>
</div>