Pipeline/frontend/src/components/dashboard/DashboardSection.tsx

61 lines
1.8 KiB
TypeScript
Raw Normal View History

2026-05-19 23:11:32 -05:00
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>
);
}