@biem/ui

Attachment

A compact card that shows users an attached file and the state of its upload.

An attachment presents a file with an icon or a thumbnail, a title and a description, and it can carry actions such as removing the file. Its state follows the upload, so users see whether a file is waiting, in progress, failed or complete.

Delivery note 4812.pdfPDF · 248 KB

Usage

attachment-default.tsx
import {
	Attachment,
	AttachmentAction,
	AttachmentActions,
	AttachmentContent,
	AttachmentDescription,
	AttachmentMedia,
	AttachmentTitle,
} from "@biem/ui/components/ui/attachment";
import { IconFileText, IconX } from "@tabler/icons-react";

export function AttachmentDefault() {
	return (
		<Attachment>
			<AttachmentMedia>
				<IconFileText stroke={1.5}/>
			</AttachmentMedia>
			<AttachmentContent>
				<AttachmentTitle>Delivery note 4812.pdf</AttachmentTitle>
				<AttachmentDescription>PDF · 248 KB</AttachmentDescription>
			</AttachmentContent>
			<AttachmentActions>
				<AttachmentAction aria-label="Remove delivery note">
					<IconX stroke={1.5}/>
				</AttachmentAction>
			</AttachmentActions>
		</Attachment>
	);
}

Examples

Horizontal

Invoices and price lists are usually recognized by their name. With orientation set to "horizontal", which is also the default, the media sits beside the name and the details of the file, so users identify the file at a glance by its name.

Delivery note 4812.pdfPDF · 248 KB

Vertical

Photos and scans say more through their content than through their name. Set to "vertical", orientation places the media above the name and gives it the full width of the attachment, so users recognize a picture before they read anything.

Delivery note 4812.pdfPDF · 248 KB

Extra Small

Space is scarce where files travel along with a message, for example in the input of a conversation. At size "xs", an attachment claims the least room, so the text that users write stays in the foreground.

Delivery note 4812.pdfPDF · 248 KB

Small

Side panels and comment threads show files beside content that matters more. An attachment with size set to "sm" keeps the file recognizable in less space, so it does not outweigh that content.

Delivery note 4812.pdfPDF · 248 KB

Default Size

In forms and upload areas, users check each file before they submit it. Unless a size is set, an attachment takes the size "default", so files keep one scale across every product.

Delivery note 4812.pdfPDF · 248 KB

Icon Media

Spreadsheets and text documents rarely offer a picture that tells them apart. For such files, the media holds an icon with variant set to "icon", its default, and users identify the file by its name and details.

Delivery note 4812.pdfPDF · 248 KB

Image Media

Pictures from the shop floor carry information that no file name can, such as the condition of a delivery. With variant set to "image", the picture fills the media and stays muted while the file is still uploading or being processed or after it has failed, so users tell a ready photo from one that is not.

Shelf photo aisle 4.jpgJPG · 1.2 MB

With Trigger

Users often check a file before they send it or work with it. Placed inside the attachment, AttachmentTrigger turns its whole surface into one target for the pointer and the keyboard, for example to open a preview. The actions keep responding on their own, so removing a file never opens it by mistake.

Delivery note 4812.pdfPDF · 248 KB

Some files already have an address of their own, such as a document in the archive. Through render, the trigger becomes a real link to that address, so users can open the file in a new tab or pass the link on.

Delivery note 4812.pdfPDF · 248 KB

Group

A message or a form often carries several files at once. Inside AttachmentGroup they share one row that users scroll sideways once it runs out of width, and scrolling comes to rest at the start of a file rather than in the middle of one.

Delivery note 4812.pdfPDF · 248 KB
Transfer list week 42.xlsxXLSX · 86 KB
Supplier invoice 2209.pdfPDF · 312 KB
Return slip 0731.pdfPDF · 94 KB

Uploading

While a file is on its way, users should not mistake it for a complete one. With state set to "uploading", the attachment signals ongoing work, and users see at once which files are still in transfer.

Delivery note 4812.pdfUploading · 64%

Processing

Once a file has arrived, the system often has to read or check it before users can work with it. Set to "processing", state keeps the activity visible through that step, so the file stays marked as not ready although its transfer has finished.

Delivery note 4812.pdfReading line items

Error

An upload can fail, for example when the connection drops. Marked with state set to "error", the attachment shows the failure on the file itself, so users find it among the others and decide what to do with it.

Delivery note 4812.pdfUpload failed

Done

Finished files are ready for whatever users do next, such as sending them with a message. Nothing about the attachment signals work in progress once state is set to "done". This value is also the default, so an attachment without a state of its own counts as finished.

Delivery note 4812.pdfPDF · 248 KB

Disabled Action

Removing a file is sometimes not possible, for example while the form that carries it is being submitted. An action marked as disabled accepts no interaction and exposes its state to assistive technology, while the pointer shows users that the action is unavailable for now.

Delivery note 4812.pdfPDF · 248 KB

API Reference

Attachment

Propstate
Type"idle" | "uploading" | "processing" | "error" | "done"
Default"done"
DescriptionSets the stage of the upload. Idle draws a dashed border, uploading and processing animate the title, and error colors the border, the media and the description as destructive.
Propsize
Type"default" | "sm" | "xs"
Default"default"
DescriptionControls the padding, gap and text size of the attachment and the width of its media.
Proporientation
Type"horizontal" | "vertical"
Default"horizontal"
DescriptionControls the layout. Horizontal places the media beside the content, vertical stacks the media above the content and moves the actions to the top right corner.

AttachmentMedia

Propvariant
Type"icon" | "image"
Default"icon"
DescriptionSets the kind of media. Icon centers an icon on a muted background. Image fits a child img to the square and dims it while the state is uploading, processing or error.

AttachmentContent

AttachmentContent has no props of its own. It accepts the props of a native div.

AttachmentTitle

AttachmentTitle has no props of its own. It accepts the props of a native span.

AttachmentDescription

AttachmentDescription has no props of its own. It accepts the props of a native span.

AttachmentActions

AttachmentActions has no props of its own. It accepts the props of a native div.

AttachmentAction

Propvariant
Type"default" | "outline" | "secondary" | "ghost" | "destructive" | "link"
Default"ghost"
DescriptionControls the visual emphasis and semantic role of the action.
Propsize
Type"default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg"
Default"icon-xs"
DescriptionControls the action dimensions and spacing.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the action with another component.
PropnativeButton
Typeboolean
Defaulttrue
DescriptionDeclares whether the rendered element is a native button. Set it to false when render returns a different element.
Propdisabled
Typeboolean
Defaultfalse
DescriptionPrevents interaction and exposes the disabled state to assistive technology.
PropfocusableWhenDisabled
Typeboolean
Defaultfalse
DescriptionKeeps the action in the tab order while it is disabled, so keyboard users can still reach it.

AttachmentTrigger

Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native button or composes the trigger with another component, such as a link.
Proptype
Type"submit" | "reset" | "button"
Default"button"
DescriptionSets the type of the native button. With render, the trigger passes type on only when it is set.

AttachmentGroup

AttachmentGroup has no props of its own. It accepts the props of a native div.