Skip to content
Scrim UI

Context Files UI

The files currently in the model's context — sizes, how many tokens each one costs, and removal without leaving the chat.

filecontextpaneltokens

Preview

In context3 files · 14% of context
  • auth/token.ts≈ 1.2k tokens
  • auth/refresh.ts≈ 840 tokens
  • design-tokens.json48 KB

Presets

Props

18000
128000

Also takes onRemove.

Agent promptClaude Code · Cursor · any agent
Add the Context Files UI component from the Scrim UI registry to this project and use it in the configuration described below.

Context Files UI — The files currently in the model's context — sizes, how many tokens each one costs, and removal without leaving the chat.

## 1. Install

```bash
npx shadcn@latest add @scrimui/context-files
```

This writes a single file to `components/ui/context-files.tsx`. It is plain React + Tailwind with no runtime dependencies — no Radix, no CVA, nothing to add to package.json. If this project does not use the shadcn CLI, copy the source from https://scrimui.dev/components/context-files to the same path by hand; nothing in the file depends on shadcn.

## 2. Use it

```tsx
import { ContextFiles } from "@/components/ui/context-files";

const FILES = [
  { name: "auth/token.ts", detail: "≈ 1.2k tokens" },
  { name: "auth/refresh.ts", detail: "≈ 840 tokens" },
  { name: "design-tokens.json", detail: "48 KB" },
];

<ContextFiles
  title="In context"
  used={18000}
  limit={128000}
  files={FILES}
  usage={{ used: 18000, limit: 128000 }}
  onRemove={() => {}}
/>
```

## 3. The configuration that matters

This is the component's "Default" state — Files in context with per-file size and a remove affordance.

Every prop is at its default value. Keep the call site minimal — do not write out default values.

## 4. Wire the handlers

`onRemove` is a stub in the snippet above (`() => {}`). Connect it to this project's own state and data layer instead of shipping the empty function.

Reference: https://scrimui.dev/components/context-files

Follows the props below — change a control and the prompt changes with it, so an agent reproduces that configuration instead of the defaults.

Install

npx shadcn@latest add @scrimui/context-files

Component source

React + Tailwind component using shadcn/ui (button). The install command adds these dependencies automatically.

When copying source manually, install the required primitives first:

npx shadcn@latest add button
context-files.tsx
"use client";

import { Button } from "@/components/ui/button";
import * as React from "react";

/* ------------------------------------------------------------------ */
/* Types                                                               */
/* ------------------------------------------------------------------ */

export type ContextFile = {
  name: string;
  /** Human size or token detail, e.g. "48 KB" or "≈ 1.2k tokens". */
  detail?: string;
};

export type ContextFilesProps = {
  files: ContextFile[];
  /** Token usage against the context window — renders a progress bar when provided. */
  usage?: { used: number; limit: number };
  onRemove?: (name: string) => void;
  title?: string;
  className?: string;
};

/* ------------------------------------------------------------------ */
/* Helpers                                                             */
/* ------------------------------------------------------------------ */

function FileIcon() {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" width="15" height="15">
      <path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" />
      <path d="M14 2v4a2 2 0 0 0 2 2h4" />
    </svg>
  );
}

function XIcon() {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" width="12" height="12">
      <path d="M18 6 6 18" />
      <path d="m6 6 12 12" />
    </svg>
  );
}

/* ------------------------------------------------------------------ */
/* ContextFiles                                                        */
/* ------------------------------------------------------------------ */

export function ContextFiles({
  files,
  usage,
  onRemove,
  title = "Files in context",
  className = "",
}: ContextFilesProps) {
  const used = usage ? Math.min(usage.used / usage.limit, 1) : 0;
  const pct = usage ? Math.round(used * 100) : 0;

  return (
    <div className={`overflow-hidden rounded-xl border border-border ${className}`}>
      <div className="flex items-center justify-between bg-muted px-3 py-2">
        <span className="text-sm font-medium text-foreground">{title}</span>
        <span className="text-xs text-muted-foreground">
          {files.length} {files.length === 1 ? "file" : "files"}
          {usage && ` · ${pct}% of context`}
        </span>
      </div>

      {files.length === 0 ? (
        <div className="px-3 py-4 text-center text-xs text-muted-foreground">
          No files in context yet — attach files and they’ll appear here.
        </div>
      ) : (
        <ul className="divide-y divide-border">
          {files.map((file) => (
            <li key={file.name} className="flex items-center gap-2.5 px-3 py-2">
              <span className="shrink-0 text-muted-foreground">
                <FileIcon />
              </span>
              <span className="min-w-0 flex-1 truncate text-sm text-foreground">
                {file.name}
              </span>
              {file.detail && (
                <span className="shrink-0 text-xs text-muted-foreground">
                  {file.detail}
                </span>
              )}
              {onRemove && (
                <Button variant="ghost" size="icon-sm"
                  type="button"
                  onClick={() => onRemove(file.name)}
                  aria-label={`Remove ${file.name}`}
                  className="min-h-6 min-w-6 shrink-0 rounded p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
                >
                  <XIcon />
                </Button>
              )}
            </li>
          ))}
        </ul>
      )}

      {usage && (
        <div className="px-3 pb-2.5">
          <div className="h-1 overflow-hidden rounded-full bg-muted">
            <div
              className={`h-full rounded-full ${pct > 85 ? "bg-red-500" : pct > 60 ? "bg-amber-500" : "bg-emerald-500"}`}
              style={{ width: `${pct}%` }}
            />
          </div>
        </div>
      )}
    </div>
  );
}

When to use it

  • Make context visible: users behave differently when they can see exactly which files the model is reading.
  • Show token pressure with a colored bar — red only past ~85% so it means something.
  • Let users remove files inline; an un-editable context list feels like the model is hiding its inputs.
  • Truncate long names with an ellipsis and put the size on its own, non-wrapping column.

What breaks in production

  • Hiding which files were used after the fact — the user can't audit or correct a hallucination they can't trace.
  • Listing internal files the user never chose; context should reflect what the user supplied or approved.
  • Showing a token bar in a color that doesn't communicate urgency (a green bar at 95% is a lie).

Related Components