Loading...
Loading...
02-reusable-page/footer/footer-minimal.tsx
/**
* Minimal Footer — 미니멀 푸터
*
* 최소 구조: 브랜드+설명 / 링크 그룹 / 저작권.
* 가장 빠르게 적용할 수 있는 경량 푸터.
* 테마 색상은 className으로 자유롭게 커스텀 가능.
*
* @source galaxy-con (260218)
* @extracted 2026-02-18
* @version 1.0.0
*
* @dependencies lucide-react, next/link
*
* @example
* ```tsx
* import { FooterMinimal } from './footer-minimal';
* import { Rocket } from 'lucide-react';
*
* <FooterMinimal
* brand={{
* name: 'Galaxy Con',
* icon: <Rocket className="h-5 w-5" />,
* description: '알고리즘 시각화로 탐험하는 공모전 정보 플랫폼.',
* }}
* linkGroups={[
* { title: '탐색', links: [{ label: '공모전 탐색', href: '/contests' }] },
* { title: '지원', links: [{ label: 'FAQ', href: '/faq' }] },
* ]}
* />
* ```
*/
import Link from 'next/link';
import type { FooterBrandInfo, FooterLinkGroup } from './_shared/types';
import type { MinimalFooterLabels } from './_shared/i18n';
import { DEFAULT_MINIMAL_LABELS } from './_shared/i18n';
// ============================================
// Props
// ============================================
export interface FooterMinimalProps {
/** 브랜드 정보 */
brand: FooterBrandInfo;
/** 링크 그룹 목록 (선택) */
linkGroups?: FooterLinkGroup[];
/** 저작권 텍스트 오버라이드 */
copyrightText?: string;
/** i18n 라벨 */
labels?: MinimalFooterLabels;
/** 추가 className */
className?: string;
}
// ============================================
// 컴포넌트
// ============================================
export function FooterMinimal({
brand,
linkGroups,
copyrightText,
labels = DEFAULT_MINIMAL_LABELS,
className = '',
}: FooterMinimalProps) {
const currentYear = new Date().getFullYear();
const homeHref = brand.homeHref ?? '/';
return (
<footer className={`border-t border-border ${className}`}>
<div className="mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8">
<div
className={`grid grid-cols-2 gap-8 ${
linkGroups && linkGroups.length > 0
? `md:grid-cols-${Math.min(linkGroups.length + 1, 5)}`
: ''
}`}
>
{/* 브랜드 */}
<div className="col-span-2">
<Link
href={homeHref}
className="flex items-center gap-2 text-lg font-bold"
>
{brand.icon && brand.icon}
{brand.name}
</Link>
{brand.description && (
<p className="mt-3 max-w-xs text-sm text-muted-foreground">
{brand.description}
</p>
)}
</div>
{/* 링크 그룹 */}
{linkGroups?.map((group) => (
<div key={group.title}>
<h3 className="mb-3 text-sm font-semibold">{group.title}</h3>
<ul className="space-y-2">
{group.links.map((link) => (
<li key={link.href}>
<Link
href={link.href}
className="text-sm text-muted-foreground transition-colors hover:text-foreground"
{...(link.external
? { target: '_blank', rel: 'noopener noreferrer' }
: {})}
>
{link.label}
</Link>
</li>
))}
</ul>
</div>
))}
</div>
{/* 저작권 */}
<div className="mt-8 border-t border-border pt-6 text-center text-xs text-muted-foreground">
{copyrightText ??
`© ${currentYear} ${brand.name}. ${labels.allRightsReserved}`}
</div>
</div>
</footer>
);
}