{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "side-panel", "type": "registry:component", "title": "Side panel", "description": "Record detail beside the table, never a navigation: scrimless, the amount is the hero, arrow-key row stepping.", "registryDependencies": [ "@venlyfinance/venly-tokens", "@venlyfinance/money" ], "files": [ { "path": "registry/components/side-panel.tsx", "type": "registry:component", "target": "~/components/venly/components/side-panel.tsx", "content": "import type { CSSProperties, ReactElement, ReactNode } from \"react\";\nimport { Money } from \"../lib/money.js\";\n\n/**\n * Side panel – record detail beside the table, not instead of it.\n *\n * Design contract encoded by this component:\n * - Clicking a row opens this panel; it never navigates.\n * - NO scrim: the table stays visible and clipped at the panel edge; the\n * source row stays tinted (the table owns that via selectedKey).\n * - Width ~27–30% of the viewport for a record.\n * - Header: thin micro-size grey context line + close control, then the\n * HERO IS THE AMOUNT (~28px), not the counterparty, then a grey\n * qualifier line.\n * - The panel edge is an overlay boundary, so it is the one base-layer\n * element allowed a shadow.\n * - Footer strip with `↑ ↓ Esc` key chips so a reviewer steps row to row\n * without closing the panel.\n */\nexport interface SidePanelProps {\n /** Thin grey context line, e.g. \"Transfer · 7 Aug 2026\". */\n context: string;\n amount?: number | null;\n /** Rendered before the hero amount, e.g. an explicit \"+\" on settled credits. */\n amountPrefix?: string;\n currency?: string;\n /** Grey line under the hero amount, e.g. the counterparty. */\n qualifier?: ReactNode;\n onClose?: () => void;\n /** Render the ↑ ↓ Esc footer strip. Default true. */\n keyboardFooter?: boolean;\n children?: ReactNode;\n style?: CSSProperties;\n className?: string;\n}\n\nfunction KeyChip({ label }: { label: string }): ReactElement {\n return (\n \n {label}\n \n );\n}\n\nexport function SidePanel({\n context,\n amount,\n amountPrefix,\n currency,\n qualifier,\n onClose,\n keyboardFooter = true,\n children,\n style,\n className,\n}: SidePanelProps): ReactElement {\n return (\n \n
\n \n {context}\n {onClose ? (\n \n ✕\n \n ) : null}\n \n
\n {amountPrefix ? (\n \n {amountPrefix}\n \n ) : null}\n \n
\n {qualifier !== undefined ? (\n \n {qualifier}\n \n ) : null}\n
\n
{children}
\n {keyboardFooter ? (\n \n \n row\n \n close\n \n ) : null}\n \n );\n}\n" } ] }