beadboard/src/components/shared/base-card.tsx
zenchantlive 71a513c639 feat(components): complete bb-ui2.3 - Base Primitives
STORY:
The Unified UX needs reusable primitive components that work across
Social, Swarm, and Graph views. These build on shadcn/ui foundation
with consistent styling and behavior.

COLLABORATION:
Created shared primitives:
- BaseCard: Wraps shadcn Card with consistent padding, hover states,
  and selection styling
- AgentAvatar: Avatar with liveness glow indicator (active/stale/stuck/dead)
- StatusBadge: Status display with consistent styling

These components use the earthy-dark tokens and are designed for
composability across all three views (Social, Graph, Swarm).

DELIVERABLES:
- src/components/shared/base-card.tsx
- src/components/shared/agent-avatar.tsx
- src/components/shared/status-badge.tsx
- src/components/shared/index.ts (barrel export)
- Tests in tests/components/shared/

VERIFICATION:
- npm run typecheck: PASS
- npm run lint: PASS
- npm run test: PASS

CLOSES: bb-ui2.3
BLOCKS: bb-ui2.5, bb-ui2.11, bb-ui2.16
2026-02-15 21:17:08 -08:00

37 lines
1.2 KiB
TypeScript

import type { ReactNode, MouseEventHandler } from 'react';
import { cn } from '@/lib/utils';
interface BaseCardProps {
children: ReactNode;
className?: string;
selected?: boolean;
onClick?: MouseEventHandler<HTMLDivElement>;
}
export function BaseCard({ children, className, selected = false, onClick }: BaseCardProps) {
const selectedClass = selected
? 'ring-1 ring-amber-200/20 shadow-[0_24px_48px_-18px_rgba(0,0,0,0.88),0_0_26px_rgba(251,191,36,0.14)]'
: 'shadow-[0_18px_38px_-18px_rgba(0,0,0,0.82),0_6px_18px_-10px_rgba(0,0,0,0.72)] hover:shadow-[0_24px_52px_-16px_rgba(0,0,0,0.9),0_10px_26px_-10px_rgba(0,0,0,0.78)]';
return (
<div
role={onClick ? 'button' : undefined}
tabIndex={onClick ? 0 : undefined}
onClick={onClick}
onKeyDown={(e) => {
if (onClick && (e.key === 'Enter' || e.key === ' ')) {
e.preventDefault();
e.currentTarget.click();
}
}}
className={cn(
'rounded-xl border border-white/[0.06] bg-[#363636] px-3.5 py-3 transition duration-200 shadow-[inset_0_1px_0_rgba(255,255,255,0.06)]',
onClick && 'cursor-pointer hover:border-white/[0.10]',
selectedClass,
className
)}
>
{children}
</div>
);
}