@bikiran/flow-progress
v2.1.1
Published
Self-polling progress tracker for long-running background operations. Configurable, placement-agnostic, and ready for any Next.js project.
Readme
@bikiran/flow-progress
Self-polling progress tracker for long-running background operations. Configurable fetcher, placement-agnostic, zero Tailwind / CSS required — uses inline styles only.
Installation
npm install @bikiran/flow-progress
# or
yarn add @bikiran/flow-progressPeer Dependencies
| Package | Version |
| -------------- | ---------------------- |
| react | ^18.0.0 \|\| ^19.0.0 |
| react-dom | ^18.0.0 \|\| ^19.0.0 |
| lucide-react | >=0.300.0 |
Usage
The component fetches progress data automatically using the native fetch API. Point it at your
backend with baseUrl and it builds ${baseUrl}/api/bikiran-engine/runs/{flowId}/progress internally.
No custom fetcher function is required.
Basic Example
"use client";
import { FlowProgress } from "@bikiran/flow-progress";
export default function MyPage() {
const [flowId, setFlowId] = useState<string | null>(null);
const [flowTitle, setFlowTitle] = useState<string | null>(null);
return (
<FlowProgress
baseUrl="https://api.example.com"
flowId={flowId}
flowTitle={flowTitle}
successMessage="Operation completed successfully."
failedMessage="Operation failed."
onSuccess={() => console.log("Done!")}
onFinish={() => {
setFlowId(null);
setFlowTitle(null);
}}
/>
);
}With All Options
<FlowProgress
baseUrl="https://api.example.com"
flowId={flowId}
flowTitle="Deploying instance"
variant="sidebar"
colorScheme="indigo"
progressBar
interval={3000}
successMessage="Deployment complete."
failedMessage="Deployment failed."
onSuccess={() => reload()}
onFailed={() => notifyAdmin()}
onFinish={() => setFlowId(null)}
/>Compact Inline
<FlowProgress
baseUrl="https://api.example.com"
flowId={flowId}
flowTitle="Processing"
variant="compact"
colorScheme="slate"
successMessage="Done."
failedMessage="Failed."
onFinish={() => setFlowId(null)}
/>Props
| Prop | Type | Default | Required | Description |
| ---------------- | -------------------------- | ----------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| baseUrl | string | — | Yes | Base URL of the progress API. The component builds and fetches {baseUrl}/api/bikiran-engine/runs/{flowId}/progress internally. |
| flowTitle | string \| null | — | Yes | Title displayed while running. Combined with flowId to control visibility. |
| flowId | string \| null | — | Yes | UUID for the flow. Component becomes visible when both flowId and flowTitle are non-null. |
| successMessage | string | — | Yes | Text shown in the completed state. |
| failedMessage | string | — | Yes | Text shown in the failed state. |
| interval | number (ms) | 5000 | No | Polling interval in milliseconds. |
| progressBar | boolean | false | No | Show animated progress bar. Not shown for compact and banner variants. |
| variant | TFlowProgressVariant | "default" | No | Layout variant — see table below. |
| colorScheme | TFlowProgressColorScheme | "blue" | No | Color theme: blue, slate, indigo, minimal. |
| onSuccess | () => void | — | No | Called once when status reaches "completed". |
| onFailed | () => void | — | No | Called once when status reaches "failed". |
| onFinish | () => void | — | No | Called when the user clicks the dismiss button. |
Variants
| Variant | Description |
| --------- | ------------------------------------------------------ |
| default | Rounded card, auto width -- general purpose |
| compact | Single slim row (48 px) -- inline in tables / toolbars |
| wide | Full-width block -- main content area, page sections |
| sidebar | Vertical stacked layout -- right/left drawer panels |
| modal | Centred, padded -- inside a modal/dialog body |
| banner | Full-width horizontal strip -- top/bottom of a page |
API Response Format
The endpoint must return JSON in this envelope shape:
// GET {baseUrl}/api/bikiran-engine/runs/{flowId}/progress
{
error: false,
data: TFlowProgressData
}When error is true the component treats the response as a fetch failure and retries on the next interval.
TFlowProgressData Shape
type TFlowProgressData = {
serviceId: string;
status: "pending" | "running" | "completed" | "failed" | "cancelled";
totalNodes: number;
completedNodes: number;
totalApproxMs: number;
completedApproxMs: number;
weightedProgressPercent: number;
liveProgressPercent: number;
currentProgressMessage: string | null;
currentTime: number;
flowStartedAt: number;
currentNodeStartedAt: number;
};Behavior
- Component renders nothing when
flowIdorflowTitleisnull. - When both become non-null the component appears and starts polling the progress endpoint using the native
fetchAPI. - Polling continues at
intervalms until a terminal status (completed,failed,cancelled) is received. - On terminal status the corresponding callback (
onSuccess/onFailed) fires once. - The component stays visible with the result until the user clicks the dismiss button, which triggers
onFinish. - On a network error or when the response has
error: true, the component shows a retry message and continues polling.
Source Structure
src/
+-- index.tsx # Single public entry point
+-- types.ts # All public TypeScript types
+-- constants.ts # TERMINAL_STATUSES, NO_BAR_VARIANTS, INLINE_VARIANTS
+-- colors.ts # TColorTokens type + COLOR_MAP record
+-- styles.ts # BASE_STYLE + VARIANT_STYLES record
+-- keyframes.ts # injectKeyframes() -- DOM side-effect
+-- hooks/
| +-- useFlowPolling.ts # Custom polling hook
+-- FlowProgress.tsx # State shell -- calls hook, renders <FlowProgressView>
+-- components/
+-- FlowProgressView.tsx # Layout scaffold -- overlay, title, rows, progress bar
+-- Spinner.tsx # Animated ring
+-- StatusIconWrap.tsx # Circular icon container
+-- ProgressBar.tsx # Animated fill bar
+-- CloseButton.tsx # Dismiss button
+-- BodyContent.tsx # Status-aware body rendererInternal components are not exported from index.tsx -- the only public surface is
FlowProgress and the TypeScript types.
License
MIT
