65 lines
2.0 KiB
TypeScript
65 lines
2.0 KiB
TypeScript
import { Card, CardContent, CardHeader } from "@repo/shadcn-ui/components/card";
|
|
import type { ReactNode } from "react";
|
|
import { useId } from "react";
|
|
|
|
/** Panel de consulta con jerarquía común; datos, textos y acciones pertenecen al consumidor. */
|
|
export function DetailPanel({
|
|
title,
|
|
description,
|
|
icon,
|
|
count,
|
|
actions,
|
|
children,
|
|
density = "default",
|
|
}: {
|
|
title: string;
|
|
description?: string;
|
|
icon: ReactNode;
|
|
count?: number | undefined;
|
|
actions?: ReactNode;
|
|
children: ReactNode;
|
|
density?: "default" | "compact";
|
|
}) {
|
|
const id = useId();
|
|
|
|
return (
|
|
<section aria-labelledby={id} className="min-w-0">
|
|
<Card
|
|
className={`@container min-w-0 shadow-none ${density === "compact" ? "gap-3 rounded-lg py-4" : ""}`}
|
|
>
|
|
<CardHeader
|
|
className={`flex flex-wrap items-start justify-between gap-3 ${density === "compact" ? "px-4" : ""}`}
|
|
>
|
|
<div className="min-w-0 space-y-1">
|
|
<h2
|
|
className="flex min-w-0 flex-wrap items-center gap-2 text-base font-semibold"
|
|
id={id}
|
|
>
|
|
<span aria-hidden="true" className="text-primary [&_svg]:size-5">
|
|
{icon}
|
|
</span>
|
|
{title}
|
|
{count !== undefined && (
|
|
<span className="rounded-md bg-muted px-2 py-0.5 text-xs font-medium tabular-nums text-muted-foreground">
|
|
{count}
|
|
</span>
|
|
)}
|
|
</h2>
|
|
{description && (
|
|
<p className="max-w-prose text-sm leading-relaxed text-muted-foreground">
|
|
{description}
|
|
</p>
|
|
)}
|
|
</div>
|
|
{actions && <div className="flex shrink-0 flex-wrap gap-2">{actions}</div>}
|
|
</CardHeader>
|
|
<CardContent
|
|
className={density === "compact" ? "flex min-w-0 flex-col gap-3 px-4" : "space-y-5"}
|
|
>
|
|
{children}
|
|
</CardContent>
|
|
</Card>
|
|
</section>
|
|
);
|
|
}
|