o2o-negosium-original/landing/app/components/ui/typography.tsx

59 lines
2.3 KiB
TypeScript

import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
// 랜딩 텍스트 스케일 단일 소스. 페이지마다 text-[44px]/font-black/…을 직접 박지 말고
// variant 로 통일한다. 색·크기 미세조정은 className 으로 합성.
const typographyVariants = cva("", {
variants: {
variant: {
// 히어로 h1
display: "text-3xl sm:text-4xl md:text-[50px] font-black tracking-tight leading-[1.2] text-ink break-keep",
// 섹션 제목 h2
title: "text-3xl md:text-[44px] font-black tracking-tight leading-tight text-ink break-keep",
// 섹션 내 서브 제목 (데모 패널 등)
heading: "text-2xl md:text-3xl font-bold tracking-tight text-ink break-keep",
// 카드 제목
cardTitle: "text-lg font-bold text-ink break-keep",
// 섹션 상단 오버라인 라벨
eyebrow: "text-sm font-semibold text-primary tracking-wider uppercase",
// 섹션 리드 문단
lead: "text-base sm:text-lg text-ink-soft font-medium leading-relaxed break-keep",
body: "text-[15px] text-ink-soft font-medium leading-relaxed break-keep",
small: "text-sm text-ink-soft font-medium leading-relaxed break-keep",
caption: "text-xs text-ink-muted font-semibold leading-relaxed break-keep",
// 11px 트래킹 대문자 메타 라벨 (단가 패널·푸터 컬럼 제목 등)
micro: "text-[11px] font-bold text-ink-muted uppercase tracking-wider",
},
},
defaultVariants: { variant: "body" },
})
const defaultTag: Record<NonNullable<VariantProps<typeof typographyVariants>["variant"]>, React.ElementType> = {
display: "h1",
title: "h2",
heading: "h3",
cardTitle: "h3",
eyebrow: "span",
lead: "p",
body: "p",
small: "p",
caption: "p",
micro: "span",
}
type TypographyProps = React.HTMLAttributes<HTMLElement> &
VariantProps<typeof typographyVariants> & {
/** 의미상 태그를 강제로 바꾸고 싶을 때 (예: cardTitle 을 h4 로) */
as?: React.ElementType
htmlFor?: string
}
function Typography({ className, variant, as, ...props }: TypographyProps) {
const Comp = as ?? defaultTag[variant ?? "body"]
return <Comp className={cn(typographyVariants({ variant }), className)} {...props} />
}
export { Typography, typographyVariants }