The Fluxbit::ProgressComponent is a customizable progress bar component that extends Fluxbit::Component. It allows you to create progress indicators with various styles, sizes, colors, and label positioning options to display completion status or loading progress.
To start using the progress component you can use the default way to call the component:
<%= render Fluxbit::ProgressComponent.new(progress: 45) %>
<!-- or -->
<%= render Fluxbit::ProgressComponent.new do %>
<!-- Progress bars don't typically have block content -->
<% end %>
or you can use the alias (from the helpers):
<%= fx_progress(progress: 45) %>
<!-- With labels -->
<%= fx_progress(progress: 75, text_label: "Loading", label_progress: true, label_text: true) %>
<!-- With custom label styling -->
<%= fx_progress(progress: 60, text_label: "Upload", label_text: true, label_html: { class: "font-bold text-green-600" }) %>
The result is:
Options
| Param | Default | Description |
|---|---|---|
| progress: | 0 | The progress percentage (0-100). Values outside this range are automatically clamped. |
| color: | :default | Sets the color scheme of the progress bar (default, dark, blue, red, green, yellow, indigo, purple, cyan, gray, lime, pink, teal). |
| size: | 1 | Specifies the size of the progress bar (0 to 3: sm, md, lg, xl). |
| text_label: | nil | Label text to display with the progress bar. |
| label_progress: | false | Whether to show the progress percentage as a label. |
| label_text: | false | Whether to show the text label. |
| progress_label_position: | :inside | Position of the progress percentage label (:inside or :outside). |
| text_label_position: | :outside | Position of the text label (:inside or :outside). |
| label_html: | {} | HTML attributes for label elements. Supports :remove_class to customize label styling. |
| stimulus: | false | Whether to add Stimulus controller data attributes for JavaScript interactions. |
| remove_class: | ”” | Classes to be removed from the default class list. |
| **props | Additional HTML attributes. |
Slots
This component does not define any named slots. The progress bar displays the completion percentage based on the progress parameter and optional labels.
Examples
Default progress bars
Progress colors
Progress sizes
Progress with outside labels
Progress with inside labels
Progress with mixed label positions
Adding/Removing classes
Adding other properties
Interactive JavaScript controls
When to use
Use Progress whenever you need to display completion status, loading progress, or any metric that can be represented as a percentage. It’s ideal for file uploads, form completion, data processing, or any task with measurable progress.
Text Label Sizing
The component automatically adjusts text size and padding based on the progress bar size:
- Size 0-1 (Small/Medium): Uses
text-xswith minimal padding for better fit in narrow bars - Size 2-3 (Large/XL): Uses larger text sizes with more padding for better readability
Labels inside the progress bar use flexbox centering to ensure proper alignment regardless of bar height.
Accessibility
- The progress bar automatically includes proper width styling based on the progress value.
- Add ARIA attributes like
role="progressbar",aria-valuenow,aria-valuemin, andaria-valuemaxfor screen reader compatibility. - Labels provide context for the progress being displayed.
- The component supports keyboard navigation when interactive elements are added.
JavaScript Integration
The Progress component includes a comprehensive Stimulus controller for dynamic updates, animations, and multi-progress bar support. Enable it by setting stimulus: true:
<%= fx_progress(progress: 50, stimulus: true, id: "my-progress") %>
Controller Architecture
The Fluxbit Progress component uses a separate Stimulus controller file located at:
- Controller File:
app/assets/javascripts/fluxbit_view_components/progress_controller.js - Registration: Automatically registered via
index.jsasfx-progress - Import Pattern: Uses ES6 modules with separate controller files (not inline controllers)
Vanilla JavaScript API (Recommended)
The easiest way to control progress bars is through the global FluxbitControllers API:
// Simple static methods - most convenient
FluxbitControllers.FxProgress.updateProgress('[data-controller="fx-progress"]', 75);
FluxbitControllers.FxProgress.animateProgress('[data-controller="fx-progress"]', 100, 2000);
FluxbitControllers.FxProgress.resetProgress('[data-controller="fx-progress"]');
FluxbitControllers.FxProgress.completeProgress('[data-controller="fx-progress"]');
// Real-time updates example
function updateUploadProgress(percentage) {
FluxbitControllers.FxProgress.updateProgress('#upload-progress', percentage);
if (percentage >= 100) {
FluxbitControllers.FxProgress.completeProgress('#upload-progress');
}
}
Multiple Progress Bars
Control multiple progress bars within the same scope using data-progress-id:
<div data-controller="fx-progress">
<!-- First progress bar -->
<%= fx_progress(progress: 30, text_label: "Upload", stimulus: true,
data: { progress_id: "upload" }) %>
<!-- Second progress bar -->
<%= fx_progress(progress: 70, text_label: "Download", stimulus: true,
data: { progress_id: "download" }) %>
<!-- Control specific progress bars -->
<button data-action="click->fx-progress#increment"
data-fx-progress-amount-param="10"
data-fx-progress-id-param="upload">+10% Upload</button>
<button data-action="click->fx-progress#increment"
data-fx-progress-amount-param="20"
data-fx-progress-id-param="download">+20% Download</button>
</div>
Direct Controller Access
For advanced scenarios, access the controller instance directly:
// Get controller instance
const controller = FluxbitControllers.FxProgress.getController('[data-controller="fx-progress"]');
// Call instance methods
controller.setProgress(75);
controller.incrementProgress(10);
controller.decrementProgress(5);
controller.reset();
controller.complete();
// Animated transitions
controller.animateToProgress(80, 1500); // Animate to 80% over 1.5 seconds
// Animation control
controller.setAnimate(false); // Disable animations
controller.setSpeed('fast'); // Set animation speed (slow, normal, fast, very_fast)
// Target specific progress bars by ID
FluxbitControllers.FxProgress.updateProgressById('[data-controller="fx-progress"]', 'upload', (progressController) => {
progressController.incrementProgress(25);
progressController.setSpeed('fast');
});
Stimulus Data Attributes
When stimulus: true is enabled, the component automatically adds:
data-controller="fx-progress"- Registers the Stimulus controllerdata-fx-progress-progress-value="X"- Initial progress valuedata-fx-progress-animate-value="true"- Enables animationsdata-fx-progress-target="bar"- Progress bar element targetdata-fx-progress-target="progressLabel"- Progress percentage label targetdata-fx-progress-target="textLabel"- Text label target
Real-World Examples
File Upload Progress
function uploadFile(file) {
const formData = new FormData();
formData.append('file', file);
// Reset progress
FluxbitControllers.FxProgress.resetProgress('#upload-progress');
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', (event) => {
if (event.lengthComputable) {
const percentage = Math.round((event.loaded / event.total) * 100);
FluxbitControllers.FxProgress.updateProgress('#upload-progress', percentage);
}
});
xhr.onload = function() {
FluxbitControllers.FxProgress.completeProgress('#upload-progress');
};
xhr.open('POST', '/upload');
xhr.send(formData);
}
Multi-Step Form Progress
class MultiStepForm {
constructor() {
this.currentStep = 1;
this.totalSteps = 4;
this.updateProgress();
}
nextStep() {
if (this.currentStep < this.totalSteps) {
this.currentStep++;
this.updateProgress();
}
}
updateProgress() {
const percentage = (this.currentStep / this.totalSteps) * 100;
FluxbitControllers.FxProgress.animateProgress('#form-progress', percentage, 500);
}
}
System Resource Monitor
// Update multiple progress bars with system stats
async function updateSystemStats() {
const response = await fetch('/api/system-stats');
const stats = await response.json();
// Update each resource metric
FluxbitControllers.FxProgress.updateProgressById('#system-monitor', 'cpu', (controller) => {
controller.animateToProgress(stats.cpu, 500);
});
FluxbitControllers.FxProgress.updateProgressById('#system-monitor', 'memory', (controller) => {
controller.animateToProgress(stats.memory, 500);
});
FluxbitControllers.FxProgress.updateProgressById('#system-monitor', 'disk', (controller) => {
controller.animateToProgress(stats.disk, 500);
});
}
Creating Custom Controllers
When creating new Fluxbit Stimulus controllers, follow this pattern:
- Create separate controller file:
app/assets/javascripts/fluxbit_view_components/your_controller.js - Use ES6 export default:
export default class extends Controller { ... } - Add import to index.js:
import FxYourController from './your_controller' - Add to exports: Include in the export object and registerFluxbitControllers function
- Never use inline controllers: Controllers must be in separate files, not embedded in the main JS file
Customization
You can customize the appearance and behavior of this component by passing different initialization parameters and adding custom styles. To do this you can create a initializer file like the:
# /config/initializers/change_progress_component_defaults.rb
Fluxbit::Config::ProgressComponent.color = :blue # the default is :default
Fluxbit::Config::ProgressComponent.size = 2 # the default is 1
Fluxbit::Config::ProgressComponent.label_progress = true # the default is false
Fluxbit::Config::ProgressComponent.progress_label_position = :outside # the default is :inside
Fluxbit::Config::ProgressComponent.label_html = { class: "font-semibold" } # the default is {}
Fluxbit::Config::ProgressComponent.styles[:base] = 'w-full bg-gray-100 rounded-lg dark:bg-gray-800' # custom base styling
Dependencies
- Stimulus: Used for JavaScript interactions when
stimulus: trueis enabled. - Tailwind CSS: Used for styling the component.
- Flowbite: Used for styling.
Styles
<%= html_escape(JSON.pretty_generate(Fluxbit::Config::ProgressComponent.styles)) %>