spb/countryatlas
Public
TypeScript 57%
Python 38.6%
JavaScript 3.6%
CSS 0.6%
1import Link from 'next/link';2import type { ReactNode } from 'react';3import { cn } from '@/lib/cn';45/** Editorial page header: optional breadcrumb + eyebrow, display title, lede, right-side actions. */6export function PageHeader({7 title,8 lede,9 eyebrow,10 crumbs,11 actions,12 meta,13 className,14}: {15 title: ReactNode;16 lede?: ReactNode;17 eyebrow?: ReactNode;18 crumbs?: Array<{ href: string; label: ReactNode }>;19 actions?: ReactNode;20 meta?: ReactNode;21 className?: string;22}) {23 return (24 <header className={cn('pb-4 pt-6 md:pt-10', className)}>25 {crumbs?.length ? (26 <nav aria-label="Breadcrumb" className="text-xs text-ink-3">27 {crumbs.map((c, i) => (28 <span key={c.href}>29 {i > 0 ? <span className="mx-1.5">/</span> : null}30 <Link href={c.href} className="-my-3 inline-flex min-h-[44px] items-center hover:text-accent md:my-0 md:min-h-0">31 {c.label}32 </Link>33 </span>34 ))}35 </nav>36 ) : null}37 <div className="flex flex-wrap items-end justify-between gap-x-8 gap-y-3">38 <div className="min-w-0 max-w-3xl">39 {eyebrow ? <div className="eyebrow mb-1">{eyebrow}</div> : null}40 <h1 className="display text-3xl leading-tight text-ink md:text-4xl">{title}</h1>41 {lede ? <p className="mt-2 max-w-prose text-sm text-ink-2 md:text-base">{lede}</p> : null}42 {meta ? <div className="tnum mt-1 text-xs text-ink-3">{meta}</div> : null}43 </div>44 {actions ? <div className="flex flex-wrap items-center gap-2 text-sm">{actions}</div> : null}45 </div>46 </header>47 );48}4950/** Quiet secondary action link/button look shared by the explore pages. */51export const ACTION_CLS = 'inline-flex min-h-[44px] items-center gap-1.5 rounded-sm border border-rule px-3 text-sm text-ink hover:bg-surface-2 md:min-h-[36px]';52export const PRIMARY_ACTION_CLS = 'inline-flex min-h-[44px] items-center gap-1.5 rounded-sm bg-ink px-3 text-sm font-medium text-paper hover:bg-accent hover:text-accent-ink md:min-h-[36px]';53