Skip to content
Components

Upload queue

Keep individual file progress, errors and cancellation visible. The caller owns the transfer.

TS
import { … } from "@fungi.computer/caps/blocks/upload-queue";

Hero

TSX
import {
UploadQueue,
type UploadQueueItem,
} from "@fungi.computer/caps/blocks/upload-queue";
const thumbnail = `data:image/svg+xml,${encodeURIComponent(
'<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32"><rect width="32" height="32" fill="#8a6d3b"/></svg>',
)}`;
const items: UploadQueueItem[] = [
{
id: "1",
name: "spore-print-01.jpg",
preview: { kind: "image", url: thumbnail },
progress: 62,
progressLabel: "62%",
statusLabel: "Uploading",
actions: {
cancel: { label: "Cancel", accessibleLabel: "Cancel spore-print-01.jpg" },
},
},
{
id: "2",
name: "field-notes.pdf",
preview: { kind: "file" },
progress: 100,
progressLabel: "Done",
statusLabel: "Uploaded",
actions: {
remove: { label: "Remove", accessibleLabel: "Remove field-notes.pdf" },
},
},
{
id: "3",
name: "cluster-02.jpg",
preview: { kind: "file" },
progress: null,
progressLabel: "",
statusLabel: "Upload failed",
alert: "Network error.",
actions: {
retry: { label: "Retry", accessibleLabel: "Retry cluster-02.jpg" },
},
},
];
export default function Hero() {
return (
<UploadQueue
className="w-full max-w-sm"
items={items}
onCancel={() => {
/* This specimen has no host action. */
}}
onRemove={() => {
/* This specimen has no host action. */
}}
onRetry={() => {
/* This specimen has no host action. */
}}
/>
);
}

Interactive

TSX
import {
UploadQueue,
type UploadQueueItem,
} from "@fungi.computer/caps/blocks/upload-queue";
import { useState } from "react";
const initial: UploadQueueItem[] = [
{
id: "1",
name: "harvest-log.csv",
preview: { kind: "file" },
progress: 40,
progressLabel: "40%",
statusLabel: "Uploading",
actions: {
cancel: { label: "Cancel", accessibleLabel: "Cancel harvest-log.csv" },
},
},
{
id: "2",
name: "notes.txt",
preview: { kind: "file" },
progress: 100,
progressLabel: "Done",
statusLabel: "Uploaded",
actions: {
remove: { label: "Remove", accessibleLabel: "Remove notes.txt" },
},
},
];
export default function Interactive() {
const [items, setItems] = useState(initial);
const remove = (id: string) => {
setItems((rows) => rows.filter((row) => row.id !== id));
};
return (
<UploadQueue
className="w-full max-w-sm"
items={items}
onCancel={remove}
onRemove={remove}
onRetry={() => {
/* This specimen has no host action. */
}}
/>
);
}