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

90 lines
2.3 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";
2026-05-24 22:38:26 -05:00
import {
sectionRail,
sectionTone,
toneBadge,
type BadgeTone,
type SectionToneKey,
} from "./tokens";
2026-05-19 23:11:32 -05:00
interface DashboardSectionProps {
title: string;
infoText?: string;
badge?: { text: string; tone: BadgeTone };
action?: { label: string; href: string };
children: ReactNode;
className?: string;
2026-05-24 22:38:26 -05:00
tone?: SectionToneKey;
2026-05-19 23:11:32 -05:00
}
/**
* 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,
2026-05-24 22:38:26 -05:00
tone = "neutral",
2026-05-19 23:11:32 -05:00
}: DashboardSectionProps) {
return (
2026-05-24 22:38:26 -05:00
<section
className={cn(
"relative overflow-hidden rounded-xl border p-4 shadow-lush md:p-6",
sectionTone[tone],
className,
)}
>
<span
className={cn(
"pointer-events-none absolute inset-x-4 top-0 h-px",
sectionRail[tone],
)}
/>
2026-05-19 23:11:32 -05:00
<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 && (
2026-05-24 22:38:26 -05:00
<span
className="inline-flex text-muted"
title={infoText}
aria-label={infoText}
>
2026-05-19 23:11:32 -05:00
<Info className="h-3.5 w-3.5" />
</span>
)}
</div>
<div className="flex items-center gap-2">
{badge && (
2026-05-24 22:38:26 -05:00
<span
className={cn(
"inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-medium",
toneBadge[badge.tone],
)}
>
2026-05-19 23:11:32 -05:00
{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>
);
}