suiss/ui · Component
Attachment
A compact file card that shows a document or image with its name, details, upload state and actions.
Attachment is an open-source component from suiss/ui for React, React Native, SwiftUI and Jetpack Compose. The @esuiss/ui CLI copies its source into your project, so you own the code.
An Attachment typically contains an AttachmentMedia thumbnail, an AttachmentContent block with AttachmentTitle and AttachmentDescription, and an AttachmentActions slot holding one or more AttachmentAction buttons. AttachmentMedia can hold an icon, an img, or an AttachmentLabel file-type tag. During an upload, put an AttachmentProgress bar inside the content. Add an AttachmentTrigger to make the whole card clickable.
Wrap several attachments in an AttachmentGroup to render them as a single list with inset dividers. Use attachments for files in composers, chat messages and upload forms.
Installation
CLI
Works in any project with a components.json. See Installation for the one-line registry setup. Or use the suiss/ui CLI:
Manual
- Install the dependencies and add the
cnhelper:
-
Add the pieces it builds on: Button.
-
Copy the source into
components/ui/attachment.tsx:
- Update the import paths to match your project.
Usage
Set state to reflect the file's lifecycle. idle adds a dashed border (outside a group), and error colors the description with text-destructive. The state, size and orientation values are also exposed as data-* attributes for your own styling.
AttachmentAction renders a Button with the secondary variant and an icon size by default. Pass variant="link" for a text action such as "Try Again". Icon-only actions need an aria-label.
AttachmentTrigger is an invisible button stretched over the card. Give it an aria-label, or use render to turn it into a link. Actions sit above it, so they remain separately clickable.
Examples
Sizes
Compares the default, sm and xs sizes.
States
Shows the idle, uploading, processing, error and done states.
Drop zone
Image
Uses an image thumbnail with the image media variant.
Vertical
Stacks the media above the content with orientation="vertical".
Clickable
Makes the whole card a button with AttachmentTrigger, alongside a separate download action.
Group
Combines several attachments in one AttachmentGroup list.
File types
Uses colored AttachmentLabel tags to indicate file extensions.
File list
A full-width list of separate attachment cards.
Uploaded
Marks completed uploads with a check icon in the actions slot.
API Reference
Attachment
The card container that sets size, orientation and state.
| Prop | Type | Default | Description |
|---|---|---|---|
size | "default" | "sm" | "xs" | "default" | Overall density: default, sm or xs. |
orientation | "horizontal" | "vertical" | "horizontal" | horizontal places media beside the content; vertical stacks it above and overlays actions on the media. |
state | "idle" | "uploading" | "processing" | "error" | "done" | "done" | Upload lifecycle state. idle adds a dashed border and error colors the description red. |
Also accepts the props of React.ComponentProps<"div">.
AttachmentLabel
A small uppercase tag, usually the file extension, shown inside the media.
Also accepts the props of React.ComponentProps<"span">.
AttachmentMedia
The thumbnail area for an icon, document tag or image.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "icon" | "document" | "image" | "icon" | Thumbnail style: icon for a bordered icon tile, document for a page shape with a bottom tag, image for a cropped image. |
Also accepts the props of React.ComponentProps<"div">.
AttachmentContent
Wraps the title, description and progress bar.
Also accepts the props of React.ComponentProps<"div">.
AttachmentTitle
The file name, truncated to one line.
Also accepts the props of React.ComponentProps<"span">.
AttachmentDescription
Secondary details such as file size or an error message.
Also accepts the props of React.ComponentProps<"span">.
AttachmentProgress
A progress bar with a value readout for uploads.
Also accepts the props of the primitive part it wraps.
AttachmentActions
The slot for action buttons or status indicators.
Also accepts the props of React.ComponentProps<"div">.
AttachmentAction
A compact button for actions such as remove, cancel or download.
Also accepts the props of React.ComponentProps<typeof Button>.
AttachmentTrigger
An invisible button covering the card to make it clickable.
Also accepts the props of useRender.ComponentProps<"button">.
AttachmentGroup
Stacks attachments into one rounded list with dividers.
Also accepts the props of React.ComponentProps<"div">.
Accessibility
AttachmentProgresswraps the progress primitive and exposes theprogressbarrole witharia-valuenow; give it anaria-label.AttachmentTriggerrenders abuttonwithtype="button"by default; give it anaria-labelthat names the file.- The trigger and each
AttachmentActionare separate tab stops, in that order. - The card shows a focus ring when its trigger has keyboard focus.
Notes
- Styling hooks:
data-slotvalues such asattachment,attachment-media,attachment-contentandattachment-action, plusdata-state,data-sizeanddata-orientationon the root anddata-varianton the media. - Inside
AttachmentGroup, attachments fill the width, lose their own rounding and get inset top dividers. AttachmentLabelusesbg-primaryby default; override it with a color class per file type.
Web preview
Attachment is a rounded View that lays out an AttachmentMedia thumbnail, an AttachmentContent column and AttachmentActions. It comes in default, sm and xs sizes and in horizontal or vertical orientation; the vertical layout makes a tile with the actions floating over the media.
The state prop reflects the upload lifecycle: idle draws a dashed border for an empty drop slot, error turns the description red, and uploading, processing and done are passed to the parts through context. Put several attachments in an AttachmentGroup to show them as one list with hairlines between rows.
Installation
The CLI also adds what it builds on: Button, Icon, Progress, Text.
Manual
- Install the dependencies:
-
Add the pieces it builds on: Button, Icon, Progress, Text, and the primitives
components/primitives/progress.tsx,components/primitives/types.tsx,components/primitives/use-render.tsx. -
Copy the source into
components/ui/attachment.tsx:
- Update the import paths to match your project.
- Install the dependencies:
-
Add the pieces it builds on: Button, Icon, Progress, Text, and the primitives
components/primitives/progress.tsx,components/primitives/types.tsx,components/primitives/use-render.tsx. -
Copy the source into
components/ui/attachment.tsx:
- Update the import paths to match your project.
-
Add the pieces it builds on: Button, Icon, Progress, Text, and the primitives
components/primitives/progress.tsx,components/primitives/types.tsx,components/primitives/use-render.tsx. -
Copy the source into
components/ui/attachment.tsx:
- Update the import paths to match your project.
-
Target iOS 17 or later.
-
Copy the theme files every view uses:
- Copy the source and every file it uses:
- Add the files to your app target.
- Set
minSdkto 24 or higher and add the dependencies:
- Copy the theme files every view uses:
- Copy the source and every file it uses:
- Update the
com.esuiss.uipackage names to match your project.
Usage
AttachmentMedia has three variants: icon for a glyph, document for a page shape (pair it with AttachmentLabel to show a file extension), and image for a thumbnail. Put AttachmentTitle and AttachmentDescription in AttachmentContent, and add AttachmentProgress with a value while uploading.
AttachmentAction is a Button that defaults to the secondary variant and a small icon size scaled to the attachment, with an enlarged hit area. Use variant="link" for a text action.
To make the whole card pressable, add an AttachmentTrigger; it covers the card while actions stay pressable above it.
Examples
Sizes
The default, sm and xs sizes.
Web preview
States
The idle, uploading, processing, error and done states.
Web preview
Image
An image thumbnail with the image media variant.
Web preview
Vertical
Tiles with orientation="vertical".
Web preview
Pressable
A card made pressable with AttachmentTrigger.
Web preview
Group
Several attachments in an AttachmentGroup, one of them uploading.
Web preview
File types
Document media with colored extension labels.
Web preview
API Reference
Attachment
Card that provides state, size and orientation to its parts.
| Prop | Type | Default | Description |
|---|---|---|---|
state | AttachmentState | "done" | idle, uploading, processing, error or done. Defaults to done. |
size | AttachmentSize | "default" | default, sm or xs. |
orientation | AttachmentOrientation | "horizontal" | horizontal or vertical. |
Also accepts the props of ViewProps.
AttachmentMedia
Thumbnail area for an icon, document shape or image.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "icon" | "document" | "image" | "icon" | icon, document or image. |
Also accepts the props of ViewProps.
AttachmentLabel
Small uppercase tag, such as a file extension.
Also accepts the props of ViewProps.
AttachmentContent
Column for the title, description and progress.
Also accepts the props of ViewProps.
AttachmentTitle
File name, one line by default.
Also accepts the props of React.ComponentProps<typeof Text>.
AttachmentDescription
Secondary details, red in the error state.
Also accepts the props of React.ComponentProps<typeof Text>.
AttachmentProgress
Progress bar with a percentage value.
Also accepts the props of React.ComponentProps<typeof ProgressPrimitive.Root>.
AttachmentActions
Row of actions; floats over the media in vertical layout.
Also accepts the props of ViewProps.
AttachmentAction
Small button sized to the attachment.
Also accepts the props of React.ComponentProps<typeof Button>.
AttachmentTrigger
Pressable overlay that makes the whole card pressable.
| Prop | Type | Default | Description |
|---|---|---|---|
render | RenderProp<Record<string, unknown>, Record<string, never>> | - |
Also accepts the props of React.ComponentProps<typeof Pressable>, React.RefAttributes<View>.
AttachmentGroup
List container that joins attachments with separators.
Also accepts the props of ViewProps.
Accessibility
AttachmentProgresshas theprogressbarrole with its value exposed.AttachmentTriggerhas thebuttonrole; give it anaccessibilityLabelsuch as "Open Invoice.pdf".- Icon-only actions need an
accessibilityLabel.
Notes
- Uses
bg-muted,border-border,bg-primaryandtext-destructivetokens; light and dark follow the system appearance. - Separators and action positions use start and end offsets, so they flip in right-to-left layouts.