Files
CollegeAIcenter/web/src/components/feature-grid.tsx
T

74 lines
3.4 KiB
TypeScript

"use client";
import Link from "next/link";
import { ArrowRight, ArrowUpRight } from "lucide-react";
import type { NavGroup, NavItem } from "@/lib/navigation";
const GROUP_THEME: Record<string, { gradient: string; accent: string; label: string }> = {
core: { gradient: "from-primary/12 to-primary/4", accent: "bg-primary/10 text-primary group-hover:bg-primary group-hover:text-primary-foreground", label: "data" },
practice: { gradient: "from-success/12 to-success/4", accent: "bg-success/10 text-success group-hover:bg-success group-hover:text-success-foreground", label: "practice" },
advance: { gradient: "from-chart-4/12 to-chart-4/4", accent: "bg-chart-4/10 text-chart-4 group-hover:bg-chart-4 group-hover:text-white", label: "advance" },
insight: { gradient: "from-chart-3/12 to-chart-3/4", accent: "bg-chart-3/10 text-chart-3 group-hover:bg-chart-3 group-hover:text-white", label: "insight" },
};
function FeatureCard({ item, groupKey }: { item: NavItem; groupKey: string }) {
const Icon = item.icon;
const theme = GROUP_THEME[groupKey] ?? GROUP_THEME.core;
return (
<Link
href={item.href}
className="group relative flex h-full flex-col gap-3 overflow-hidden rounded-2xl bg-card p-5 shadow-sm ring-1 ring-foreground/[0.06] transition-all duration-300 hover:-translate-y-1 hover:shadow-xl hover:ring-primary/30"
>
<div className={`pointer-events-none absolute inset-0 bg-gradient-to-br ${theme.gradient} opacity-0 transition-opacity duration-300 group-hover:opacity-100`} />
<div className="relative flex items-center justify-between">
<span className={`flex size-11 items-center justify-center rounded-xl transition-colors duration-300 ${theme.accent}`}>
<Icon className="size-5" />
</span>
<ArrowUpRight className="size-4 text-muted-foreground/40 transition-all duration-300 group-hover:translate-x-0.5 group-hover:-translate-y-0.5 group-hover:text-primary" />
</div>
<div className="relative">
<h3 className="text-base font-semibold text-foreground">{item.label}</h3>
<p className="mt-1.5 text-sm leading-relaxed text-muted-foreground">
{item.desc}
</p>
</div>
</Link>
);
}
export function FeatureGrid({ items }: { items: NavItem[] }) {
const features = items.filter((i) => i.desc);
return (
<div className="stagger grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
{features.map((f) => (
<FeatureCard key={f.href} item={f} groupKey={f.group ?? "core"} />
))}
</div>
);
}
export function GroupedFeatureGrid({ groups }: { groups: NavGroup[] }) {
return (
<div className="space-y-8">
{groups.map((g) => (
<section key={g.key} className="animate-fade-in-up">
<div className="mb-4 flex items-center gap-2">
<div className="h-5 w-1 rounded-full bg-primary" />
<h2 className="text-sm font-bold tracking-wide text-foreground">{g.label}</h2>
<span className="text-xs text-muted-foreground">({g.items.length})</span>
<ArrowRight className="ml-auto size-3.5 text-muted-foreground/50" />
</div>
<div className="stagger grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
{g.items.map((item) => (
<FeatureCard key={item.href} item={item} groupKey={g.key} />
))}
</div>
</section>
))}
</div>
);
}