UploadQueueModal
A floating modal docked in the bottom-right corner of the screen that tracks ongoing file uploads. Mimics the behavior of Google Drive's upload progress widget with minimize/expand transitions.
Preview
Usage
"use client";
import { UploadQueueModal } from '@photonix/ultimate';
const files = [
{ id: '1', name: 'brand-assets.zip', size: 4_200_000, status: 'uploading' as const, progress: 64 },
{ id: '2', name: 'cover.png', size: 820_000, status: 'success' as const, progress: 100 },
{ id: '3', name: 'brief.pdf', size: 380_000, status: 'pending' as const, progress: 0 },
];
export default function UploadQueueModalBasicExample() {
return <UploadQueueModal open files={files} title="Uploading 3 items" />;
}Component API
UploadQueueModal
Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | - | Whether the modal is open |
onClose | (() => void) | - | Callback when the modal is closed |
files | UploadQueueItem[] | [] | List of files in the upload queue |
onCancelItem | ((id: string) => void) | - | Callback when a file is cancelled/removed |
title | string | - | Optional title to override the auto-generated one |
defaultMinimized | boolean | false | Whether the modal should start minimized |
className | string | - | Additional class name |
Variants
Basic Queue
Displays the upload queue in various states (Uploading, Success, Error, Pending).
Basic Queue
"use client";
import { useState } from 'react';
import { Button, Flex, UploadQueueModal, type UploadQueueItem } from '@photonix/ultimate';
export default function UploadQueueModalBasicQueueExample() {
const [open, setOpen] = useState(false);
const [files, setFiles] = useState<UploadQueueItem[]>([
{ id: '1', name: 'quarterly_report.pdf', size: 5242880, status: 'success', progress: 100 },
{ id: '2', name: 'corporate_video.mp4', size: 104857600, status: 'uploading', progress: 45 },
{ id: '3', name: 'unsupported_archive.rar', size: 26214400, status: 'error', progress: 0, error: 'File size limit exceeded' },
{ id: '4', name: 'profile_picture.png', size: 1572864, status: 'pending', progress: 0 },
]);
return (
<Flex gap="md">
<Button onClick={() => setOpen(true)}>Open Static Queue</Button>
<UploadQueueModal open={open} onClose={() => setOpen(false)} files={files} onCancelItem={(id) => setFiles((prev) => prev.filter((f) => f.id !== id))} />
</Flex>
);
}Interactive Simulator
Trigger mock uploads in real-time. Files progress automatically and show success/error states.
Interactive Simulator
"use client";
import { useState } from 'react';
import { Button, Flex, UploadQueueModal, type UploadQueueItem } from '@photonix/ultimate';
export default function UploadQueueModalInteractiveExample() {
const [open, setOpen] = useState(false);
const [files, setFiles] = useState<UploadQueueItem[]>([]);
const simulateUpload = (id: string) => {
setFiles((prev) => prev.map((f) => f.id === id ? { ...f, status: 'uploading' } : f));
let progress = 0;
const interval = setInterval(() => {
progress += Math.floor(Math.random() * 15) + 5;
if (progress >= 100) {
progress = 100;
clearInterval(interval);
setFiles((prev) => prev.map((f) => {
if (f.id === id) {
const isError = f.name.includes('corrupted');
return { ...f, status: isError ? 'error' : 'success', progress: 100, error: isError ? 'Forbidden file signature detected' : undefined };
}
return f;
}));
} else {
setFiles((prev) => prev.map((f) => f.id === id ? { ...f, progress } : f));
}
}, 200);
};
const handleAddUploads = () => {
setOpen(true);
const newItems: UploadQueueItem[] = [
{ id: Math.random().toString(36).slice(2), name: 'spreadsheet_data.xlsx', size: 327680, status: 'pending', progress: 0 },
{ id: Math.random().toString(36).slice(2), name: 'project_intro.mov', size: 52428800, status: 'pending', progress: 0 },
{ id: Math.random().toString(36).slice(2), name: 'corrupted_archive.7z', size: 15728640, status: 'pending', progress: 0 },
];
setFiles((prev) => [...prev, ...newItems]);
newItems.forEach((item, index) => setTimeout(() => simulateUpload(item.id), index * 800));
};
return (
<Flex gap="md" align="center">
<Button onClick={() => setOpen(true)}>Open Upload Queue</Button>
<Button variant="secondary" onClick={handleAddUploads}>Simulate New Uploads</Button>
{files.length > 0 && <Button variant="tertiary" onClick={() => setFiles([])}>Clear Queue</Button>}
<UploadQueueModal open={open} onClose={() => setOpen(false)} files={files} onCancelItem={(id) => setFiles((prev) => prev.filter((f) => f.id !== id))} />
</Flex>
);
}Minimized Default
Open the upload status panel minimized by default (showing only the header at the bottom-right).
Minimized Default
"use client";
import { useState } from 'react';
import { Button, Flex, UploadQueueModal, type UploadQueueItem } from '@photonix/ultimate';
const files: UploadQueueItem[] = [
{ id: '1', name: 'minimized_upload.docx', size: 1024 * 128, status: 'uploading', progress: 30 },
];
export default function UploadQueueModalMinimizedExample() {
const [open, setOpen] = useState(false);
return (
<Flex gap="md">
<Button onClick={() => setOpen(true)}>Open Minimized Queue</Button>
<UploadQueueModal open={open} onClose={() => setOpen(false)} files={files} defaultMinimized />
</Flex>
);
}On this page
Preview
Component API
Variants
Basic Queue
Interactive Simulator
Minimized Default