tasting-notes.pdf
roast-log.csv
farm-visit.mov
'use client';
import { useEffect, useState } from 'react';
import { Attachment } from '@brand-studio/ui';
export default function AttachmentDemo() {
const [progress, setProgress] = useState(0);
const [failed, setFailed] = useState(true);
const [files, setFiles] = useState(['tasting-notes.pdf', 'roast-log.csv']);
useEffect(() => {
if (progress >= 100) return;
const timer = setTimeout(() => setProgress(value => Math.min(100, value + 7)), 180);
return () => clearTimeout(timer);
}, [progress]);
return (
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 10, justifyContent: 'center' }}>
{files.includes('tasting-notes.pdf') && <Attachment name="tasting-notes.pdf" size="240 KB" progress={progress} onRemove={() => setFiles(list => list.filter(file => file !== 'tasting-notes.pdf'))} />}
{files.includes('roast-log.csv') && <Attachment name="roast-log.csv" size="18 KB" onRemove={() => setFiles(list => list.filter(file => file !== 'roast-log.csv'))} />}
<Attachment name="farm-visit.mov" size="1.2 GB" error={failed ? 'Too large to upload' : undefined} progress={failed ? undefined : 30} onRetry={() => setFailed(false)} />
</div>
);
}Installation
pnpm add @brand-studio/uinpm install @brand-studio/uiyarn add @brand-studio/uibun add @brand-studio/uiInstall the peer dependencies
npm install react react-domImport the stylesheet once
import '@brand-studio/ui/styles.css';Wrap your app in a brand theme
import { BrandTheme, Attachment } from '@brand-studio/ui'; import brand from './brand.json'; <BrandTheme palette={brand.tokens} mode="system"> {/* your app */} </BrandTheme>
Usage
import { Attachment } from '@brand-studio/ui';<Attachment name="tasting-notes.pdf" size="240 KB" progress={progress} onRemove={remove} />
<Attachment name="farm-visit.mov" error="Too large to upload" onRetry={retry} onRemove={remove} />Pass progress from 0 to 100 while the file uploads; at 100 or unset, the size shows. preview takes an image URL for a thumbnail; otherwise the file type shows. An error replaces the size and, with onRetry, adds a retry button.
Accessibility
- Remove and retry name the file: "Remove tasting-notes.pdf".
- Upload progress is a labelled progress bar, and an error is announced when it appears.
API Reference
| Prop | Type | Default |
|---|---|---|
name | string | – |
size? | string | – |
preview? | string | – |
progress? | number | – |
error? | string | – |
onRemove? | (() => void) | – |
onRetry? | (() => void) | – |
className? | string | '' |