spb/spboucher.ai Public
spboucher.ai — personal website of Simon-Pierre Boucher.
TypeScript 93.4%
HTML 5.5%
CSS 1%
1/*2 section-heading.tsx3 spboucher.ai Web4 Author: Simon-Pierre Boucher5 Mail: contact@spboucher.ai6*/78import type { LucideIcon } from "lucide-react";910import { IconTile } from "@/components/icon-tile";11import { cn } from "@/lib/utils";1213interface SectionHeadingProps {14 eyebrow?: string;15 title: string;16 description?: string;17 icon?: LucideIcon;18 as?: "h1" | "h2" | "h3";19 className?: string;20}2122/** Unified section header: rounded icon tile, eyebrow, title, description. */23export function SectionHeading({24 eyebrow,25 title,26 description,27 icon,28 as: Tag = "h2",29 className,30}: SectionHeadingProps) {31 const isPageTitle = Tag === "h1";32 return (33 <div className={cn("flex items-start gap-4", className)}>34 {icon && <IconTile icon={icon} size={isPageTitle ? "lg" : "md"} />}35 <div className="min-w-0 flex-1">36 {eyebrow && (37 <p className="flex items-center gap-3 font-mono text-[0.68rem] font-medium uppercase tracking-[0.22em] text-primary">38 <span39 aria-hidden="true"40 className="h-px w-6 shrink-0 bg-primary/60"41 />42 {eyebrow}43 </p>44 )}45 <Tag46 className={cn(47 "font-display tracking-tight",48 isPageTitle49 ? "mt-2 text-4xl font-semibold sm:text-5xl"50 : "mt-1 text-2xl font-semibold",51 !eyebrow && "mt-0",52 )}53 >54 {title}55 </Tag>56 {description && (57 <p className="mt-2.5 max-w-3xl text-sm leading-relaxed text-muted-foreground">58 {description}59 </p>60 )}61 </div>62 </div>63 );64}65