Thumbnail
Thumbnail displays a compact, square preview of an image attachment. It shows a shimmer effect while uploading, the image on success, and a placeholder icon when no source is set. Use it in chat composers, file upload lists, or anywhere you need a small image preview with optional remove and click actions.
Installation
npm install @astryxdesign/core@0.7.1 @astryxdesign/theme-neutral@0.7.1 @stylexjs/stylex@0.19.0
Requires React 19+, base CSS and a Theme provider. See Setup.
Thumbnail
Thumbnail displays a compact, square preview of an image attachment. It shows a shimmer effect while uploading, the image on success, and a placeholder icon when no source is set. Use it in chat composers, file upload lists, or anywhere you need a small image preview with optional remove and click actions.
| Prop | Type | Default | Description |
|---|---|---|---|
| src | string | Image source URL. | |
| alt | string | Alt text for the image. When omitted, the image is explicitly decorative (alt="", role="presentation", aria-hidden) and hidden from screen readers; a dev warning fires if neither alt nor label is set. | |
| label | string | Accessible label (e.g. file name). Shown as tooltip on hover. | |
| onRemove | (e: React.MouseEvent) => void | Callback for the overlaid remove button. | |
| onClick | (e: React.MouseEvent) => void | Click handler. Adds button semantics and a hover overlay. | |
| isLoading | boolean | false | Shows skeleton (no src) or upload overlay (with src). |
| isDisabled | boolean | false | Whether the thumbnail is disabled. |
| showRemoveOn | 'always' | 'hover' | 'hover' | When the remove button is visible. hover (the default) reveals it on hover and on keyboard focus, and keeps it visible on any touch-capable device; always shows it at rest. Only applies when onRemove is set. |
| xstyle | StyleXStyles | StyleX styles for layout customization (margins, positioning, sizing). Must be a stylex.create() value, not an inline style object like style={{}}. | |
| className | string | CSS class name for the root element. Prefer xstyle for styling; className is provided for integration with non-StyleX systems. | |
| style | CSSProperties | Inline styles for the root element. Prefer xstyle for styling; inline styles bypass StyleX optimization. | |
| data-testid | string | Test selector for automated testing frameworks. |
Usage guidance
- Always provide a label prop with the file name so the thumbnail and its remove button are accessible to screen readers and show a tooltip on hover.
- Use isLoading without a src to show a skeleton during initial upload, and isLoading with a src to show a spinner overlay once a preview URL is available.
- Pair onClick with a lightbox or detail view so users can inspect the full image; the thumbnail adds button semantics and a hover overlay automatically.
- Avoid: Don't use Thumbnail for non-image file types like PDFs or spreadsheets; use a file attachment component with an appropriate icon instead.
- Avoid: Don't omit alt text when a src is provided; screen readers need a description of the image content, not just the file name from label.
Theming API
{
"targets": [
{
"className": "astryx-thumbnail"
}
],
"vars": [
{
"name": "--_thumbnail-hit-inset",
"description": "Outset of the remove button's invisible hit area, applied to a ::after overlay. 0 on a fine pointer; negative on a coarse one, which grows the 20px button to the 24px touch target without changing what is drawn.",
"default": "0px",
"private": true
},
{
"name": "--_press-overlay",
"description": "Fill of the ::after interaction overlay: transparent at rest, the hover overlay token on hover (hover-capable pointers), the pressed overlay token while pressed (`:active` on a mouse; `data-astryx-press=\"on\"` written by the touch press controller under a finger) and the hover token for the release fade. Set on the card element by its own interaction arms.",
"default": "transparent",
"private": true
},
{
"name": "--_press-overlay-transition",
"description": "Duration of the overlay's background-color transition: the fast duration token, except 0s while a believed touch press paints so it lands on the first frame.",
"default": "var(--duration-fast)",
"private": true
}
]
}
Anatomy
- Image: The preview image, displayed as a square with cover fit.
- Placeholder: An image silhouette icon shown when no src is provided.
- Remove button: An overlaid close button in the top-right corner. Appears when onRemove is set. Sits on a fixed --color-overlay scrim with an --color-on-dark icon to stay visible on any image.
- Upload overlay: A semi-transparent overlay with a spinner, shown when isLoading is true and a src preview is available.
- Skeleton: A shimmer animation shown when isLoading is true and no src is set.
Examples
- Thumbnail: A thumbnail with an image and label.
- Thumbnail — Disabled: Thumbnails in the disabled state with reduced opacity. The remove button and click handler are suppressed when disabled.
- Thumbnail — Gallery: A row of clickable thumbnails with labels that open a detail view. Use for image attachment lists where users need to preview and manage uploads.
- Thumbnail — Removable: Thumbnails with a remove button overlay. The close button uses APCA luminance detection to stay visible on both dark and light images.
- Thumbnail — States: All visual states side by side: image loaded, placeholder, skeleton loading, and upload overlay. Demonstrates the full lifecycle of a thumbnail from empty to loaded.