Progress

Progress bar component for showing completion status.

import { Progress } from "ui-lab-components";
 
export function Example() {
  return <Progress value={60} />;
}

File Upload

Simulated upload progress with a label and live percentage — starts on button click.

report-q4-2025.pdf
Uploading0%
"use client";
 
import { useState, useEffect } from 'react';
import { Progress, Flex, Button } from 'ui-lab-components';
 
export const metadata = {
  title: 'File Upload',
  description: 'Simulated upload progress with a label and live percentage — starts on button click.',
  access: 'free' as const,
};
 
export default function Example() {
  const [progress, setProgress] = useState(0);
  const [running, setRunning] = useState(false);
 
  useEffect(() => {
    if (!running) return;
    if (progress >= 100) { setRunning(false); return; }
    const t = setTimeout(() => setProgress((p) => Math.min(p + Math.random() * 12, 100)), 200);
    return () => clearTimeout(t);
  }, [running, progress]);
 
  const reset = () => { setProgress(0); setRunning(false); };
 
  return (
    <Flex direction="column" gap="md" style={{ width: 340 }}>
      <Flex direction="column" gap="xs">
        <span style={{ fontSize: "var(--text-sm)", var(--foreground-muted)" }}>
          report-q4-2025.pdf
        </span>
        <Progress value={progress} label="Uploading" showValue />
      </Flex>
      <Flex gap="sm">
        <Button variant="primary" onClick={() => setRunning(true)} disabled={running || progress === 100}>
          {progress === 100 ? "Done" : "Upload"}
        </Button>
        <Button variant="ghost" onClick={reset}>Reset</Button>
      </Flex>
    </Flex>
  );
}
 

Storage Quota

Fixed progress bar showing disk usage relative to a custom max value.

Storage74%
7.4 GB of 10 GB used
import { Progress, Flex } from 'ui-lab-components';
 
export const metadata = {
  title: 'Storage Quota',
  description: 'Fixed progress bar showing disk usage relative to a custom max value.',
  access: 'free' as const,
};
 
const used = 7.4;
const total = 10;
 
export default function Example() {
  return (
    <Flex direction="column" gap="md" style={{ width: 300 }}>
      <Flex direction="column" gap="xs">
        <Progress value={used} max={total} label="Storage" showValue />
        <span style={{ fontSize: "var(--text-xs)", var(--foreground-muted)" }}>
          {used} GB of {total} GB used
        </span>
      </Flex>
    </Flex>
  );
}
 

Onboarding Steps

Step tracker using value/max to represent wizard completion.

Step 1 of 4Profile
"use client";
 
import { useState } from 'react';
import { Progress, Flex, Button } from 'ui-lab-components';
 
export const metadata = {
  title: 'Onboarding Steps',
  description: 'Step tracker using value/max to represent wizard completion.',
  access: 'free' as const,
};
 
const steps = ["Profile", "Preferences", "Integrations", "Invite team"];
 
export default function Example() {
  const [step, setStep] = useState(1);
 
  return (
    <Flex direction="column" gap="md" style={{ width: 340 }}>
      <Flex direction="column" gap="xs">
        <Progress value={step} max={steps.length} />
        <span style={{ fontSize: "var(--text-sm)", var(--foreground-muted)" }}>
          Step {step} of {steps.length} — {steps[step - 1]}
        </span>
      </Flex>
      <Flex gap="sm">
        <Button variant="ghost" onClick={() => setStep((s) => Math.max(1, s - 1))} disabled={step === 1}>
          Back
        </Button>
        <Button variant="primary" onClick={() => setStep((s) => Math.min(steps.length, s + 1))} disabled={step === steps.length}>
          Next
        </Button>
      </Flex>
    </Flex>
  );
}
 

Indeterminate Loading

Animated bar for unknown-duration operations — switches to complete when done.

Fetching results…
"use client";
 
import { useState, useEffect } from 'react';
import { Progress, Flex, Button } from 'ui-lab-components';
 
export const metadata = {
  title: 'Indeterminate Loading',
  description: 'Animated bar for unknown-duration operations — switches to complete when done.',
  access: 'free' as const,
};
 
export default function Example() {
  const [loading, setLoading] = useState(true);
 
  useEffect(() => {
    if (!loading) return;
    const t = setTimeout(() => setLoading(false), 3000);
    return () => clearTimeout(t);
  }, [loading]);
 
  return (
    <Flex direction="column" gap="md" style={{ width: 320 }}>
      <Flex direction="column" gap="xs">
        <span style={{ fontSize: "var(--text-sm)", var(--foreground-muted)" }}>
          {loading ? "Fetching results…" : "Results loaded"}
        </span>
        <Progress indeterminate={loading} value={loading ? 0 : 100} />
      </Flex>
      <Button variant="ghost" onClick={() => setLoading(true)} disabled={loading}>
        Reload
      </Button>
    </Flex>
  );
}
 

Skill Levels

Stacked progress bars in a profile or stats context with labels and values.

TypeScript92%
Rust54%
Go38%
import { Progress, Flex } from 'ui-lab-components';
 
export const metadata = {
  title: 'Skill Levels',
  description: 'Stacked progress bars in a profile or stats context with labels and values.',
  access: 'free' as const,
};
 
const skills = [
  { name: "TypeScript", value: 92 },
  { name: "Rust", value: 54 },
  { name: "Go", value: 38 },
];
 
export default function Example() {
  return (
    <Flex direction="column" gap="sm" style={{ width: 300 }}>
      {skills.map((s) => (
        <Progress key={s.name} value={s.value} label={s.name} showValue />
      ))}
    </Flex>
  );
}
 
UI Lab