Task console
Floating progress console for long-running batch operations. Per-item state, auto-dismiss, position-pinned.
TaskConsole is the floating progress panel for long-running multi-item operations — generating 14 pages, syncing 32 records, processing a CSV upload. Pins to a screen corner, shows per-item completion state, and auto-dismisses when all items finish.
For ephemeral confirmations, use Toast. For persistent banners, use Banner. For single-task progress, use ProgressBar.
Use it for
- Batch generation jobs ("Generating 14 pages")
- Multi-record sync or import operations
- Long-running content scrapes or audits
- Any background task that produces multiple discrete sub-results the user benefits from seeing as they complete
Import
import { TaskConsole } from '@brikdesigns/bds';Variants
Default
The console accepts a list of items, each with its own state. As items complete, the console updates in real-time.
import { useState } from 'react';
const [items, setItems] = useState([
{ id: '1', label: 'Generating /home', status: 'pending' },
{ id: '2', label: 'Generating /about', status: 'pending' },
{ id: '3', label: 'Generating /contact', status: 'pending' },
]);
<TaskConsole
isOpen={isRunning}
title="Generating 14 pages"
subtitle="Less than a minute left"
items={items}
onDismiss={() => setIsRunning(false)}
/>Position
Pin to the bottom-right (default) or bottom-left.
<TaskConsole position="bottom-left" {...props} />
<TaskConsole position="bottom-right" {...props} />Default collapsed
Start the console minimized. The user can expand to see per-item state.
<TaskConsole defaultCollapsed {...props} />Auto-dismiss
Set autoDismissDelay (ms) to auto-close the console after all items complete. 0 disables auto-dismiss (user dismisses manually).
<TaskConsole autoDismissDelay={3000} {...props} />Pattern: live batch generation
The canonical pattern — open the console on job start, update items as each completes, auto-dismiss at the end.
async function generatePages(slugs: string[]) {
const items = slugs.map((slug) => ({
id: slug,
label: `Generating /${slug}`,
status: 'pending' as const,
}));
setConsoleState({ isOpen: true, items });
for (const slug of slugs) {
setConsoleState((prev) => ({
...prev,
items: prev.items.map((i) =>
i.id === slug ? { ...i, status: 'in-progress' } : i
),
}));
await generatePage(slug);
setConsoleState((prev) => ({
...prev,
items: prev.items.map((i) =>
i.id === slug ? { ...i, status: 'complete' } : i
),
}));
}
}
<TaskConsole
isOpen={consoleState.isOpen}
title={`Generating ${slugs.length} pages`}
items={consoleState.items}
autoDismissDelay={3000}
onDismiss={() => setConsoleState({ isOpen: false, items: [] })}
/>When not to use
- Don't use TaskConsole for single-task progress. Use ProgressBar — it's the right shape for "one task, % complete."
- Don't use TaskConsole for instantaneous operations. If a job completes in under 1 second, the console flashes uselessly. Use Toast for the completion confirmation.
- Don't run multiple TaskConsoles simultaneously. Pin one at a time; queue subsequent operations or aggregate them in one console.
Accessibility
- Renders a
<div role="status" aria-live="polite">so screen readers announce progress without interrupting current speech. - Per-item state changes are announced as items move from pending → in-progress → complete.
- The collapse / dismiss buttons carry
aria-labels.
API
| Prop | Type | Default |
|---|---|---|
title | ReactNode (required) | — |
items | TaskConsoleItem[] (required) | — |
isOpen | boolean | true |
position | 'bottom-right' | 'bottom-left' | 'bottom-right' |
onDismiss | () => void | — |
defaultCollapsed | boolean | false |
autoDismissDelay | number (ms) | 0 (no auto-dismiss) |
subtitle | ReactNode | — |
The TaskConsoleItem shape is defined alongside the component — typically { id, label, status: 'pending' \| 'in-progress' \| 'complete' \| 'error' }.
Related
- ProgressBar — single-task alternative
- Toast — short-confirmation alternative
- NotificationList — for completed-task review after the fact
- Storybook playground