This commit is contained in:
1 parent
c1541b80df
commit
b4c7908029
97 files changed
+12403
-154
No files matched your search
@@ -0,0 +1,111 @@
|
||||
import { Link } from "@/i18n/navigation";
|
||||
import { ArrowRight, Sparkles } from "lucide-react";
|
||||
import { Container } from "@/components/ui/layout";
|
||||
import { buttonClassName } from "@/components/ui/button-variants";
|
||||
|
||||
/**
|
||||
* 首页 Hero 区。
|
||||
*
|
||||
* 对应 DESIGN.md 的 hero-band-sky:大气渐变(天空蓝 → 柔奶油)作为背景,
|
||||
* 居中标题、副标题与按钮行。品牌薄荷绿仅用于单个强调 CTA。
|
||||
*
|
||||
* 这里用 CSS 渐变 + 径向光晕替代插画资源,避免引入额外图片依赖,
|
||||
* 同时保持规范要求的「氛围感渐变」基调。
|
||||
*/
|
||||
export interface HomeHeroProps {
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
subtitle: string;
|
||||
primaryLabel: string;
|
||||
secondaryLabel: string;
|
||||
stats: {
|
||||
posts: number;
|
||||
tags: number;
|
||||
since: string;
|
||||
postsLabel: string;
|
||||
tagsLabel: string;
|
||||
sinceLabel: string;
|
||||
};
|
||||
}
|
||||
|
||||
export function HomeHero({
|
||||
eyebrow,
|
||||
title,
|
||||
subtitle,
|
||||
primaryLabel,
|
||||
secondaryLabel,
|
||||
stats,
|
||||
}: HomeHeroProps) {
|
||||
return (
|
||||
<section
|
||||
aria-labelledby="hero-heading"
|
||||
className="relative overflow-hidden border-b border-hairline-soft"
|
||||
>
|
||||
{/* 氛围渐变背景(装饰性,对辅助技术隐藏) */}
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="pointer-events-none absolute inset-0 -z-10 bg-gradient-to-b from-hero-sky-from via-[#d9dbe0] to-hero-sky-to"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="pointer-events-none absolute inset-0 -z-10 opacity-70 [background:radial-gradient(60%_50%_at_50%_0%,rgba(255,255,255,0.85),transparent_70%)]"
|
||||
/>
|
||||
|
||||
<Container className="flex flex-col items-center py-section text-center sm:py-section-lg lg:py-hero">
|
||||
{/* 大写微标签 */}
|
||||
<p className="inline-flex items-center gap-xs rounded-full border border-white/60 bg-white/70 px-md py-[6px] text-micro-uppercase font-semibold uppercase tracking-[0.5px] text-steel backdrop-blur-sm">
|
||||
<Sparkles className="size-3.5 text-brand-green-deep" aria-hidden="true" />
|
||||
{eyebrow}
|
||||
</p>
|
||||
|
||||
<h1
|
||||
id="hero-heading"
|
||||
className="mt-lg w-full max-w-[880px] text-heading-2 font-semibold text-ink text-balance-pretty sm:text-heading-1 lg:text-hero-display"
|
||||
>
|
||||
{title}
|
||||
</h1>
|
||||
|
||||
<p className="mt-lg w-full max-w-[640px] text-body-md text-slate text-balance-pretty sm:text-subtitle">
|
||||
{subtitle}
|
||||
</p>
|
||||
|
||||
{/* 按钮行:品牌绿强调 CTA + 描边次级按钮 */}
|
||||
<div className="mt-xxl flex flex-col items-center gap-sm sm:flex-row">
|
||||
<Link
|
||||
href="/#posts"
|
||||
className={buttonClassName({ variant: "accent", size: "lg" })}
|
||||
>
|
||||
{primaryLabel}
|
||||
<ArrowRight className="size-4" aria-hidden="true" />
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
href="/about"
|
||||
className={buttonClassName({ variant: "secondary", size: "lg" })}
|
||||
>
|
||||
{secondaryLabel}
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* 站点统计:窄屏下压缩间距,避免三个卡片把布局撑出横向滚动 */}
|
||||
<dl className="mt-section grid w-full min-w-0 max-w-[560px] grid-cols-3 gap-xs sm:mt-hero sm:gap-md">
|
||||
<StatItem value={String(stats.posts)} label={stats.postsLabel} />
|
||||
<StatItem value={String(stats.tags)} label={stats.tagsLabel} />
|
||||
<StatItem value={stats.since} label={stats.sinceLabel} />
|
||||
</dl>
|
||||
</Container>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function StatItem({ value, label }: { value: string; label: string }) {
|
||||
return (
|
||||
<div className="flex min-w-0 flex-col items-center gap-[2px] rounded-lg border border-white/60 bg-white/55 px-xs py-sm backdrop-blur-sm sm:px-md">
|
||||
<dt className="sr-only">{label}</dt>
|
||||
<dd className="font-mono text-heading-5 font-semibold text-ink sm:text-heading-4">
|
||||
{value}
|
||||
</dd>
|
||||
<dd className="text-caption text-steel">{label}</dd>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user