/** * 섹션 제목 — 그 자체로 배리에이션을 갖는 원자. * * 섹션 배리에이션을 바꿔도 제목 스타일은 따로 고를 수 있어야 한다 * ("갤러리는 격자로, 제목은 가운데 정렬" 같은 조합이 실제로 나온다). */ import type {ReactNode} from 'react'; import type {TemplateItem} from '@o2o/shared'; import {cn} from '@/lib/utils'; export type HeadingStyle = 'underline' | 'centered' | 'eyebrow' | 'minimal'; interface SectionHeadingProps { title: string; subtitle?: string; /** 제목 위에 얹는 작은 라벨. eyebrow · centered 스타일에서 쓴다. */ eyebrow?: string; variant?: HeadingStyle; /** 제목 오른쪽에 붙는 것(경고 배지, 추가 버튼 등). */ trailing?: ReactNode; /** * 템플릿 색 토큰. 넘기면 제목은 text, eyebrow 는 accent 를 따른다. * * ★ 부제·밑줄은 일부러 중립 회색으로 남긴다 — 여기까지 토큰을 먹이면 * accent 가 밝은 템플릿에서 부제가 배경에 묻힌다. */ colors?: TemplateItem['colors']; className?: string; } export function SectionHeading({ title, subtitle, eyebrow, variant = 'underline', trailing, colors, className, }: SectionHeadingProps) { const titleStyle = colors ? {color: colors.text} : undefined; const eyebrowStyle = colors ? {color: colors.accent} : undefined; if (variant === 'centered') { return (
{eyebrow && ( {eyebrow} )}

{title}

{subtitle &&

{subtitle}

} {trailing &&
{trailing}
}
); } if (variant === 'eyebrow') { return (
{eyebrow && ( {eyebrow} )}

{title}

{subtitle &&

{subtitle}

}
{trailing}
); } if (variant === 'minimal') { // 여기서 제목은 사실상 작은 라벨이라 text 가 아니라 secondary 를 쓴다. return (

{title}

{trailing}
); } // underline — 기본. 아래 실선이 섹션의 시작을 확실히 끊어준다. return (

{title}

{subtitle &&

{subtitle}

}
{trailing &&
{trailing}
}
); }