Skip to content

File card

Shows a file as a card with its thumbnail or type icon, its name and actions. To pick files, use File selector.

Renewal proposal.pdf

Installation

pnpm dlx shadcn@latest add @wisty/file-card

The CLI installs the Radix or Base UI file to match your project, with what it builds on: icon, spinner, button, dropdown-menu.

If your project doesn't have Wisty UI's theme yet, add it once with npx shadcn@latest add @wisty/cosmos. Until then, components keep shadcn's default look. Installation has the details.

When to use

Use it

  • A record page lists its files as a grid of cards, each with a thumbnail or a type icon and its name.
  • One file needs a preview people open, with Download and a menu of file actions beside its name.
  • An attachment row needs a small picture of the file, like an email's attachment beside its linked name.
  • Files just chosen in a File selector should show as cards before they're uploaded.
  • It replaces SLDS's file card, what lightning-file-card and the Files related list draw.

Don't use it

  • People pick or drop files. Use File selector, then show what they chose with File card.
  • The upload itself, with progress and a server. The card only draws a file the page already knows.
  • A plain list of files with no pictures, like names and sizes in a table or a list. Use Item or Table.
  • A record or a block of content that isn't a file. Use Card.

Usage

Copy the icon package's folder to the app's static files once, unchanged, as Icon does:

mkdir -p public/assets/icons
cp -R node_modules/@salesforce-ux/icons/dist/salesforce-lightning-design-system-icons/. public/assets/icons/
import {
  FileCard,
  FileCardActions,
  FileCardCaption,
  FileCardPreview,
  FileCardSource,
  FileCardTitle,
} from "@/components/wisty/file-card"
FileCard
├── FileCardPreview
├── FileCardCaption
│   ├── FileCardTitle
│   └── FileCardActions
└── FileCardSource
<FileCard name="Site survey.csv">
  <FileCardPreview href="/files/site-survey" />
  <FileCardCaption>
    <FileCardTitle />
  </FileCardCaption>
</FileCard>

FileCardPreview is a link with href, a button with onClick, and a picture with neither. Its thumbnail is the image, { state: "loading" } while the page fetches one, or { state: "unavailable" } when it can't be shown. Leave it out for a file that has no image, and the preview shows its type icon. { state: "placeholder" } fills the preview with a pattern in the theme's primary colors instead, for a page with no real images yet, like a prototype over sample records. The type icon comes from the name's extension, or from icon when the page knows better:

<FileCard name="Site survey notes" icon="doctype:quip_doc">

fileCardIcon(name) gives the same icon for a name, for a list that draws it elsewhere.

Examples

Crops

The placeholder pattern filling each `crop` on `FileCardPreview`, with long names truncated before the download button.

Storefront renovation, north entrance.jpg
Storefront renovation, east entrance.jpg
Storefront renovation, south entrance.jpg

Without a title

An image with no `FileCardTitle`: `variant="scrim"` on `FileCardCaption` puts the download button on a dark gradient.

More files

Two of a record's files and a tile linking to 22 more, with `variant="overlay"` and an `aria-label` that names the link.

  • Renewal proposal.pdf
  • Site survey.png
  • +22

Email attachment

A captionless card as an attachment row's picture, beside the linked file name, its size and a download link.

Chosen files

Files just chosen in a file selector, as static cards with a Remove button and the type icon read from each name.

  • Signed order form.pdf
  • Pricing model.xlsx

External source

A Quip document with `FileCardSource` naming the service it comes from, beside its own type icon.

Site survey notes
From Quip

Thumbnail states

A thumbnail still loading, one that can't be shown, and a file of an unknown type, each keeping its name and link.

Loading thumbnail
Floor plan.png
Thumbnail unavailable
Inspection photos.zip
Meter readings.dat

API reference

