SPB Git

spb/spboucher.ai Public

spboucher.ai — personal website of Simon-Pierre Boucher.

TypeScript 93.4% HTML 5.5% CSS 1%
1.6 KB · 65 lines tsx
Raw Blame History
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