{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "card", "type": "registry:ui", "title": "TAC Card", "description": "Card primitive at zero-radius with semantic tokens. For Paper Ops Console card usage prefer OpsCard (composed/ops-console/ops-card.tsx) which adds the corner-tick + accent variants.", "files": [ { "path": "src/components/primitives/card.tsx", "type": "registry:ui", "content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@workspace/ui/lib/utils\"\n\n/**\n * Card — Violet Grid v6 primitive.\n *\n * v6 changes:\n * - Surface tier variants: `default` (elevated), `outline` (legacy),\n * `surface` (explicit elevated), `floating` (popover-tier),\n * `interactive` (interactive-tier + tac-hover-lift).\n * - Container query at root (`@container/card`) so children can write\n * `@sm:grid-cols-2`, `@lg:grid-cols-4` etc — adapts to the card's\n * own width, not the viewport.\n * - Optional `inner-border` modifier via the `microContrast` prop:\n * adds a 1px overlay-fg-soft inset ring for depth without shadow.\n *\n * See `docs/VIOLET-GRID-V6-EVOLUTION.md` § 2.2.\n */\nconst cardVariants = cva(\n // v6: @container/card lets descendants use @sm/@lg etc. against the card width\n \"group/card @container/card flex flex-col gap-4 overflow-hidden py-4 text-xs/relaxed text-card-foreground ring-1 ring-foreground/10 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-2 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-[var(--radius-lg)] *:[img:last-child]:rounded-[var(--radius-lg)]\",\n {\n variants: {\n variant: {\n default: \"bg-card rounded-[var(--radius-lg)]\",\n outline: \"bg-card border border-border rounded-[var(--radius-xl)]\",\n // v6: explicit surface tiers\n surface: \"bg-surface-elevated border border-border rounded-[var(--radius-lg)]\",\n floating: \"bg-surface-floating border border-border ring-1 ring-fg-soft shadow-[var(--shadow-brutal-sm)] rounded-[var(--radius-lg)]\",\n interactive: \"bg-surface-interactive border border-border tac-hover-lift cursor-pointer rounded-[var(--radius-lg)]\",\n },\n microContrast: {\n true: \"ring-1 ring-fg-soft\",\n false: \"\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n microContrast: false,\n },\n }\n)\n\ninterface CardProps extends React.ComponentProps<\"div\">, VariantProps {\n size?: \"default\" | \"sm\"\n}\n\nfunction Card({\n className,\n size = \"default\",\n variant,\n microContrast,\n role,\n tabIndex,\n onKeyDown,\n onClick,\n ...props\n}: CardProps) {\n // v6: when the `interactive` variant is used and the consumer wires an onClick,\n // promote the div to a focusable, keyboard-activatable button-equivalent so\n // keyboard and AT users get parity with mouse users. Consumers can still\n // override role/tabIndex explicitly.\n const isInteractive = variant === \"interactive\"\n const resolvedRole = role ?? (isInteractive && onClick ? \"button\" : undefined)\n const resolvedTabIndex =\n tabIndex ?? (isInteractive && onClick ? 0 : undefined)\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (isInteractive && onClick && (event.key === \"Enter\" || event.key === \" \")) {\n event.preventDefault()\n onClick(event as unknown as React.MouseEvent)\n }\n onKeyDown?.(event)\n }\n\n return (\n \n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n cardVariants,\n}\n" } ] }