{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "code-accordion", "title": "Code Accordion", "description": "A code window that springs a range of lines closed and replaces them with a \"N lines collapsed\" placeholder.", "dependencies": [ "remotion" ], "files": [ { "path": "registry/remocn/code-accordion/index.tsx", "content": "\"use client\";\n\nimport { interpolate, spring, useCurrentFrame, useVideoConfig } from \"remotion\";\n\nexport interface CodeAccordionProps {\n lines?: string[];\n collapseRange?: [number, number];\n collapseAt?: number;\n title?: string;\n fontSize?: number;\n width?: number;\n background?: string;\n cardColor?: string;\n textColor?: string;\n mutedColor?: string;\n speed?: number;\n className?: string;\n}\n\nconst FONT_MONO =\n \"var(--font-geist-mono), ui-monospace, SFMono-Regular, monospace\";\n\nconst DEFAULT_LINES = [\n \"export function processOrders(orders) {\",\n \" const valid = [];\",\n \" for (const order of orders) {\",\n \" if (!order.id) continue;\",\n \" if (!order.customer) continue;\",\n \" if (!order.items?.length) continue;\",\n \" if (order.total <= 0) continue;\",\n \" if (order.status === 'cancelled') continue;\",\n \" if (order.status === 'refunded') continue;\",\n \" const enriched = enrich(order);\",\n \" const validated = validate(enriched);\",\n \" if (!validated.ok) continue;\",\n \" const priced = price(validated.value);\",\n \" const taxed = applyTax(priced);\",\n \" const shipped = applyShipping(taxed);\",\n \" valid.push(shipped);\",\n \" }\",\n \" return valid;\",\n \"}\",\n];\n\nexport function CodeAccordion({\n lines = DEFAULT_LINES,\n collapseRange = [3, 14],\n collapseAt = 30,\n title = \"process-orders.ts\",\n fontSize = 16,\n width = 720,\n background = \"#050505\",\n cardColor = \"#0a0a0a\",\n textColor = \"#e4e4e7\",\n mutedColor = \"#52525b\",\n speed = 1,\n className,\n}: CodeAccordionProps) {\n const frame = useCurrentFrame() * speed;\n const { fps } = useVideoConfig();\n\n const lineHeight = Math.round(fontSize * 1.55);\n const [start, end] = collapseRange;\n const collapsedCount = Math.max(0, end - start + 1);\n\n // Spring drives BOTH the inner collapse height AND a tiny y-bounce on the\n // window so the accordion feels like it has weight.\n const collapseProgress = spring({\n frame: frame - collapseAt,\n fps,\n config: { damping: 10, stiffness: 110, mass: 1 },\n });\n\n const collapsedHeight = interpolate(\n collapseProgress,\n [0, 1],\n [collapsedCount * lineHeight, lineHeight], // collapses down to the placeholder bar's height\n );\n\n const collapsedOpacity = interpolate(collapseProgress, [0, 0.6], [1, 0], {\n extrapolateLeft: \"clamp\",\n extrapolateRight: \"clamp\",\n });\n\n const placeholderOpacity = interpolate(collapseProgress, [0.4, 1], [0, 1], {\n extrapolateLeft: \"clamp\",\n extrapolateRight: \"clamp\",\n });\n\n const before = lines.slice(0, start);\n const collapsed = lines.slice(start, end + 1);\n const after = lines.slice(end + 1);\n\n return (\n