{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"context-files","type":"registry:ui","title":"Context Files","description":"The files currently in the model's context — sizes, how many tokens each one costs, and removal without leaving the chat.","author":"Scrim UI (https://scrimui.dev)","categories":["files"],"docs":"https://scrimui.dev/components/context-files","dependencies":[],"registryDependencies":[],"files":[{"path":"src/showcase/context-files/context-files.tsx","content":"\"use client\";\n\nimport * as React from \"react\";\n\n/* ------------------------------------------------------------------ */\n/* Types                                                               */\n/* ------------------------------------------------------------------ */\n\nexport type ContextFile = {\n  name: string;\n  /** Human size or token detail, e.g. \"48 KB\" or \"≈ 1.2k tokens\". */\n  detail?: string;\n};\n\nexport type ContextFilesProps = {\n  files: ContextFile[];\n  /** Token usage against the context window — renders a progress bar when provided. */\n  usage?: { used: number; limit: number };\n  onRemove?: (name: string) => void;\n  title?: string;\n  className?: string;\n};\n\n/* ------------------------------------------------------------------ */\n/* Helpers                                                             */\n/* ------------------------------------------------------------------ */\n\nfunction FileIcon() {\n  return (\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" width=\"15\" height=\"15\">\n      <path d=\"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\" />\n      <path d=\"M14 2v4a2 2 0 0 0 2 2h4\" />\n    </svg>\n  );\n}\n\nfunction XIcon() {\n  return (\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" width=\"12\" height=\"12\">\n      <path d=\"M18 6 6 18\" />\n      <path d=\"m6 6 12 12\" />\n    </svg>\n  );\n}\n\n/* ------------------------------------------------------------------ */\n/* ContextFiles                                                        */\n/* ------------------------------------------------------------------ */\n\nexport function ContextFiles({\n  files,\n  usage,\n  onRemove,\n  title = \"Files in context\",\n  className = \"\",\n}: ContextFilesProps) {\n  const used = usage ? Math.min(usage.used / usage.limit, 1) : 0;\n  const pct = usage ? Math.round(used * 100) : 0;\n\n  return (\n    <div className={`overflow-hidden rounded-xl border border-zinc-200 dark:border-zinc-800 ${className}`}>\n      <div className=\"flex items-center justify-between bg-zinc-50 px-3 py-2 dark:bg-zinc-800/60\">\n        <span className=\"text-[13px] font-medium text-zinc-700 dark:text-zinc-200\">{title}</span>\n        <span className=\"text-xs text-zinc-500 dark:text-zinc-400\">\n          {files.length} {files.length === 1 ? \"file\" : \"files\"}\n          {usage && ` · ${pct}% of context`}\n        </span>\n      </div>\n\n      {files.length === 0 ? (\n        <div className=\"px-3 py-4 text-center text-xs text-zinc-500 dark:text-zinc-400\">\n          No files in context yet — attach files and they’ll appear here.\n        </div>\n      ) : (\n        <ul className=\"divide-y divide-zinc-100 dark:divide-zinc-800/60\">\n          {files.map((file) => (\n            <li key={file.name} className=\"flex items-center gap-2.5 px-3 py-2\">\n              <span className=\"shrink-0 text-zinc-400 dark:text-zinc-500\">\n                <FileIcon />\n              </span>\n              <span className=\"min-w-0 flex-1 truncate text-[13px] text-zinc-700 dark:text-zinc-200\">\n                {file.name}\n              </span>\n              {file.detail && (\n                <span className=\"shrink-0 text-[11px] text-zinc-500 dark:text-zinc-400\">\n                  {file.detail}\n                </span>\n              )}\n              {onRemove && (\n                <button\n                  type=\"button\"\n                  onClick={() => onRemove(file.name)}\n                  aria-label={`Remove ${file.name}`}\n                  className=\"shrink-0 rounded p-1 text-zinc-400 transition-colors hover:bg-zinc-100 hover:text-zinc-700 dark:text-zinc-500 dark:hover:bg-zinc-800 dark:hover:text-zinc-200\"\n                >\n                  <XIcon />\n                </button>\n              )}\n            </li>\n          ))}\n        </ul>\n      )}\n\n      {usage && (\n        <div className=\"px-3 pb-2.5\">\n          <div className=\"h-1 overflow-hidden rounded-full bg-zinc-100 dark:bg-zinc-800\">\n            <div\n              className={`h-full rounded-full ${pct > 85 ? \"bg-red-500\" : pct > 60 ? \"bg-amber-500\" : \"bg-emerald-500\"}`}\n              style={{ width: `${pct}%` }}\n            />\n          </div>\n        </div>\n      )}\n    </div>\n  );\n}\n","type":"registry:ui","target":"components/ui/context-files.tsx"}]}