# File card

Package: @commenda/pathfinder@0.1.0
Page: /docs/components/file-card
Figma: https://www.figma.com/design/dn7BkGYEfIyP0o2zfesfVh/The-System?node-id=291-146

```tsx
import { FileCard } from '@commenda/pathfinder/file-card';

<FileCard
  file={{
    id: 'return',
    filename: 'Q3 2026 sales tax return.pdf',
    sizeBytes: 1_200_000,
    upload: { status: 'uploading', progress: 64 },
  }}
  actionConfig={{ onCancel: cancelUpload }}
/>;
```


## Usage [#usage]

```tsx
import { FileCard } from '@commenda/pathfinder/file-card';

<FileCard
  file={{
    id: 'return',
    filename: 'Q3 2026 sales tax return.pdf',
    sizeBytes: 1_200_000,
    upload: { status: 'uploading', progress: 64 },
  }}
  actionConfig={{ onCancel: cancelUpload }}
/>;
```

Use this card independently in a form or let [File upload](/docs/components/file-upload) compose it. File icons come from the filename extension; unknown extensions use the generic file icon. File sizes use decimal units, so 1,000,000 bytes is 1 MB. Omit `sizeBytes` when it is unknown.

## State and actions [#state-and-actions]

| State     | Data                                         | Available actions         |
| --------- | -------------------------------------------- | ------------------------- |
| Uploading | `{ status: 'uploading', progress?: number }` | Cancel                    |
| Complete  | `{ status: 'complete' }`                     | Preview, Download, Remove |
| Failed    | `{ status: 'failed', message: string }`      | Retry, Remove             |

A finite progress value is clamped to 0–100; omitted or non-finite progress is indeterminate. Only `status: 'complete'` shows Uploaded. Every action is optional and receives the stable file ID. The card never starts a request, opens a URL, or mutates the file. Actions have accessible names that include the original filename.

## Long filenames and errors [#long-filenames-and-errors]

Names truncate with their full text preserved in the title tooltip. Errors wrap and increase card height, keeping Retry and Remove available. Standalone cards leave list-level focus recovery and announcements to their owner; FileUpload supplies those behaviors.

## API reference [#api-reference]

| Prop | Type | Requirement | Behavior |
| --- | --- | --- | --- |
| `file` | `UploadFileItem` | required | Stable `id`, original `filename`, optional `sizeBytes`, and `upload` state |
| `actionConfig` | `FileActionConfig` | optional | `onCancel`, `onRetry`, `onRemove`, `onPreview`, `onDownload`; each receives an ID |
| `disabled` | `boolean` | optional | Disable all provided actions |
| `className` | `string` | optional | Host layout customization |

### file fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | Yes |  |
| `filename` | `string` | Yes |  |
| `sizeBytes` | `number` | No |  |
| `upload` | `UploadState` | Yes |  |

### file.upload fields

Choose one shape; excluded fields cannot be combined.

#### Option 1

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | `"uploading"` | Yes |  |
| `progress` | `number` | No |  |

#### Option 2

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | `"complete"` | Yes |  |

#### Option 3

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | `"failed"` | Yes |  |
| `message` | `string` | Yes |  |

### actionConfig fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `onCancel` | `((id: string) => void)` | No |  |
| `onRetry` | `((id: string) => void)` | No |  |
| `onRemove` | `((id: string) => void)` | No |  |
| `onPreview` | `((id: string) => void)` | No |  |
| `onDownload` | `((id: string) => void)` | No |  |

`UploadFileItem`, `UploadState`, and `FileActionConfig` are exported from both file-upload and file-card subpaths. The upload state is a discriminated union: failed requires an error message, uploading optionally carries progress, and complete carries neither.

## Design rules [#design-rules]

- **FILE-CARD-01:** A 24px type icon, 12px leading inset/gap, 8px trailing inset, 8px radius, and subtle border. Complete/failed rows have a 56px minimum; uploading has a 63px minimum. Error content may grow.
- **FILE-CARD-02:** Actions reflect lifecycle state. Do not interpret progress reaching 100% as server-confirmed success. Hide actions without callbacks.
- **FILE-CARD-03:** Never rename a file for display or remove a failed upload silently. Preserve the original name, show a specific failure message, and retain retry/removal controls.
