FileCard

A file shown as a card with its type icon, name and size, or as an image, video or audio preview.

Accessibility

What FileCard does for you, and what it leaves to the page around it.

What a file card renders

A file card is a set of <div>s with no role. A screen reader reads the name, the extension and the description line as text. The type icon is decorative and hidden, so the extension in the name is what tells the reader the type.
  • Keep the extension in name. “Q3 report” with a red icon is a PDF only to a sighted reader.
  • The size reads as “482 KB”. If the description carries a status, like uploading or failed, write it in words, not only as a color.

Clickable cards

onClick goes on a <div>. The card does not take focus, has no link or button role and does not answer Enter, so a keyboard user cannot open the file.
  • For a file the reader opens or downloads, wrap the card in a real link and leave onClick off. The link takes its name from the card's text: the file name and the size.
  • For any other action, put a Button next to the card or in its description, and keep the card itself plain.
1
<a href={file.url} download={file.name}>
2
<FileCard name={file.name} byte={file.size} />
3
</a>

Mask content is hover only

mask is invisible until the pointer is over the card. A button inside it can still take focus, so a keyboard user can land on a control they cannot see, and a touch user never sees it at all.
  • Never make the mask the only way to an action. Offer the same action somewhere that is always visible, like the message's Actions row.

Images, audio and video

An image preview takes its alt text from name, so a screen reader hears “river.jpg”. Audio and video use the browser's own player, with its controls, which work from the keyboard.
  • When the image carries meaning, pass a real description through imageProps: imageProps={{ alt: "A river at dusk" }}. It wins over the file name.
  • A video with speech needs captions. Pass a <track kind="captions"> as videoProps.children.
  • Do not autoplay audio or video through audioProps or videoProps. Sound that starts on its own talks over a screen reader.

FileCard.List

The list is a row of <div>s with no list role and no count. The remove button on each card is a <div> with a click handler: it takes no focus and has no name. The arrow buttons scrollX adds are real buttons, but they carry only a glyph and no name.
  • Say how many files there are in text next to the list, like “3 files attached”, so the reader knows what to expect.
  • To make removing work from the keyboard, turn removable off and put a Button in each file's description, with an aria-label like “Remove oblomov.pdf”. This works for file cards, not for image, audio or video previews.
  • After a remove, move focus to the next file or to the input, so it does not drop to the top of the page.
  • Prefer wrap where every file must be reachable. A scrolling strip hides files behind arrows that a screen reader cannot name.