suiss/uim · React Native Component

Attachment

A compact card for a file or upload, with media, name, details, progress and actions.

Attachment is an open-source mobile component from suiss/uim for React Native and Expo, with SwiftUI and Jetpack Compose versions built from the same design tokens. The @esuiss/uim CLI copies its source into your project, so you own the code.

iOS
Attachment on iOS in light mode

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

$ pnpm dlx @esuiss/uim@latest add attachment

The CLI also adds what it builds on: Button, Icon, Progress, Text.

Manual

  1. Install the dependencies:
npx expo install cn
  1. 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.

  2. Copy the source into components/ui/attachment.tsx:

uniwind/components/ui/attachment.tsx
import { cn } from "cn"
import * as React from "react"
import { Pressable, View, type ViewProps } from "react-native"
import * as ProgressPrimitive from "@/components/primitives/progress"
import type { RenderProp } from "@/components/primitives/types"
import { resolveClassName, useRender } from "@/components/primitives/use-render"
import { Button, buttonTextVariants } from "@/components/ui/button"
import { IconClassContext } from "@/components/ui/icon"
import {
  ProgressIndicator,
  ProgressTrack,
  ProgressValue,
} from "@/components/ui/progress"
import { Text, TextClassContext } from "@/components/ui/text"

type AttachmentState = "idle" | "uploading" | "processing" | "error" | "done"
  1. Update the import paths to match your project.

Usage

import { Attachment, AttachmentMedia, AttachmentLabel, AttachmentContent, AttachmentTitle, AttachmentDescription, AttachmentProgress, AttachmentActions, AttachmentAction, AttachmentTrigger, AttachmentGroup } from "@/components/ui/attachment"
<Attachment orientation="horizontal" state="done">
  <AttachmentMedia variant="document">
    <AttachmentLabel className="bg-red">pdf</AttachmentLabel>
  </AttachmentMedia>
  <AttachmentContent>
    <AttachmentTitle>Quarterly report.pdf</AttachmentTitle>
    <AttachmentDescription>2.4 MB</AttachmentDescription>
  </AttachmentContent>
  <AttachmentActions>
    <AttachmentAction accessibilityLabel="Remove">
      <Icon as={XIcon} />
    </AttachmentAction>
  </AttachmentActions>
</Attachment>

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.

iOS
Attachment (sizes) on iOS in light mode

States

The idle, uploading, processing, error and done states.

iOS
Attachment (states) on iOS in light mode

Image

An image thumbnail with the image media variant.

iOS
Attachment (image) on iOS in light mode

Vertical

Tiles with orientation="vertical".

iOS
Attachment (vertical) on iOS in light mode

Pressable

A card made pressable with AttachmentTrigger.

iOS
Attachment (pressable) on iOS in light mode

Group

Several attachments in an AttachmentGroup, one of them uploading.

iOS
Attachment (group) on iOS in light mode

File types

Document media with colored extension labels.

iOS
Attachment (file types) on iOS in light mode

API Reference

Attachment

Card that provides state, size and orientation to its parts.

ExtendsViewProps
PropType
About
idle, uploading, processing, error or done. Defaults to done.
Type
AttachmentState
Default
"done"
About
default, sm or xs.
Type
AttachmentSize
Default
"default"
About
horizontal or vertical.
Type
AttachmentOrientation
Default
"horizontal"

AttachmentMedia

Thumbnail area for an icon, document shape or image.

ExtendsViewProps
PropType
About
icon, document or image.
Type
"icon""document""image"
Default
"icon"

AttachmentLabel

Small uppercase tag, such as a file extension.

ExtendsViewProps

AttachmentContent

Column for the title, description and progress.

ExtendsViewProps

AttachmentTitle

File name, one line by default.

ExtendsReact.ComponentProps<typeof Text>

AttachmentDescription

Secondary details, red in the error state.

ExtendsReact.ComponentProps<typeof Text>

AttachmentProgress

Progress bar with a percentage value.

ExtendsReact.ComponentProps<typeof ProgressPrimitive.Root>

AttachmentActions

Row of actions; floats over the media in vertical layout.

ExtendsViewProps

AttachmentAction

Small button sized to the attachment.

ExtendsReact.ComponentProps<typeof Button>

AttachmentTrigger

Pressable overlay that makes the whole card pressable.

ExtendsReact.ComponentProps<typeof Pressable>React.RefAttributes<View>
PropType
Type
RenderProp<Record<string, unknown>, Record<string, never>>
Default
—

AttachmentGroup

List container that joins attachments with separators.

ExtendsViewProps

Accessibility

  • AttachmentProgress has the progressbar role with its value exposed.
  • AttachmentTrigger has the button role; give it an accessibilityLabel such as "Open Invoice.pdf".
  • Icon-only actions need an accessibilityLabel.

Notes

  • Uses bg-surface-secondary, border-separator, bg-accent and text-danger tokens; light and dark follow the system appearance.
  • Separators and action positions use start and end offsets, so they flip in right-to-left layouts.