learning_ai_common_plat/packages/ui/src/components/EntityCard.tsx

64 lines
1.9 KiB
TypeScript

import * as React from 'react';
import { clsx } from 'clsx';
export interface EntityCardProps extends Omit<React.HTMLAttributes<HTMLElement>, 'title'> {
title: React.ReactNode;
subtitle?: React.ReactNode;
eyebrow?: React.ReactNode;
status?: React.ReactNode;
metadata?: React.ReactNode;
actions?: React.ReactNode;
footer?: React.ReactNode;
selected?: boolean;
}
export function EntityCard({
title,
subtitle,
eyebrow,
status,
metadata,
actions,
footer,
selected,
className,
children,
...props
}: EntityCardProps) {
return (
<article
className={clsx(
'grid gap-4 rounded-xl border bg-[var(--bl-surface-card)] p-5 shadow-sm shadow-black/[0.03]',
selected
? 'border-[var(--bl-accent)] ring-2 ring-[var(--bl-focus-ring-muted)]'
: 'border-[var(--bl-border)]',
className
)}
{...props}
>
<div className="flex min-w-0 items-start justify-between gap-3">
<div className="min-w-0">
{eyebrow && (
<div className="mb-1 text-xs font-semibold uppercase tracking-[0.08em] text-[var(--bl-text-secondary)]">
{eyebrow}
</div>
)}
<div className="flex min-w-0 flex-wrap items-center gap-2">
<h3 className="m-0 min-w-0 text-base font-semibold leading-6 text-[var(--bl-text-primary)]">
{title}
</h3>
{status}
</div>
{subtitle && (
<p className="mt-1 text-sm leading-6 text-[var(--bl-text-secondary)]">{subtitle}</p>
)}
</div>
{actions && <div className="flex shrink-0 items-center gap-2">{actions}</div>}
</div>
{metadata && <div className="flex min-w-0 flex-wrap gap-2">{metadata}</div>}
{children}
{footer && <div className="border-t border-[var(--bl-border)] pt-3">{footer}</div>}
</article>
);
}