Hero
Three-column editorial hero with a 44px spine, a full-width copy column, and a 380px table-of-contents sidebar. Includes a scrolling ticker strip and collapses to a single column on mobile.
<Hero content={defaultHero} />import Link from 'next/link'
import { Button } from '@/components/ui/Button'
import type { HeroContent } from '@/types'
interface HeroProps {
content: HeroContent
}
const TICKER_ITEMS = [
'Next.js 15', 'TypeScript', 'Tailwind v4', 'Editorial Design', 'Cormorant Garamond',
'App Router', 'Server Components', 'Zod Validation', 'Auth Pages', 'Design Tokens',
]
export function Hero({ content }: HeroProps): React.JSX.Element {
const tickerText = [...TICKER_ITEMS, ...TICKER_ITEMS]
return (
<section className="hero-outer">
{/* Ticker strip */}
<div className="hero-ticker-wrap">
<div className="hero-ticker-inner" aria-hidden="true">
{tickerText.map((item, i) => (
<span key={`${item}-${i}`} className="hero-ticker-text">
{item}
<span className="hero-ticker-sep">·</span>
</span>
))}
</div>
</div>
{/* 3-col grid: spine | copy | TOC */}
<div className="hero-grid">
{/* Magazine spine */}
<div className="hero-spine" aria-hidden="true">
<span className="hero-spine-text">{content.spineText}</span>
</div>
{/* Main copy column */}
<div className="hero-main">
<div className="hero-badge">
<span className="hero-badge-rule" />
{content.badge}
</div>
<h1 className="hero-title">
<span>{content.titleLine1}</span>
<span className="hero-title-line2">{content.titleLine2}</span>
</h1>
<span className="hero-title-div">{content.titleDivider}</span>
<p className="hero-sub">{content.subtitle}</p>
<div className="hero-actions">
<Button variant="primary" size="lg" href={content.ctaHref}>
{content.ctaLabel}
</Button>
<Button variant="secondary" size="lg" href={content.secondaryCtaHref}>
{content.secondaryCtaLabel}
</Button>
</div>
{/* Stats row */}
<div className="hero-stats">
{content.stats.map((stat) => (
<div key={stat.id} className="hero-stat">
<span className="hero-stat-val">{stat.value}</span>
<span className="hero-stat-lbl">{stat.label}</span>
</div>
))}
</div>
</div>
{/* TOC panel */}
<aside className="hero-toc">
<div className="hero-toc-label">Contents</div>
<ul className="hero-toc-list" role="list">
{content.toc.map((item) => (
<li key={item.num}>
<Link href={item.href} className="hero-toc-item">
<span className="hero-toc-item-num">{item.num}</span>
<span className="hero-toc-item-label">{item.label}</span>
<span className="hero-toc-item-arrow" aria-hidden="true">→</span>
</Link>
</li>
))}
</ul>
<div className="hero-toc-footer">
<span className="hero-toc-ver">{content.tocVersion}</span>
<div className="hero-stack">
{content.stackItems.map((item) => (
<span key={item.id} className="hero-stack-item">
{item.label}
</span>
))}
</div>
</div>
</aside>
</div>
</section>
)
}
Button
Multi-variant button with primary, secondary, and ghost styles in three sizes. Renders as a Next.js Link when an href is provided.
Badge
Inline label badge with five variants: ink, accent, cta, ghost, and parchment. Suited for tags, status labels, and category markers.
Card
Composable card container with sharp zero-radius corners in the FOLIO aesthetic. Pairs with folio-card-header, folio-card-body, and folio-card-footer CSS classes.
Calendar
Interactive month-view calendar with previous/next navigation and day selection. Highlights today in forest green and the selected day in cognac.
DateBlock
Magazine-style date display that renders month, day number, and weekday name in an editorial dateline layout. Server component.
Pullquote
Editorial blockquote with ruled top and bottom borders and an optional attribution citation. Suited for testimonials and highlighted copy.
Text
Polymorphic text primitive with body, caption, label, and code variants. Renders as any inline or block HTML tag via the `as` prop.
Features
Ledger-row feature list using a 56px index gutter, feature title, description, and a right-aligned tag. Roman numeral indexes reinforce the editorial aesthetic.
About
Two-column about section with forest green background, a pullquote, and body copy. Pairs a narrative text column with a supporting details column.