File Card
A card for a single file: a realistic file-type illustration or image thumbnail, the name, a meta line, trailing actions and an optional progress bar. Composes into attachment rows and upload trays.
Installation#
Usage#
File Card is composed from named parts, like Card. The FileCard root owns the surface, variant, state, and density; the parts (FileCardIcon, FileCardName, FileCardProgress) read it from context.
import {
FileCard,
FileCardIcon,
FileCardContent,
FileCardName,
FileCardMeta,
FileCardActions,
fileTypeFromName,
} from "@/components/ui/file-card"
import { Button } from "@/components/ui/button"
import { DownloadSimple, Trash } from "@phosphor-icons/react"
export function Attachment({ file }) {
return (
<FileCard>
<FileCardIcon type={fileTypeFromName(file.name)} />
<FileCardContent>
<FileCardName>{file.name}</FileCardName>
<FileCardMeta>{file.size}</FileCardMeta>
</FileCardContent>
<FileCardActions>
<Button variant="ghost" size="sm" iconOnly aria-label="Download"><DownloadSimple /></Button>
<Button variant="ghost" size="sm" iconOnly aria-label="Remove"><Trash /></Button>
</FileCardActions>
</FileCard>
)
}Anatomy#
A row reads left-to-right: a FileCardIcon (or FileCardThumbnail) leads, a FileCardContent column fills with the FileCardName over a muted FileCardMeta line, and FileCardActions ride the right edge. The name truncates so a long filename never pushes the actions off the card.
File types#
Pass type to FileCardIcon and it renders a realistic file illustration: a sheet with a dog-eared corner and a colored band stamped with the extension. The tone re-themes across all four palettes: PDFs read red, images purple, sheets green, and so on. The band shows a short stand-in (PDF, XLS, IMG…) by default; pass label to stamp the real extension (the demo below shows DOCX, XLSX, TSX). Don’t know the type up front? Derive it from the filename with fileTypeFromName(file.name). The illustration is FileIcon, also usable on its own: every extension, its soft and solid variants and SVG downloads live on File Icons.
Thumbnail#
For images, swap the glyph tile for a FileCardThumbnail. It fills the same footprint, clips the preview to the concentric radius, and carries a subtle inset outline so the image edge reads cleanly on any surface. Always pass a meaningful alt.
Tile layout#
Same card, second arrangement. Pass layout="tile" and the row becomes the square cell of an image grid: the FileCardThumbnail fills it edge to edge and FileCardActions become a blurred scrim that fades in on hover or keyboard focus. The tile itself never moves - no lift, no press scale - so the photo and the wash carry the whole interaction. Pair it with File Upload’s FileUploadGrid.
Upload progress#
Drop a FileCardProgress into the content column to show an in-flight upload. It renders the DS Progress bar, so a live value animates smoothly, the percentage uses tabular-nums, and the bar re-tones to destructive when the card’s state is error. Swap it for a FileCardMeta once the upload lands.
The readout is droppable. Leave it in and the label and percentage sit above the bar; pass hideValue and move the number out to a FileCardValue beside the content column, and the bar runs the full width with the percentage holding the row’s right edge.
States#
The root state drives the surface and the trailing FileCardStatus glyph: uploading spins, success lights a green check, and error pulls a soft destructive border with a warning so a failed file reads at a glance.
Variants#
default sits on a hairline border with a soft shadow; outline drops the shadow for flat, gridded lists; elevated trades the border for a lifted shadow when a card needs to float; ghost strips all chrome and padding so the row sits flush in feeds, comment threads, and dense lists. The file illustration still carries the file’s identity.
Density#
Density is Koala’s cross-cutting spacing axis (see Density). For File Card it tunes padding, gap, and the media tile. compact is the dense app default for upload trays and file lists; comfortable is roomier. Set it per-card or for a whole list with DensityProvider.
Interactive#
A file row is inert by default. When the whole card should open the file, pass asChild to render it as a link and interactive to add the pointer, hover lift, and focus ring. For per-file actions instead, keep the card inert and drop Buttons into FileCardActions.
API reference#
FileCard forwards all div props and adds layout (row | tile), variant (default | outline | elevated | ghost), state (idle | uploading | success | error), density (compact | comfortable), interactive, and asChild. The parts ( FileCardContent, FileCardName, FileCardMeta, FileCardValue, FileCardActions) forward div props. FileCardIcon adds type and an optional label band override (or pass your own glyph as children); FileCardThumbnail forwards img props and requires alt; FileCardProgress takes value, label, and hideValue; FileCardStatus takes an optional status (else it reads the card’s state). The helper fileTypeFromName(name) maps a filename to a type. Every part accepts className, merged last.