CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-top-loading-bar

A highly customizable React top-loading bar component with hook-based, ref-based, and state-based control patterns.

64

1.25x
Overview
Eval results
Files

state-based-control.mddocs/

State-based Control

The state-based approach uses the controlled component pattern, where you manage the progress state in your component and pass it to the LoadingBar as a prop. This provides React-style declarative control over the loading bar.

Basic Setup

Control the loading bar by managing progress state:

import React, { useState } from "react";
import LoadingBar from "react-top-loading-bar";

const App = () => {
  const [progress, setProgress] = useState(0);

  return (
    <div>
      <LoadingBar
        color="#f11946"
        progress={progress}
        onLoaderFinished={() => setProgress(0)}
      />
      <button onClick={() => setProgress(100)}>Complete</button>
    </div>
  );
};

LoadingBar Props for State Control

interface IProps {
  // State Control
  progress?: number;
  onLoaderFinished?: () => void;
  
  // Visual Properties
  color?: string;
  background?: string;
  height?: number;
  shadow?: boolean;
  className?: string;
  containerClassName?: string;
  style?: CSSProperties;
  containerStyle?: CSSProperties;
  shadowStyle?: CSSProperties;
  
  // Animation Timing
  loaderSpeed?: number;
  transitionTime?: number;
  waitingTime?: number;
}

Key Props

/**
 * Current progress value (0-100)
 */
progress?: number;

/**
 * Callback fired when loading animation completes
 * Called after the bar reaches 100% and fade animation finishes
 */
onLoaderFinished?: () => void;

Usage Examples

Simple Progress Control

const SimpleProgress = () => {
  const [progress, setProgress] = useState(0);

  const handleStart = () => setProgress(20);
  const handleIncrease = () => setProgress(prev => Math.min(prev + 20, 100));
  const handleComplete = () => setProgress(100);

  return (
    <div>
      <LoadingBar
        color="blue"
        progress={progress}
        onLoaderFinished={() => setProgress(0)}
      />
      <button onClick={handleStart}>Start (20%)</button>
      <button onClick={handleIncrease}>+20%</button>
      <button onClick={handleComplete}>Complete</button>
    </div>
  );
};

API Loading State

const ApiExample = () => {
  const [progress, setProgress] = useState(0);
  const [loading, setLoading] = useState(false);

  const fetchData = async () => {
    setLoading(true);
    setProgress(10);

    try {
      // Start request
      setProgress(30);
      const response = await fetch("/api/data");
      
      // Processing
      setProgress(70);
      const data = await response.json();
      
      // Complete
      setProgress(100);
    } catch (error) {
      setProgress(100); // Complete on error too
    } finally {
      setLoading(false);
    }
  };

  return (
    <div>
      <LoadingBar
        color="green"
        progress={progress}
        onLoaderFinished={() => setProgress(0)}
      />
      <button onClick={fetchData} disabled={loading}>
        {loading ? "Loading..." : "Fetch Data"}
      </button>
    </div>
  );
};

Form Submission Progress

const FormSubmission = () => {
  const [progress, setProgress] = useState(0);
  const [formData, setFormData] = useState({ name: "", email: "" });

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    
    // Validation
    setProgress(20);
    await new Promise(resolve => setTimeout(resolve, 300));
    
    // Submit
    setProgress(50);
    await fetch("/api/submit", {
      method: "POST",
      body: JSON.stringify(formData),
    });
    
    // Processing
    setProgress(80);
    await new Promise(resolve => setTimeout(resolve, 500));
    
    // Complete
    setProgress(100);
  };

  return (
    <div>
      <LoadingBar
        color="purple"
        progress={progress}
        onLoaderFinished={() => {
          setProgress(0);
          alert("Form submitted successfully!");
        }}
      />
      <form onSubmit={handleSubmit}>
        <input
          value={formData.name}
          onChange={(e) => setFormData(prev => ({ ...prev, name: e.target.value }))}
          placeholder="Name"
        />
        <input
          value={formData.email}
          onChange={(e) => setFormData(prev => ({ ...prev, email: e.target.value }))}
          placeholder="Email"
        />
        <button type="submit">Submit</button>
      </form>
    </div>
  );
};

Multi-step Process

const MultiStepProcess = () => {
  const [progress, setProgress] = useState(0);
  const [currentStep, setCurrentStep] = useState(0);

  const steps = [
    { name: "Initialize", progress: 10 },
    { name: "Validate", progress: 30 },
    { name: "Process", progress: 60 },
    { name: "Finalize", progress: 90 },
    { name: "Complete", progress: 100 },
  ];

  const executeStep = async (stepIndex: number) => {
    setCurrentStep(stepIndex);
    setProgress(steps[stepIndex].progress);
    
    // Simulate step execution
    await new Promise(resolve => setTimeout(resolve, 1000));
    
    if (stepIndex < steps.length - 1) {
      executeStep(stepIndex + 1);
    }
  };

  return (
    <div>
      <LoadingBar
        color="orange"
        progress={progress}
        onLoaderFinished={() => {
          setProgress(0);
          setCurrentStep(0);
        }}
      />
      <p>Current Step: {steps[currentStep]?.name}</p>
      <button onClick={() => executeStep(0)}>Start Process</button>
    </div>
  );
};

File Upload with Progress

const FileUpload = () => {
  const [progress, setProgress] = useState(0);

  const uploadFile = (file: File) => {
    const formData = new FormData();
    formData.append("file", file);

    const xhr = new XMLHttpRequest();

    // Track upload progress
    xhr.upload.addEventListener("progress", (e) => {
      if (e.lengthComputable) {
        const percentComplete = (e.loaded / e.total) * 100;
        setProgress(percentComplete);
      }
    });

    xhr.onload = () => {
      setProgress(100);
    };

    xhr.open("POST", "/upload");
    xhr.send(formData);
  };

  return (
    <div>
      <LoadingBar
        color="red"
        progress={progress}
        onLoaderFinished={() => setProgress(0)}
      />
      <input
        type="file"
        onChange={(e) => e.target.files?.[0] && uploadFile(e.target.files[0])}
      />
    </div>
  );
};

Visual Customization

Customize appearance through props:

<LoadingBar
  progress={progress}
  color="#ff6b6b"
  height={4}
  shadow={true}
  background="rgba(255,255,255,0.1)"
  loaderSpeed={300}
  transitionTime={200}
  waitingTime={500}
  className="custom-loader"
  containerClassName="custom-container"
  style={{ borderRadius: "2px" }}
  onLoaderFinished={() => console.log("Done!")}
/>

Important Notes

  • Progress Range: Progress values should be between 0 and 100
  • Auto Reset: Use onLoaderFinished callback to reset progress to 0 after completion
  • Smooth Transitions: The loading bar automatically animates between progress values
  • Complete State: Setting progress to 100 triggers the completion animation
  • No Conflicts: Do not use progress prop with ref methods simultaneously

Install with Tessl CLI

npx tessl i tessl/npm-react-top-loading-bar

docs

hook-based-control.md

index.md

ref-based-control.md

state-based-control.md

tile.json