Progress
Stabletask progress
Migration
68%
Provisioning
92%
Quota
84%
Usage example #
Copy this ERB into a Rails view after installing the component. The snippet below is the same code used by the live preview above.
app/views/.../progress_example.html.erb
<div class="w-full max-w-md space-y-4">
<%= render Senren::ProgressComponent.new(label: "Migration", value: 68, variant: :default) %>
<%= render Senren::ProgressComponent.new(label: "Provisioning", value: 92, variant: :success) %>
<%= render Senren::ProgressComponent.new(label: "Quota", value: 84, variant: :warning) %>
</div>
Install this component #
Copy the official component into your app
Use this when you want the Senren-maintained implementation copied into app/components/senren.
Terminal
bin/rails senren:add progress
Create a custom component with the same conventions
Use this when you need an app-specific static component that follows Senren's ViewComponent structure.
Terminal
bin/rails generate senren:component progress --no-client
At a glance #
Category
Data
Class name
Senren::ProgressComponent
Stimulus
—
Variants
default, success, warning, destructive
Depends on
—
Pairs with
card, alert
Source #
app/components/senren/progress_component.html.erb
<div <%= tag.attributes(**root_attrs("w-full")) %>>
<% if label.present? %>
<div class="mb-2 flex items-center justify-between text-sm">
<span class="font-medium text-[hsl(var(--senren-foreground))]"><%= label %></span>
<span class="text-[hsl(var(--senren-muted-foreground))]"><%= percent %>%</span>
</div>
<% end %>
<div role="progressbar" aria-valuemin="0" aria-valuemax="<%= max.to_i %>" aria-valuenow="<%= value.to_i %>" class="h-2.5 w-full overflow-hidden rounded-full bg-[hsl(var(--senren-muted))]">
<div class="h-full rounded-full transition-[width] duration-300 ease-out <%= indicator_class %>" style="width: <%= percent %>%"></div>
</div>
</div>
app/components/senren/progress_component.rb
# frozen_string_literal: true
module Senren
class ProgressComponent < BaseComponent
VARIANTS = {
default: '',
success: '',
warning: '',
destructive: ''
}.freeze
INDICATOR_VARIANTS = {
default: 'bg-[hsl(var(--senren-primary))]',
success: 'bg-[hsl(var(--senren-success))]',
warning: 'bg-[hsl(var(--senren-warning))]',
destructive: 'bg-[hsl(var(--senren-destructive))]'
}.freeze
SIZES = { md: '' }.freeze
def initialize(value: 0, max: 100, label: nil, variant: :default, class_name: nil, **html)
super(variant: variant, size: :md, class_name: class_name, **html)
@value = value.to_f
@max = max.to_f.positive? ? max.to_f : 100.0
@label = label
end
attr_reader :value, :max, :label
def percent
((value / max) * 100).clamp(0, 100).round
end
def indicator_class
INDICATOR_VARIANTS.fetch(variant)
end
end
end
AI agent rules #
Use for
- +task progress
- +file upload
- +loading bars
Avoid
- -decorative animation
Accessibility #
- role=progressbar with aria-valuenow/min/max.