61 lines
1.8 KiB
TypeScript
61 lines
1.8 KiB
TypeScript
|
|
import type { ReactNode } from "react";
|
||
|
|
import Link from "next/link";
|
||
|
|
import { ArrowUpRight, Info } from "lucide-react";
|
||
|
|
import { cn } from "@/lib/utils";
|
||
|
|
import { toneBadge, type BadgeTone } from "./tokens";
|
||
|
|
|
||
|
|
interface DashboardSectionProps {
|
||
|
|
title: string;
|
||
|
|
infoText?: string;
|
||
|
|
badge?: { text: string; tone: BadgeTone };
|
||
|
|
action?: { label: string; href: string };
|
||
|
|
children: ReactNode;
|
||
|
|
className?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Standard dashboard card section.
|
||
|
|
* Uses .surface-card so all color values come from design tokens —
|
||
|
|
* no hardcoded palette classes.
|
||
|
|
*/
|
||
|
|
export function DashboardSection({
|
||
|
|
title,
|
||
|
|
infoText,
|
||
|
|
badge,
|
||
|
|
action,
|
||
|
|
children,
|
||
|
|
className,
|
||
|
|
}: DashboardSectionProps) {
|
||
|
|
return (
|
||
|
|
<section className={cn("surface-card rounded-xl p-4 md:p-6", className)}>
|
||
|
|
<div className="mb-4 flex items-center justify-between gap-3">
|
||
|
|
<div className="flex items-center gap-1.5">
|
||
|
|
<h3 className="text-lg font-semibold text-strong">{title}</h3>
|
||
|
|
{infoText && (
|
||
|
|
<span className="inline-flex text-muted" title={infoText} aria-label={infoText}>
|
||
|
|
<Info className="h-3.5 w-3.5" />
|
||
|
|
</span>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
<div className="flex items-center gap-2">
|
||
|
|
{badge && (
|
||
|
|
<span className={cn("inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-medium", toneBadge[badge.tone])}>
|
||
|
|
{badge.text}
|
||
|
|
</span>
|
||
|
|
)}
|
||
|
|
{action && (
|
||
|
|
<Link
|
||
|
|
href={action.href}
|
||
|
|
className="inline-flex items-center gap-1 text-xs text-muted transition hover:text-strong"
|
||
|
|
>
|
||
|
|
{action.label}
|
||
|
|
<ArrowUpRight className="h-3.5 w-3.5" />
|
||
|
|
</Link>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
{children}
|
||
|
|
</section>
|
||
|
|
);
|
||
|
|
}
|