File Card
Presentation-only card that represents a single file with its media, name, label, and actions.
Installation
The component is exported from @by/experience-system. Add the package with your package manager:
pnpm add @by/experience-systemIn this monorepo, depend on the workspace package (for example via workspace:* or your catalog) so imports resolve to packages/experience-system.
Composition
Use the following composition to build a FileCard:
FileCard
├── FileCardMedia
├── FileCardContent
│ ├── FileCardName
│ └── FileCardLabel (optional)
└── FileCardActions (optional)Group related cards with FileCardGroup for consistent spacing. FileCard is presentation-only — it has no built-in file behavior (no upload, drag-and-drop, or I/O). It is a div by default and can render as any element with asChild.
Usage
import {
FileCard,
FileCardActions,
FileCardContent,
FileCardGroup,
FileCardLabel,
FileCardMedia,
FileCardName,
} from '@by/experience-system';FileCard is a client component ('use client'). Use it inside a Client Component or a dynamic import when using the Next.js App Router.
<FileCard onClick={() => open(file)}>
<FileCardMedia fileName="report.pdf" />
<FileCardContent>
<FileCardName>report.pdf</FileCardName>
<FileCardLabel>240 KB</FileCardLabel>
</FileCardContent>
</FileCard>Pass onClick to make the whole card activate a consumer-defined callback: the card becomes interactive (role="button", keyboard focusable, activates on Enter / Space). Prefer asChild with a real <a> or <button> when you already have a semantic element.
When to use
Use FileCard to display an existing file — for example a selected attachment, a search result, or an item in a file list — with a derived type icon or extension badge, a name, and optional actions.
When not to use
For picking or uploading files (dropzone, validation, image gallery, preview dialog), use FileUpload instead. FileCard does not read or manage files.
Examples
Sizes
Use the size prop for sm, md (baseline), or lg density. Horizontal cards use minimum heights per the design spec: sm is a 24px compact row (name and label inline), md is 40px (stacked name over label), and lg is 48px. Inside a size="sm" card, FileCardMedia defaults to the compact badge media.
Media types
FileCardMedia renders an icon (file-type glyph), a badge (uppercase extension), or an image (thumbnail). When no children are supplied and fileName is set, the icon and badge are derived from the extension. When variant is omitted, the media defaults to badge for size="sm" and icon otherwise.
Category colors
Media derived from fileName is colored by the file's category — documents (blue), PDF (red), spreadsheets (green), presentations (orange), images (purple), media (cyan), compressed (brown), design (iris), and code / unknown (slate). Category tints use contrast white text in light mode and black text in dark mode. The resolved category is exposed on data-category. Explicit children keep their own color.
Toolbar & status
The card has no persistent right-side toolbar. Surface actions on demand: put an overflow menu in FileCardActions (via DropdownMenu), reveal details with a HoverCard, show a Spinner while work is in flight, or pair color="error" with an error icon and a retry control.
Vertical
Use orientation="vertical" for a stacked card layout. Vertical cards use fixed square footprints (sm 24px, md 40px, lg 100px). With FileCardMedia variant="image", the preview spans the full card width (16:9) at size="lg". At sm and md, an image-only vertical card fills the square and hides name, label, and actions. FileCardActions is positioned in the top-end corner of vertical cards.
API Reference
Subsection titles name the exports from @by/experience-system. FileCard is an Experience System composite (not a Radix primitive); the tables document each part's props and data attributes.
FileCard
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
variant | 'outline' | 'soft' | 'outline' |
orientation | 'horizontal' | 'vertical' | 'horizontal' |
size | 'sm' | 'md' | 'lg' | 'md' |
color | 'neutral' | 'warning' | 'error' | 'neutral' |
selected | boolean | false |
onClick | React.MouseEventHandler | — |
Also accepts standard div attributes except color, which is reserved for the semantic status tint.
| Data attribute | Values |
|---|---|
data-slot | file-card |
data-variant | outline, soft |
data-orientation | horizontal, vertical |
data-size | sm, md, lg |
data-color | neutral, warning, error |
data-selected | present ('true') when selected |
data-interactive | present ('true') when interactive or asChild |
FileCardGroup
Container that groups related cards with consistent spacing. Accepts standard div attributes; applies no list role by default. For list semantics pass role="list" here and role="listitem" on each card (or use <ul>/<li>).
FileCardMedia
| Prop | Type | Default |
|---|---|---|
variant | 'icon' | 'badge' | 'image' | badge for sm, else icon |
fileName | string | — |
previewSrc | string | — |
previewAlt | string | '' |
When no children are supplied and fileName is set, icon renders the matching @by/icons/ui file-type icon and badge renders the uppercase extension. Explicit children always win over derivation. When the resolved media is image and previewSrc is set (and no children are supplied), the thumbnail is rendered from that URL. In orientation="vertical" cards the image variant fills the square card. Derived icon/badge media sits on a solid category-colored square (documents → blue, PDF → red, spreadsheets → green, presentations → orange, images → purple, media → cyan, compressed → brown, design → iris, code / unknown → slate) with contrast text that adapts in dark mode.
| Data attribute | Values |
|---|---|
data-slot | file-card-media |
data-variant | icon, badge, image |
data-category | document, pdf, spreadsheet, presentation, image, media, compressed, design, code, unknown (only when derived from fileName) |
FileCardContent
Wraps FileCardName and FileCardLabel. Accepts standard div attributes. data-slot="file-card-content".
FileCardName
Displays the file name, including its extension; truncates on overflow. Accepts standard div attributes. data-slot="file-card-name".
FileCardLabel
Displays supporting text such as a label, file size, or status message. Use kind="meta" for helper text and kind="status" for status messages that should stay visually distinct. In compact rows (size="sm"), name and label sit inline. Tints to match color="warning" / color="error". Accepts standard div attributes. data-slot="file-card-label".
FileCardActions
Container for action buttons or other controls. In orientation="vertical" cards, actions are absolutely positioned in the top-end corner. Action clicks also bubble to the card onClick; call stopPropagation in the action handler to prevent the card click. Accepts standard div attributes. data-slot="file-card-actions".
Accessibility
- When
onClickis set (andasChildis not), the card exposesrole="button", becomes focusable (tabIndex={0}), and activates on Enter / Space. A visible focus-visible ring is rendered. - Prefer
asChildwith a semantic<a>or<button>when the card is a link or a real button; wire click/keyboard behavior on that child. The card still receives interactive affordances viadata-interactive. - Derived media icons are
aria-hidden; convey the file type through the visible name and label rather than the glyph alone. - Give icon-only controls inside
FileCardActionsanaria-label, and label a loadingSpinnerso its purpose is announced.
Keyboard interactions
| Key | Description |
|---|---|
Tab | Moves focus to an interactive card (or asChild element). |
Space / Enter | Activates an interactive card and fires onClick. |
Source in the repo: packages/experience-system/src/components/FileCard/FileCard.tsx. Agent-oriented contracts: packages/experience-system/src/components/FileCard/FileCard.instructions.md.