PartBuilt onDescription
FileCard<div> (opens in a new tab)One file as a card: a preview, and a title bar with its name and actions.
FileCardPreview<div> (opens in a new tab)The cropped picture of the file: a link with href, a button with onClick, or a picture with neither.
FileCardCaption<div> (opens in a new tab)The bar over the preview's bottom that holds the title and actions, or a count over the whole preview.
FileCardTitle<span> (opens in a new tab)The file's type icon and its name, truncated.
FileCardActions<div> (opens in a new tab)The file's own actions, like Download and a menu, beside the title or on their own.
FileCardSourceIconThe icon of the service the file comes from, over the preview's top start.

FileCard

One file as a card: a preview, and a title bar with its name and actions.

PropTypeDefaultDescription
name*stringThe file's name, with its extension.
icon`doctype:${FileCardDoctype}`The type icon; defaults to the one for the name's extension.

FileCardPreview

The cropped picture of the file: a link with href, a button with onClick, or a picture with neither.

PropTypeDefaultDescription
thumbnailFileCardThumbnailThe image, a stand-in pattern, a loading image or one that can't be shown; omit it for the type icon.
cropFileCardCrop"16-by-9"The crop's ratio. Default "16-by-9".
loadingLabelstring"Loading thumbnail"Read while the image loads. Default "Loading thumbnail".
unavailableLabelstring"Thumbnail unavailable"Shown when the image can't be. Default "Thumbnail unavailable".
hrefstringMakes the preview a link that opens the file. Not with onClick.
onClickReact.MouseEventHandler<HTMLButtonElement>Makes the preview a button that runs the page's own preview. Not with href.
disabledbooleanTurns the button off, with onClick.

FileCardCaption

The bar over the preview's bottom that holds the title and actions, or a count over the whole preview.

PropTypeDefault
variant"default" | "overlay" | "scrim""default"

FileCardTitle

The file's type icon and its name, truncated.

PropTypeDefaultDescription
childrenstringWords shown instead of the file's name.

FileCardActions

The file's own actions, like Download and a menu, beside the title or on their own.

PropTypeDefaultDescription
aria-label*stringNames the group after the file it acts on.

FileCardSource

The icon of the service the file comes from, over the preview's top start.

PropTypeDefaultDescription
label*stringNames the service, and is its tooltip unless title is given.

fileCardIconfunction

The type icon for a file name's extension in any case, or "doctype:unknown".

ParameterTypeDefault
name*string

Returns "doctype:audio" | "doctype:html" | "doctype:link" | "doctype:video" | "doctype:image" | "doctype:unknown" | "doctype:overlay" | "doctype:ai" | "doctype:attachment" | "doctype:box_notes" | "doctype:css" | "doctype:csv" | "doctype:eps" | "doctype:excel" | "doctype:exe" | "doctype:flash" | "doctype:folder" | "doctype:gdoc" | "doctype:gdocs" | "doctype:gform" | "doctype:gpres" | "doctype:gsheet" | "doctype:keynote" | "doctype:library_folder" | "doctype:mp4" | "doctype:pack" | "doctype:pages" | "doctype:pdf" | "doctype:ppt" | "doctype:psd" | "doctype:quip_doc" | "doctype:quip_sheet" | "doctype:quip_slide" | "doctype:rtf" | "doctype:shared_folder" | "doctype:slack_canvas" | "doctype:slack_list_item" | "doctype:slack_lists" | "doctype:slide" | "doctype:stypi" | "doctype:txt" | "doctype:vcf" | "doctype:visio" | "doctype:webex" | "doctype:word" | "doctype:xml" | "doctype:zip".

FileCardDoctypetype

A symbol in the doctype sprite of

type FileCardDoctype =
  | "ai"
  | "attachment"
  | "audio"
  | "box_notes"
  | "css"
  | "csv"
  | "eps"
  | "excel"
  | "exe"
  | "flash"
  | "folder"
  | "gdoc"
  | "gdocs"
  | "gform"
  | "gpres"
  | "gsheet"
  | "html"
  | "image"
  | "keynote"
  | "library_folder"
  | "link"
  | "mp4"
  | "overlay"
  | "pack"
  | "pages"
  | "pdf"
  | "ppt"
  | "psd"
  | "quip_doc"
  | "quip_sheet"
  | "quip_slide"
  | "rtf"
  | "shared_folder"
  | "slack_canvas"
  | "slack_list_item"
  | "slack_lists"
  | "slide"
  | "stypi"
  | "txt"
  | "unknown"
  | "vcf"
  | "video"
  | "visio"
  | "webex"
  | "word"
  | "xml"
  | "zip"

