108 lines
3.3 KiB
TypeScript
108 lines
3.3 KiB
TypeScript
import { Link } from "@/i18n/navigation";
|
|
import { getTranslations } from "next-intl/server";
|
|
import { Mail, Rss, SquareArrowOutUpRight } from "lucide-react";
|
|
import { siteConfig } from "@/lib/site-config";
|
|
|
|
/**
|
|
* 社交链接图标。
|
|
*
|
|
* 注意:lucide-react v1.x 已移除品牌图标(Github / Twitter 等),
|
|
* 因此这里使用通用图标,由 `label` 文本承载具体含义——
|
|
* 图标仅作装饰(aria-hidden),可访问性不依赖它。
|
|
*/
|
|
const SOCIAL_ICONS = {
|
|
github: SquareArrowOutUpRight,
|
|
twitter: Rss,
|
|
mail: Mail,
|
|
} as const;
|
|
|
|
/**
|
|
* 站点页脚。
|
|
*
|
|
* DESIGN.md 的 footer-region:白底上一道 hairline 顶边,多列分组,
|
|
* 分栏标题用 body-sm-medium 深色,链接用 body-sm 灰色。
|
|
*/
|
|
export async function SiteFooter() {
|
|
const t = await getTranslations("Footer");
|
|
const tNav = await getTranslations("Nav");
|
|
const year = new Date().getFullYear();
|
|
|
|
return (
|
|
<footer className="border-t border-hairline bg-canvas">
|
|
<div className="mx-auto w-full max-w-[1280px] px-lg py-section sm:px-xxl">
|
|
<div className="grid grid-cols-1 gap-xxl sm:grid-cols-2 lg:grid-cols-4">
|
|
{/* 品牌列 */}
|
|
<div className="flex flex-col gap-sm lg:col-span-2">
|
|
<div className="flex items-center gap-xs text-body-md font-semibold text-ink">
|
|
<span
|
|
aria-hidden="true"
|
|
className="grid size-7 place-items-center rounded-md bg-primary font-mono text-caption font-semibold text-brand-green"
|
|
>
|
|
>_
|
|
</span>
|
|
{siteConfig.name}
|
|
</div>
|
|
|
|
<p className="max-w-[360px] text-body-sm text-steel">
|
|
{siteConfig.description}
|
|
</p>
|
|
</div>
|
|
|
|
{/* 导航列 */}
|
|
<nav aria-label={t("navigation")} className="flex flex-col gap-xs">
|
|
<h2 className="mb-xs text-body-sm font-medium text-ink">
|
|
{t("navigation")}
|
|
</h2>
|
|
<Link
|
|
href="/"
|
|
className="py-xxs text-body-sm text-steel transition-colors duration-150 hover:text-ink"
|
|
>
|
|
{tNav("home")}
|
|
</Link>
|
|
<Link
|
|
href="/about"
|
|
className="py-xxs text-body-sm text-steel transition-colors duration-150 hover:text-ink"
|
|
>
|
|
{tNav("about")}
|
|
</Link>
|
|
</nav>
|
|
|
|
{/* 社交列 */}
|
|
<div className="flex flex-col gap-xs">
|
|
<h2 className="mb-xs text-body-sm font-medium text-ink">
|
|
{t("elsewhere")}
|
|
</h2>
|
|
|
|
<ul className="flex flex-col gap-xxs">
|
|
{siteConfig.social.map((item) => {
|
|
const Icon = SOCIAL_ICONS[item.icon];
|
|
|
|
return (
|
|
<li key={item.label}>
|
|
<a
|
|
href={item.href}
|
|
target={item.href.startsWith("mailto:") ? undefined : "_blank"}
|
|
rel="noopener noreferrer"
|
|
className="inline-flex items-center gap-xs py-xxs text-body-sm text-steel transition-colors duration-150 hover:text-ink"
|
|
>
|
|
<Icon className="size-4" aria-hidden="true" />
|
|
{item.label}
|
|
</a>
|
|
</li>
|
|
);
|
|
})}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-xxl flex flex-col gap-xs border-t border-hairline-soft pt-lg text-caption text-steel sm:flex-row sm:items-center sm:justify-between">
|
|
<p>
|
|
© {year} {siteConfig.name}. {t("rights")}
|
|
</p>
|
|
<p className="font-mono">{t("builtWith")}</p>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
);
|
|
}
|