File Card
One file as a card row (thumbnail or icon, name, details, actions) that opens the viewer or links to a download or page; UploadCard is its twin for uploads.
- Status
- Since
0.25.22- Accessibility pattern
- one named open button or link, named actions menu
Last updated
Install
Configure registry credentials first using the Quickstart. Before copying this item or any transitive registry dependency, verify the signed manifest and save the exact bytes for File Card before installation. Retain the digest printed by this command.
pnpm exec vegastack-design verify file-cardInstall with the pinned shadcn CLI. Bare shadcn does not verify VegaStack signature or integrity.
pnpm dlx shadcn@4.21.0 add @vegastack/file-cardRun the exact offline --post-write command printed by the preflight, using its saved item path and independently retained --expected-integrity digest. Use the saved preflight for every transitive registry dependency too; stop on any mismatch before using the components.
The same command installs the registry items it composes: @vegastack/attachment, @vegastack/data-table-parts, @vegastack/dropdown-menu, @vegastack/file-kind, @vegastack/file-viewer, @vegastack/image.
Usage
import { AttachmentGroup } from "@/components/ui/attachment";
import { FileCard, UploadCard } from "@/components/ui/file-card";
<AttachmentGroup layout="cards" role="list" aria-label="Files">
<FileCard
name="spec-sheet.pdf"
contentType="application/pdf"
descriptions={["64 KB", "Asha Rao · today"]}
file={file}
actions={[{ label: "Remove", destructive: true, onSelect: remove }]}
/>
<UploadCard
name="install-guide.pdf"
type="application/pdf"
progress={64}
error={null}
onCancel={cancel}
onRetry={retry}
/>
</AttachmentGroup>;FileCard is the one tile every file list shares — a task's attachments, a product's files, images and
accessories. It composes Attachment and adds no layout of its own:
put cards in an AttachmentGroup with role="list" (each card is a listitem), choosing
layout="cards" for a responsive grid, or layout="list" for full-width rows.
Anatomy
Examples
Open in the viewer
Give a card its file (a FileViewerItem) and the whole card becomes one
Open {name} button. It opens the viewer, paging through the group's cards; onOpen replaces the
built-in viewer with your own handler.
Link to a download or a page
href makes the whole card one link, for a file that opens elsewhere: a file the viewer cannot show
downloads, an accessory navigates to its page. download downloads in place and names the link
Download {name}; target="_blank" opens a new tab (with rel="noopener") and names it Open {name} in a new tab. The ⋯ menu stays above the link, clickable on its own. When file is set href is
ignored.
Thumbnail, icon, preview
thumb shows the stored image in the media box, with its blur underneath until it loads; without one
the box shows the file's type icon. preview is the picked image's local object URL: it shows while
there is no thumbnail yet and sits under the thumbnail until it loads, so the card never flashes blank.
icon replaces both — a lock, a page's emoji.
Muted
muted dims the media of a file the record no longer uses. Say why in descriptions, so the state is
never carried by opacity alone.
Actions
actions is a RowAction[] — the same shape a table row's menu takes — drawn as a ⋯ menu named
Actions for {name}. extra puts your own controls before it (a "Go to comment" link, a remove
button).
Wording
The built-in names and text — Actions for {name}, Download {name}, Retry {name}, "Finishing
upload" — are overridable through the labels prop of FileCard and of UploadCard, for another
language or house style.
Uploading
UploadCard lays out like a FileCard, so a list swaps one for the other as a file finishes. It shows
a determinate bar (progress), "preparing" while progress is null, "Finishing upload" once the
bytes are up (finishing), and on error the reason with Retry. Cancel is always there; cancellable={false}
disables it.
API Reference
FileCard
| Prop | Type | Default | Description |
|---|---|---|---|
name* | string | — | The file name: the card's title. |
actions | RowAction[] | [] | The ⋯ menu, named "Actions for {name}". Empty (and no extra) draws no actions. |
contentType | string | null | — | MIME type, which picks the type icon when there is no thumbnail. |
descriptions | React.ReactNode[] | — | The lines under the name (size, who, when). The first reads in tabular figures; a null
entry is skipped. |
download | boolean | false | With href: the link downloads the file instead of navigating, and is named "Download {name}". |
extra | React.ReactNode | — | Controls before the ⋯ menu (a "Go to comment" link, a remove button). |
file | FileViewerItem | — | The file this card stands for. With it the whole card is one "Open {name}" button that opens
the file viewer — the enclosing group's preview, or onOpen — and href is ignored. |
href | string | — | Make the whole card a link, for a file that opens elsewhere: a download for a file the viewer
cannot show, or a page to navigate to. Ignored when file is set. |
icon | React.ReactNode | — | In place of the thumbnail or type icon — a lock, a page's emoji. |
labels | FileCardLabels | — | Override the built-in link and menu names (for another language or wording). Each is given the file name. |
muted | boolean | false | Dim the media (the file is no longer in use); say why in descriptions. |
onOpen | ((file: FileViewerItem) => void) | — | Called instead of the built-in viewer when the card is opened. Needs file. |
preview | string | null | — | The picked image's local preview (an object URL): shown while there is no thumbnail yet, and under the thumbnail until it loads, so the card never flashes blank. |
size | "default" | "lg" | "sm" | "xs" | null | "default" | The card's size. |
target | React.HTMLAttributeAnchorTarget | — | With href: the link's target. _blank also sets rel="noopener" and names the link
"Open {name} in a new tab". |
thumb | FileCardThumb | null | — | The stored thumbnail. With it (or preview) the media shows the image instead of a type icon. |
UploadCard
| Prop | Type | Default | Description |
|---|---|---|---|
error* | string | null | — | The failure reason; shows the error state with Retry. null for none. |
name* | string | — | The file name: the card's title. |
onCancel* | () => void | — | Cancel the upload. |
onRetry* | () => void | — | Retry after an error. |
progress* | number | null | — | Upload progress, 0–100; null while preparing (fingerprint, ticket). |
type* | string | — | MIME type, which picks the type icon. |
cancellable | boolean | true | Whether Cancel is enabled. |
finishing | boolean | false | The bytes are up and the upload is being completed: the bar becomes "Finishing upload" and Cancel is disabled. |
labels | UploadCardLabels | — | Override the built-in text and names (for another language or wording). |
preview | string | null | — | The picked image as an object URL: shown at once, while it uploads. |
size | "default" | "lg" | "sm" | "xs" | null | "default" | The card's size. |
Accessibility
- Each card is a
listitem: give theAttachmentGrouprole="list"and anaria-label. - The open button and the link are named for the file and for what activating them does —
Open {name},Download {name},Open {name} in a new tab— and the whole card is the target. - The ⋯ menu button is named
Actions for {name}; it and anyextracontrol sit above the open button or link, so each stays separately focusable and clickable. UploadCard's bar is a named progress bar (Uploading {name},Preparing {name}) that announces its percentage; a failure's reason is text, never colour alone.- Focus is the global outline from
base.css, on the open button or link, following the card's corner.
| Contract | States tested |
|---|---|
| Behaviour | default, muted, uploading, processing, error, open, link, disabled |
| Accessibility | labeled, semantic-html, status-announcement, focus-visible |
| Visual | default, muted, error |