FileCardCroptype

type FileCardCrop = "16-by-9" | "4-by-3" | "1-by-1"

FileCardThumbnailtype

The preview's image, a stand-in pattern, or why there's none yet.

type FileCardThumbnail =
  | { state: "image"; src: string; alt: string }
  | { state: "placeholder" }
  | { state: "loading" }
  | { state: "unavailable" }

SLDS mapping

FileCard is slds-file slds-file_card. FileCardPreview is the slds-file__crop link, with the image, the centered slds-file__icon or the medium spinner of slds-file_loading inside. FileCardCaption is slds-file__title_card by default, slds-file__title_overlay over slds-file_overlay as overlay, and slds-file__title_scrim as scrim. FileCardTitle is the small media object with the x-small type icon and slds-file__text slds-truncate. FileCardActions is slds-file__actions-menu with its button group, and FileCardSource is slds-file__external-icon.

Known gaps:

  • No uncropped figure (slds-file__figure) or portrait figure (slds-file__figure_portrait). Every preview has a crop.
  • No link attachment, the media object with a small file and a source line.
  • The preview's eye and the action icons are lucide's, where SLDS draws its own eye and utility:download and utility:down.
  • "Thumbnail unavailable" under the type icon is an addition. SLDS draws a missing and a broken image the same.
  • The placeholder pattern is an addition. SLDS draws a file with no image as its type icon.
PropValueSLDSNotes
crop16-by-9 (added)slds-file__crop slds-file__crop_16-by-9The default: a 16:9 preview with the image centered at its own size.
crop4-by-3 (added)slds-file__crop slds-file__crop_4-by-3A 4:3 preview, as a grid of a record's files uses.
crop1-by-1 (added)slds-file__crop slds-file__crop_1-by-1A square preview.
variantdefault (added)slds-file__title slds-file__title_cardOn FileCardCaption: the title bar over the preview's bottom, with the actions at its end.
variantoverlay (added)slds-file_overlay, slds-file__title slds-file__title_overlay slds-text-heading_largeOn FileCardCaption: a dark layer over the whole preview with a centered count, like "+22".
variantscrim (added)slds-file__title slds-file__title_scrim, slds-button_icon-inverseOn FileCardCaption: the actions alone on a gradient over the image, with inverse icons.
(loading)aria-busy (added)slds-file_loadingOn FileCardPreview while its image loads: a spinner, and no hover layer.

Accessibility

  • A link or button preview is named by the file's name. Give the more-files tile an aria-label that says what it opens, like "Show 22 more files".
  • Give each action its own name with the file in it, like "Download Renewal proposal.pdf", and give FileCardActions an aria-label.
  • Write an alt that describes the image, or "" when the name beside it says it all, as in an attachment row.
  • While the image loads the preview is aria-busy and described by "Loading thumbnail". When it can't be shown, by "Thumbnail unavailable". Change the words with loadingLabel and unavailableLabel.

Motion

  • The spinner turns while a thumbnail loads, and stops with reduced motion.

Responsive behavior

  • The card fills its container. The page sets its width or the grid's columns.
  • A long name truncates before the actions, and the full name shows as the preview's tooltip.
  • On a device with no hover, the dark layer and the eye don't show.

Rules

  • Put actions in FileCardActions, never inside FileCardPreview. The preview is the card's one link or button.
  • Give every action button type="button" in a form, or it submits the form.
  • Keep FileCardTitle and FileCardActions in a default FileCardCaption. A scrim caption holds only actions, and an overlay caption only a FileCardTitle with its count.
  • Pass icon only as a doctype: symbol the icon package has. The type checks it.
  • Never pass asChild or render.