www_site/components/ui.tsx

45 lines
3.2 KiB
TypeScript
Raw Normal View History

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>
<h2 className="text-balance mt-5 text-3xl font-semibold tracking-[-0.04em] text-copy sm:text-5xl">{title}</h2>
{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>;
}
export function StatusCard({ title, description, tone = "neutral" }: { title: string; description: string; tone?: "neutral" | "info" | "warning" | "success" }) {
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" };
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></div>;
}
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>;
}