2026-09-08 09:20:15 +00:00
|
|
|
|
import Link from "next/link";
|
|
|
|
|
|
import { ArrowRight, ArrowUpRight, CheckIcon } from "@/components/icons";
|
|
|
|
|
|
|
|
|
|
|
|
export function DevPlaceholder({ children = "开发占位" }: { children?: React.ReactNode }) {
|
|
|
|
|
|
return <span className="inline-flex items-center rounded-full border border-warning/30 bg-warning/10 px-2.5 py-1 text-[0.68rem] font-semibold tracking-wide text-warning">{children}</span>;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function SectionHeading({ eyebrow, title, description, tone = "orange" }: { eyebrow: string; title: string; description?: string; tone?: "orange" | "blue" | "cyan" }) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
<div className="max-w-2xl">
|
|
|
|
|
|
<p className={`eyebrow ${tone === "blue" ? "eyebrow-blue" : tone === "cyan" ? "eyebrow-cyan" : ""}`}>{eyebrow}</p>
|
2026-09-08 11:51:22 +00:00
|
|
|
|
<h2 className="text-balance mt-5 text-3xl font-semibold tracking-[-0.04em] text-copy sm:text-5xl">{title}</h2>
|
2026-09-08 09:20:15 +00:00
|
|
|
|
{description ? <p className="body-copy mt-5 max-w-xl text-base">{description}</p> : null}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function ArrowLink({ href, children, external = false }: { href: string; children: React.ReactNode; external?: boolean }) {
|
|
|
|
|
|
return <Link className="inline-flex items-center gap-2 text-sm font-semibold text-cyan transition-colors hover:text-copy" href={href}>{children}{external ? <ArrowUpRight /> : <ArrowRight />}</Link>;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function ProductVisual({ accent = "orange", label = "PRODUCT CONCEPT" }: { accent?: "orange" | "blue"; label?: string }) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
<div aria-label="开发占位产品视觉,不代表真实产品" className="product-visual">
|
|
|
|
|
|
<div className={`absolute left-8 top-8 h-24 w-44 rounded-[2rem] border ${accent === "orange" ? "border-orange/70 shadow-[0_0_60px_rgba(255,106,0,0.14)]" : "border-blue/70 shadow-[0_0_60px_rgba(22,119,255,0.18)]"} bg-ink/80 sm:h-32 sm:w-60`} />
|
|
|
|
|
|
<div className={`absolute left-20 top-20 h-16 w-24 rounded-full border ${accent === "orange" ? "border-orange/60" : "border-blue/60"} bg-panel/80 sm:left-32 sm:top-28 sm:h-20 sm:w-36`} />
|
|
|
|
|
|
<span className="absolute bottom-5 left-6 text-[0.62rem] font-semibold tracking-[0.24em] text-subtle">{label}</span>
|
|
|
|
|
|
<DevPlaceholder />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function PreviewNotice({ children = "当前为 Phase 1 界面预览,真实业务将在后续阶段接入。" }: { children?: React.ReactNode }) {
|
|
|
|
|
|
return <div className="rounded-xl border border-warning/25 bg-warning/8 px-4 py-3 text-sm leading-6 text-warning" role="status"><span className="font-semibold">开发预览:</span>{children}</div>;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-08 16:43:56 +00:00
|
|
|
|
export function StatusCard({ title, description, tone = "neutral", children }: { title: string; description: string; tone?: "neutral" | "info" | "warning" | "success"; children?: React.ReactNode }) {
|
2026-09-08 09:20:15 +00:00
|
|
|
|
const styles = { neutral: "border-line bg-panel", info: "border-blue/25 bg-blue/8", warning: "border-warning/25 bg-warning/8", success: "border-success/25 bg-success/8" };
|
2026-09-08 16:43:56 +00:00
|
|
|
|
return <div className={`rounded-xl border p-4 ${styles[tone]}`}><p className="font-semibold text-copy">{title}</p><p className="mt-2 text-sm leading-6 text-muted">{description}</p>{children}</div>;
|
2026-09-08 09:20:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function FeatureList({ items }: { items: string[] }) {
|
|
|
|
|
|
return <ul className="space-y-3">{items.map((item) => <li className="flex gap-3 text-sm leading-6 text-muted" key={item}><span className="mt-1 text-cyan"><CheckIcon /></span><span>{item}</span></li>)}</ul>;
|
|
|
|
|
|
}
|