Skip to content

LumexProgressBar#282

Open
kevinvenclovas wants to merge 7 commits intoLumexUI:mainfrom
kevinvenclovas:LumexProgressBar
Open

LumexProgressBar#282
kevinvenclovas wants to merge 7 commits intoLumexUI:mainfrom
kevinvenclovas:LumexProgressBar

Conversation

@kevinvenclovas
Copy link
Copy Markdown

@kevinvenclovas kevinvenclovas commented Feb 22, 2026

Description

What's been done?

  • Added ProgressBar component
  • Added docs and updates exist image with the new component

Checklist

  • My code follows the project's coding style and guidelines.
  • I have included inline docs for my changes, where applicable.
  • I have added, updated or removed tests according to my changes.
  • All tests are passing.
  • There's an open issue for the PR that I am making.
image

Summary by CodeRabbit

  • New Features
    • Added a Progress component with configurable sizes, colors, radius, indeterminate animation, value labels, and ARIA support.
  • Documentation
    • Comprehensive docs, interactive examples and preview code (usage, sizes, colors, indeterminate, label, value, custom styles) plus navigation entries added to the docs site.
  • Style
    • New loading animation and utilities with animation control.
  • Tests
    • Test suite covering rendering, accessibility, clamping, indeterminate behavior, and styling.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 22, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a new LumexProgress component (component + code-behind + slot types), styling variants and animation, documentation pages/examples and interactive previews, navigation entries, and a comprehensive test suite covering rendering, ARIA, clamping/percentage logic, and indeterminate behavior.

Changes

Cohort / File(s) Summary
Navigation & Theme
docs/LumexUI.Docs.Client/Common/Navigation/NavigationStore.cs, src/LumexUI/Styles/_theme.css
Appends LumexProgress entries to docs navigation (Components and Components API) and adds an animation variable plus progress-loading keyframes and related utilities.
Component Implementation
src/LumexUI/Components/Progress/LumexProgress.razor, src/LumexUI/Components/Progress/LumexProgress.razor.cs, src/LumexUI/Components/Progress/ProgressSlots.cs
New LumexProgress component and ProgressSlots: parameters (Value/Min/Max, Label/ValueLabel, IsIndeterminate, ShowValueLabel, animation/disable/disabled flags, Color/Size/Radius), computed percentage/indicator width, ARIA attributes, slot-based rendering and GetStyles.
Component Styling
src/LumexUI/Styles/Progress.cs
New Progress style builder using TwVariants: defines slots, size/radius variants, behavior flags (IsIndeterminate, DisableAnimation, IsDisabled), and color compound variants; caching of ComponentVariant.
Documentation Examples
docs/.../Pages/Components/Progress/Examples/*
Adds Usage, Sizes, Colors, Indeterminate, Label, CustomStyles, and Value examples (Value contains timer-driven demo and IAsyncDisposable).
Documentation Preview
docs/.../Pages/Components/Progress/PreviewCodes/*
Adds interactive PreviewCode wrapper pages for each example snippet (InteractiveWebAssembly render mode).
Main Documentation Page
docs/LumexUI.Docs.Client/Pages/Components/Progress/Progress.razor
New docs page assembling examples, custom styles, API panel and navigation headings; registers LumexProgress in API list.
Test Suite
tests/LumexUI.Tests/Components/Progress/ProgressTests.cs
Comprehensive tests for rendering, slot presence, indicator width/clamping, indeterminate animation/ARIA behavior, label/value rendering, color/size/radius props, and slot/class customization.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • PR #114 — Also adds a component navigation entry to NavigationStore (similar insertion pattern).
  • PR #252 — Modifies the same docs NavigationStore to append component/API entries (same file touched).
  • PR #249 — Adds a new UI component and updates docs/navigation similarly (related at component + docs level).

Suggested labels

📦 Scope: Components, 🚀 Type: Feature

Suggested reviewers

  • desmondinho

Poem

🐰 I hopped along a code-filled trail,

Painted bars that tell the tale,
Colors gleam and numbers climb,
LumexProgress ticks in time,
Small hops forward, progress hale. 🥕

🚥 Pre-merge checks | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is incomplete and missing the 'Closes #{issue_number}' section; the template requires this but the description leaves it blank, and there is no open issue per the unchecked checkbox. Add the issue number reference in the 'Closes' section or clarify why no issue exists, and ensure all template sections are properly filled out.
Docstring Coverage ⚠️ Warning Docstring coverage is 5.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'LumexProgressBar' is generic and does not clearly convey what was changed; it appears to be a component name rather than a summary of the actual changes. Use a more descriptive title like 'Add LumexProgress component with documentation and tests' to clearly summarize the main change.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (11)
docs/LumexUI.Docs.Client/Pages/Components/ProgressBar/Examples/CustomStyles.razor (1)

2-10: Both LumexProgressBar elements have no child content — prefer self-closing tags.

Helps keep markup concise and signals intent.

♻️ Proposed cleanup
-    <LumexProgressBar Value="60" 
-                     Color="@ThemeColor.Primary"
-                     Class="border-2 border-primary">
-    </LumexProgressBar>
+    <LumexProgressBar Value="60"
+                     Color="@ThemeColor.Primary"
+                     Class="border-2 border-primary" />

-    <LumexProgressBar Value="80" 
-                     Color="@ThemeColor.Success"
-                     Classes="@(new ProgressBarSlots { Track = "shadow-medium" })">
-    </LumexProgressBar>
+    <LumexProgressBar Value="80"
+                     Color="@ThemeColor.Success"
+                     Classes="@(new ProgressBarSlots { Track = "shadow-medium" })" />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@docs/LumexUI.Docs.Client/Pages/Components/ProgressBar/Examples/CustomStyles.razor`
around lines 2 - 10, Replace the two LumexProgressBar elements with self-closing
tags since they contain no child content; update the markup for the components
that use the LumexProgressBar (the instances with Value, Color, Class and the
one using Classes="@(new ProgressBarSlots { Track = "shadow-medium" })") so they
are written as self-closing elements to keep the Razor markup concise and signal
no children are intended.
src/LumexUI/Components/ProgressBar/ProgressBarContext.cs (2)

39-39: Non-standard whitespace inside constructor parameter list parentheses.

♻️ Proposed fix
-	public ProgressBarContext( double percentage, double normalizedValue, double value, double maxValue )
+	public ProgressBarContext(double percentage, double normalizedValue, double value, double maxValue)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/LumexUI/Components/ProgressBar/ProgressBarContext.cs` at line 39, The
constructor signature for ProgressBarContext contains non-standard whitespace
characters inside the parameter-list parentheses; update the ProgressBarContext
constructor declaration to use normal ASCII spaces and consistent spacing so it
reads exactly like: ProgressBarContext(double percentage, double
normalizedValue, double value, double maxValue) (i.e., remove any
hidden/non-breaking spaces after '(' and around commas/parentheses).

15-30: Use { get; init; } to enable with-expression support on record properties.

Properties declared with { get; } cannot be targeted by with expressions (e.g., context with { Percentage = 75 } will not compile). Using { get; init; } aligns with standard record semantics, makes properties settable during construction and via with expressions, and keeps the type effectively immutable.

♻️ Proposed refactor
-	public double Percentage { get; }
+	public double Percentage { get; init; }

-	public double NormalizedValue { get; }
+	public double NormalizedValue { get; init; }

-	public double Value { get; }
+	public double Value { get; init; }

-	public double MaxValue { get; }
+	public double MaxValue { get; init; }

The constructor body remains unchanged; init accessors are settable during construction and from with expressions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/LumexUI/Components/ProgressBar/ProgressBarContext.cs` around lines 15 -
30, Change the four read-only properties on ProgressBarContext (Percentage,
NormalizedValue, Value, MaxValue) from "{ get; }" to "{ get; init; }" so they
can be set during construction and via "with" expressions; keep the existing
constructor logic unchanged so initialization remains the same but the
properties support record-style immutability updates.
docs/LumexUI.Docs.Client/Pages/Components/ProgressBar/Examples/Position.razor (1)

2-19: Size="@Size.Medium" is redundant — consider removing it

Size.Medium is the default value per LumexProgressBar.razor.cs. Including it on all three bars in a positioning example implies size affects label positioning, which it doesn't. Removing it would keep the snippet focused on the LabelPosition parameter being demonstrated.

🧹 Suggested cleanup
 <div class="w-full flex flex-col gap-4">
     <LumexProgressBar Value="50" 
                      ShowLabel="true" 
                      IsLabelInline="true" 
                      LabelPosition="@Align.Start"
-                     Size="@Size.Medium"
                      Color="@ThemeColor.Primary" />
     <LumexProgressBar Value="50" 
                      ShowLabel="true" 
                      IsLabelInline="true" 
                      LabelPosition="@Align.Center"
-                     Size="@Size.Medium"
                      Color="@ThemeColor.Primary" />
     <LumexProgressBar Value="50" 
                      ShowLabel="true" 
                      IsLabelInline="true" 
                      LabelPosition="@Align.End"
-                     Size="@Size.Medium"
                      Color="@ThemeColor.Primary" />
 </div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@docs/LumexUI.Docs.Client/Pages/Components/ProgressBar/Examples/Position.razor`
around lines 2 - 19, The examples redundantly set Size="@Size.Medium" which is
the default in LumexProgressBar (see LumexProgressBar.razor.cs); remove the
Size="@Size.Medium" attribute from each LumexProgressBar in this Position.razor
example so the snippet focuses on LabelPosition/Align
(LabelPosition="@Align.Start", "@Align.Center", "@Align.End") and avoids
implying size affects label positioning.
docs/LumexUI.Docs.Client/Pages/Components/ProgressBar/Examples/InlineLabel.razor (1)

2-19: LabelPosition="@Align.Center" is redundant — consider removing it

Align.Center is the default per LumexProgressBar.razor.cs. Since this example's purpose is to show inline labels at varying sizes (not positions), including the explicit default on all three instances may imply it's required for inline labelling when it isn't. Removing it keeps the snippet minimal and on-point.

🧹 Suggested cleanup
 <div class="w-full flex flex-col gap-4">
     <LumexProgressBar Value="40" 
                      ShowLabel="true" 
                      IsLabelInline="true" 
-                     LabelPosition="@Align.Center"
                      Size="@Size.Small"
                      Color="@ThemeColor.Primary" />
     <LumexProgressBar Value="60"
                      ShowLabel="true" 
                      IsLabelInline="true" 
-                     LabelPosition="@Align.Center"
                      Size="@Size.Medium"
                      Color="@ThemeColor.Primary" />
     <LumexProgressBar Value="80" 
                      ShowLabel="true" 
                      IsLabelInline="true" 
-                     LabelPosition="@Align.Center"
                      Size="@Size.Large"
                      Color="@ThemeColor.Primary" />
 </div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@docs/LumexUI.Docs.Client/Pages/Components/ProgressBar/Examples/InlineLabel.razor`
around lines 2 - 19, The LabelPosition="@Align.Center" attribute is redundant
because Align.Center is the default in LumexProgressBar (see
LumexProgressBar.razor.cs); remove the LabelPosition="@Align.Center" from each
LumexProgressBar instance so the examples focus on IsLabelInline and different
Size values without implying the position must be set explicitly.
tests/LumexUI.Tests/Components/ProgressBar/ProgressBarTests.cs (3)

238-256: NormalizedValue assertion is inconclusive — test cannot distinguish it from Value.

With Value=60 and MaxValue=200, 60 is fully within [0, MaxValue], so NormalizedValue == Value == 60 regardless of clamping. The assertion context.NormalizedValue.Should().Be(60.0) provides no evidence that NormalizedValue behaves differently from the raw Value. Using an out-of-range value (e.g., Value = -10) would actually exercise clamping and prove the two properties diverge:

♻️ Suggested test adjustment
  var cut = RenderComponent<LumexProgressBar>( p => p
      .Add( p => p.ShowLabel, true )
-     .Add( p => p.Value, 60 )
+     .Add( p => p.Value, -10 )  // out-of-range → NormalizedValue should be 0
      .Add( p => p.MaxValue, 200 )
      .Add( p => p.LabelContent, context =>
      {
-         context.Percentage.Should().Be( 30.0 );
-         context.NormalizedValue.Should().Be( 60.0 );
-         context.Value.Should().Be( 60.0 );
+         context.Percentage.Should().Be( 0.0 );    // clamped
+         context.NormalizedValue.Should().Be( 0.0 ); // clamped to 0, not -10
+         context.Value.Should().Be( -10.0 );        // raw input preserved
          context.MaxValue.Should().Be( 200.0 );
          return "Test";
      } )
  );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/LumexUI.Tests/Components/ProgressBar/ProgressBarTests.cs` around lines
238 - 256, Update the ProgressBar_LabelContent_ShouldHaveAccessToContext test so
NormalizedValue is actually exercised: set LumexProgressBar.Value to an
out-of-range value (for example -10) while keeping MaxValue at 200, then assert
that context.Value equals the raw -10.0 and context.NormalizedValue equals the
clamped value (e.g., 0.0) along with the existing Percentage/MaxValue
assertions; modify the render block passed to RenderComponent<LumexProgressBar>
and the assertions inside the LabelContent delegate accordingly.

207-222: ProgressBar_LabelPosition_ShouldApplyCorrectPosition only asserts the label renders, not that the correct alignment class is applied.

The test verifies no exception occurs and the label slot is present, but says nothing about whether Align.Start, Align.Center, or Align.End produces the expected CSS class on the label element. Consider adding a class assertion (e.g., text-start, text-center, text-end, or whichever utility the style system emits).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/LumexUI.Tests/Components/ProgressBar/ProgressBarTests.cs` around lines
207 - 222, Update the test ProgressBar_LabelPosition_ShouldApplyCorrectPosition
to assert that the rendered label element receives the expected CSS alignment
class based on the LabelPosition value: when LabelPosition is Align.Start assert
the label contains the "text-start" (or the project-specific start class), for
Align.Center assert "text-center", and for Align.End assert "text-end"; locate
the label via cut.FindBySlot("label") and add an assertion against
label.ClassList or label.GetAttribute("class") to verify the correct class is
present for LumexProgressBar's LabelPosition handling.

172-205: OuterHtml string comparison for DOM-containment checks is fragile.

track!.Children.Any(c => c.OuterHtml == label.OuterHtml) relies on exact string equality of the rendered HTML. Any change in attribute ordering, whitespace, or added children by bUnit could produce a false negative without a real bug. Prefer an explicit parent-child DOM relationship check:

♻️ Proposed refactor
- track!.Children.Any( c => c.OuterHtml == label.OuterHtml ).Should().BeTrue();
+ label!.ParentElement!.GetAttribute( "data-slot" ).Should().Be( "track" );
- track!.Children.Any( c => c.OuterHtml == label.OuterHtml ).Should().BeFalse();
+ label!.ParentElement!.GetAttribute( "data-slot" ).Should().NotBe( "track" );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/LumexUI.Tests/Components/ProgressBar/ProgressBarTests.cs` around lines
172 - 205, The tests ProgressBar_IsLabelInline_ShouldRenderLabelInsideTrack and
ProgressBar_IsLabelInlineFalse_ShouldRenderLabelOutsideTrack use fragile
OuterHtml string equality; change them to assert DOM parent-child relationships
using the found elements (track and label) instead: for the inline case assert
that label's parent/ancestor is the track element (e.g., label.Parent equals or
is contained within track), and for the non-inline case assert the label is not
a child/descendant of track (e.g., label.Parent is not track or track does not
contain label), keeping the existing variables track and label to locate the
elements.
src/LumexUI/Components/ProgressBar/LumexProgressBar.razor.cs (1)

116-128: OnParametersSet rebuilds slot styles on every render, including high-frequency Value changes.

Style output depends only on Size, Radius, Color, IsLoadingBar, IsLabelInline, and LabelPosition—none of which change during a typical progress animation. Rebuilding _slots on every Value update is wasteful. Consider tracking the style-relevant parameters and short-circuiting when they are unchanged.

♻️ Proposed approach
+private Size _prevSize;
+private Radius _prevRadius;
+private ThemeColor _prevColor;
+private bool _prevIsLoadingBar;
+private bool _prevIsLabelInline;
+private Align _prevLabelPosition;

 protected override void OnParametersSet()
 {
+    if( Size == _prevSize && Radius == _prevRadius && Color == _prevColor &&
+        IsLoadingBar == _prevIsLoadingBar && IsLabelInline == _prevIsLabelInline &&
+        LabelPosition == _prevLabelPosition )
+    {
+        return;
+    }
+    ( _prevSize, _prevRadius, _prevColor, _prevIsLoadingBar, _prevIsLabelInline, _prevLabelPosition ) =
+        ( Size, Radius, Color, IsLoadingBar, IsLabelInline, LabelPosition );
+
     var progressBar = Styles.ProgressBar.Style( TwMerge );
     _slots = progressBar( new()
     { ... } );
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/LumexUI/Components/ProgressBar/LumexProgressBar.razor.cs` around lines
116 - 128, OnParametersSet currently recomputes _slots via
Styles.ProgressBar.Style(TwMerge) on every render (including frequent Value
updates); change it to memoize the style-relevant inputs (Size, Radius, Color,
IsLoadingBar, IsLabelInline, LabelPosition) and only call
Styles.ProgressBar.Style(...) to rebuild _slots when any of those tracked
properties actually change. Implement simple cached fields (e.g., _lastSize,
_lastRadius, etc. or a single struct/hash) inside the LumexProgressBar class,
compare them at the start of OnParametersSet, and return early if unchanged;
otherwise update the cached values and recompute _slots as you do now.
src/LumexUI/Styles/ProgressBar.cs (1)

104-181: Seven near-identical color CompoundVariant blocks can be collapsed into a loop.

Each block differs only by ThemeColor value. Since ColorVariants.Solid is a Dictionary<ThemeColor, string>, all entries can be generated by iterating it.

♻️ Proposed refactor

Replace lines 104–181 with a foreach inside the CompoundVariants collection initializer, or build the list before the VariantConfig:

-			// Color variants for fill
-			new CompoundVariant()
-			{
-				Conditions = new()
-				{
-					[nameof( LumexProgressBar.Color )] = nameof( ThemeColor.Default )
-				},
-				Classes = new SlotCollection()
-				{
-					[nameof( ProgressBarSlots.Fill )] = ColorVariants.Solid[ThemeColor.Default]
-				}
-			},
-			// ... (repeated for each ThemeColor)
+			// Color variants for fill — generated from ColorVariants.Solid
+			..ColorVariants.Solid.Select( kvp => new CompoundVariant()
+			{
+				Conditions = new()
+				{
+					[nameof( LumexProgressBar.Color )] = kvp.Key.ToString()
+				},
+				Classes = new SlotCollection()
+				{
+					[nameof( ProgressBarSlots.Fill )] = kvp.Value
+				}
+			} ),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/LumexUI/Styles/ProgressBar.cs` around lines 104 - 181, The repeated
CompoundVariant blocks mapping LumexProgressBar.Color values to
ColorVariants.Solid can be collapsed by iterating the ColorVariants.Solid
dictionary (or its keys) and creating a CompoundVariant per entry; replace the
seven hard-coded CompoundVariant initializers with a loop that for each
ThemeColor key builds a CompoundVariant with Conditions = {
[nameof(LumexProgressBar.Color)] = nameof(ThemeColor.<key>) } and Classes = new
SlotCollection() { [nameof(ProgressBarSlots.Fill)] = ColorVariants.Solid[key] }
(either via a foreach when constructing the CompoundVariants collection or by
pre-building a List<CompoundVariant> and adding it to the VariantConfig).
src/LumexUI/Components/ProgressBar/LumexProgressBar.razor (1)

19-21: Hardcoded animation-duration inline style bypasses theming.

The 1.5s duration is set as an inline style rather than being expressed as a CSS custom property or embedded in the animate-shimmer class. If the theme ever needs to adjust this timing (e.g., via --animate-shimmer), this inline value will silently win.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/LumexUI/Components/ProgressBar/LumexProgressBar.razor` around lines 19 -
21, The inline style setting animation-duration: 1.5s on the div in
LumexProgressBar.razor (the element with class "absolute inset-0 bg-white/30
animate-shimmer") bypasses theming; remove that inline style and instead drive
the duration from a CSS custom property (e.g. --animate-shimmer) or define it
inside the .animate-shimmer rule so theme overrides work—update the component to
omit the style attribute and modify the .animate-shimmer CSS to use
var(--animate-shimmer, 1.5s) (or place the duration directly in the class) so
theme values can take precedence.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/LumexUI/Components/ProgressBar/LumexProgressBar.razor`:
- Around line 40-52: The external label branch inside the conditional using
ShouldShowLabel && !IsLabelInline incorrectly outputs NormalizedValue:F0%
instead of the computed Percentage, so update the fallback in the div (where
LabelContent and Context are used and GetStyles(nameof(S.Label)) is applied) to
render Percentage:F0% instead of NormalizedValue:F0%; keep the custom
LabelContent path unchanged so consumers still receive Context when provided.

In `@src/LumexUI/Components/ProgressBar/LumexProgressBar.razor.cs`:
- Around line 107-108: The NormalizedValue property uses Math.Clamp(Value, 0,
MaxValue) which throws if MaxValue is negative; update NormalizedValue to bound
the clamp's upper limit to a non-negative value (e.g., use Math.Max(0,
MaxValue)) so the clamp call never receives max < min. Keep the Percentage guard
(MaxValue > 0) as-is; change only the NormalizedValue computation referenced by
the NormalizedValue property to use Math.Max(0, MaxValue).
- Line 110: ShouldShowLabel currently suppresses the default label at exactly 0%
because of the "NormalizedValue > 0" check; change the property on
LumexProgressBar.razor.cs (ShouldShowLabel) to only gate on explicit consumer
intent and loading state by removing the NormalizedValue check so it becomes
ShowLabel && !IsLoadingBar (i.e., always show the label when ShowLabel is true
unless IsLoadingBar is true, and still allow LabelContent to override).

In `@src/LumexUI/Components/ProgressBar/ProgressBarContext.cs`:
- Around line 18-20: The property NormalizedValue and its XML doc
disagree—change the API to match intent by renaming NormalizedValue to
ClampedValue and update its doc to "Gets the value clamped between 0 and <see
cref="MaxValue"/>", then update all references/usages (including any consumers
in LabelContent fragments, bindings, and tests) to use ClampedValue; ensure any
logic that currently computes clamp(Value, 0, MaxValue) remains unchanged and
only the property name and XML comment are updated to avoid breaking semantics.

In `@tests/LumexUI.Tests/Components/ProgressBar/ProgressBarTests.cs`:
- Around line 116-124: The test
ProgressBar_IsLoadingBar_ShouldHaveShimmerAnimation currently only checks for
the shimmer overlay; update it to also locate the Fill element of
LumexProgressBar (the Fill slot rendered when IsLoadingBar=true) and assert that
the fill element has the CSS class "animate-progress-loading" (e.g., find the
fill element and call Should().Contain("animate-progress-loading") or use an
element.HasClass assertion) to ensure the fill itself receives the loading
animation applied in ProgressBar.cs.

---

Nitpick comments:
In
`@docs/LumexUI.Docs.Client/Pages/Components/ProgressBar/Examples/CustomStyles.razor`:
- Around line 2-10: Replace the two LumexProgressBar elements with self-closing
tags since they contain no child content; update the markup for the components
that use the LumexProgressBar (the instances with Value, Color, Class and the
one using Classes="@(new ProgressBarSlots { Track = "shadow-medium" })") so they
are written as self-closing elements to keep the Razor markup concise and signal
no children are intended.

In
`@docs/LumexUI.Docs.Client/Pages/Components/ProgressBar/Examples/InlineLabel.razor`:
- Around line 2-19: The LabelPosition="@Align.Center" attribute is redundant
because Align.Center is the default in LumexProgressBar (see
LumexProgressBar.razor.cs); remove the LabelPosition="@Align.Center" from each
LumexProgressBar instance so the examples focus on IsLabelInline and different
Size values without implying the position must be set explicitly.

In
`@docs/LumexUI.Docs.Client/Pages/Components/ProgressBar/Examples/Position.razor`:
- Around line 2-19: The examples redundantly set Size="@Size.Medium" which is
the default in LumexProgressBar (see LumexProgressBar.razor.cs); remove the
Size="@Size.Medium" attribute from each LumexProgressBar in this Position.razor
example so the snippet focuses on LabelPosition/Align
(LabelPosition="@Align.Start", "@Align.Center", "@Align.End") and avoids
implying size affects label positioning.

In `@src/LumexUI/Components/ProgressBar/LumexProgressBar.razor`:
- Around line 19-21: The inline style setting animation-duration: 1.5s on the
div in LumexProgressBar.razor (the element with class "absolute inset-0
bg-white/30 animate-shimmer") bypasses theming; remove that inline style and
instead drive the duration from a CSS custom property (e.g. --animate-shimmer)
or define it inside the .animate-shimmer rule so theme overrides work—update the
component to omit the style attribute and modify the .animate-shimmer CSS to use
var(--animate-shimmer, 1.5s) (or place the duration directly in the class) so
theme values can take precedence.

In `@src/LumexUI/Components/ProgressBar/LumexProgressBar.razor.cs`:
- Around line 116-128: OnParametersSet currently recomputes _slots via
Styles.ProgressBar.Style(TwMerge) on every render (including frequent Value
updates); change it to memoize the style-relevant inputs (Size, Radius, Color,
IsLoadingBar, IsLabelInline, LabelPosition) and only call
Styles.ProgressBar.Style(...) to rebuild _slots when any of those tracked
properties actually change. Implement simple cached fields (e.g., _lastSize,
_lastRadius, etc. or a single struct/hash) inside the LumexProgressBar class,
compare them at the start of OnParametersSet, and return early if unchanged;
otherwise update the cached values and recompute _slots as you do now.

In `@src/LumexUI/Components/ProgressBar/ProgressBarContext.cs`:
- Line 39: The constructor signature for ProgressBarContext contains
non-standard whitespace characters inside the parameter-list parentheses; update
the ProgressBarContext constructor declaration to use normal ASCII spaces and
consistent spacing so it reads exactly like: ProgressBarContext(double
percentage, double normalizedValue, double value, double maxValue) (i.e., remove
any hidden/non-breaking spaces after '(' and around commas/parentheses).
- Around line 15-30: Change the four read-only properties on ProgressBarContext
(Percentage, NormalizedValue, Value, MaxValue) from "{ get; }" to "{ get; init;
}" so they can be set during construction and via "with" expressions; keep the
existing constructor logic unchanged so initialization remains the same but the
properties support record-style immutability updates.

In `@src/LumexUI/Styles/ProgressBar.cs`:
- Around line 104-181: The repeated CompoundVariant blocks mapping
LumexProgressBar.Color values to ColorVariants.Solid can be collapsed by
iterating the ColorVariants.Solid dictionary (or its keys) and creating a
CompoundVariant per entry; replace the seven hard-coded CompoundVariant
initializers with a loop that for each ThemeColor key builds a CompoundVariant
with Conditions = { [nameof(LumexProgressBar.Color)] = nameof(ThemeColor.<key>)
} and Classes = new SlotCollection() { [nameof(ProgressBarSlots.Fill)] =
ColorVariants.Solid[key] } (either via a foreach when constructing the
CompoundVariants collection or by pre-building a List<CompoundVariant> and
adding it to the VariantConfig).

In `@tests/LumexUI.Tests/Components/ProgressBar/ProgressBarTests.cs`:
- Around line 238-256: Update the
ProgressBar_LabelContent_ShouldHaveAccessToContext test so NormalizedValue is
actually exercised: set LumexProgressBar.Value to an out-of-range value (for
example -10) while keeping MaxValue at 200, then assert that context.Value
equals the raw -10.0 and context.NormalizedValue equals the clamped value (e.g.,
0.0) along with the existing Percentage/MaxValue assertions; modify the render
block passed to RenderComponent<LumexProgressBar> and the assertions inside the
LabelContent delegate accordingly.
- Around line 207-222: Update the test
ProgressBar_LabelPosition_ShouldApplyCorrectPosition to assert that the rendered
label element receives the expected CSS alignment class based on the
LabelPosition value: when LabelPosition is Align.Start assert the label contains
the "text-start" (or the project-specific start class), for Align.Center assert
"text-center", and for Align.End assert "text-end"; locate the label via
cut.FindBySlot("label") and add an assertion against label.ClassList or
label.GetAttribute("class") to verify the correct class is present for
LumexProgressBar's LabelPosition handling.
- Around line 172-205: The tests
ProgressBar_IsLabelInline_ShouldRenderLabelInsideTrack and
ProgressBar_IsLabelInlineFalse_ShouldRenderLabelOutsideTrack use fragile
OuterHtml string equality; change them to assert DOM parent-child relationships
using the found elements (track and label) instead: for the inline case assert
that label's parent/ancestor is the track element (e.g., label.Parent equals or
is contained within track), and for the non-inline case assert the label is not
a child/descendant of track (e.g., label.Parent is not track or track does not
contain label), keeping the existing variables track and label to locate the
elements.

@kevinvenclovas kevinvenclovas changed the title added component progress bar LumexProgressBar Feb 22, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
src/LumexUI/Components/ProgressBar/ProgressBarContext.cs (1)

18-18: ⚠️ Potential issue | 🟡 Minor

Residual doc inconsistency: ClampedValue summary still says "normalized value".

The property was correctly renamed from NormalizedValue to ClampedValue, but the XML summary on line 18 was not updated and still reads "Gets the normalized value". It should read "Gets the clamped value".

📝 Proposed fix
-/// Gets the normalized value (clamped between 0 and <see cref="MaxValue"/>).
+/// Gets the clamped value (between 0 and <see cref="MaxValue"/>).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/LumexUI/Components/ProgressBar/ProgressBarContext.cs` at line 18, Update
the XML doc comment for the ClampedValue property so it no longer says
"normalized value": change the summary to "Gets the clamped value (clamped
between 0 and <see cref=\"MaxValue\"/>)." Locate the summary above the
ClampedValue property in ProgressBarContext (the XML <summary> for ClampedValue)
and replace the word "normalized" with "clamped" while preserving the rest of
the tag and cref reference.
🧹 Nitpick comments (1)
tests/LumexUI.Tests/Components/ProgressBar/ProgressBarTests.cs (1)

249-268: Assertions inside the LabelContent render callback can silently pass.

If ShouldShowLabel ever evaluates to false (e.g., due to a future regression), the callback is never invoked and context.Percentage.Should().Be(30.0) never runs — the test reports green because only the outer label.Should().NotBeNull() fires (and finds null, which would fail). But the specific context-value assertions are simply skipped without any diagnostic. Capturing the context outside is safer and makes intent explicit.

♻️ Proposed refactor
+ProgressBarContext? capturedCtx = null;
 var cut = RenderComponent<LumexProgressBar>( p => p
     .Add( p => p.ShowLabel, true )
     .Add( p => p.Value, 60 )
     .Add( p => p.MaxValue, 200 )
-    .Add( p => p.LabelContent, context =>
-    {
-        context.Percentage.Should().Be( 30.0 );
-        context.ClampedValue.Should().Be( 60.0 );
-        context.Value.Should().Be( 60.0 );
-        context.MaxValue.Should().Be( 200.0 );
-        return "Test";
-    } )
+    .Add( p => p.LabelContent, context => { capturedCtx = context; return "Test"; } )
 );
 
-var label = cut.FindBySlot( "label" );
-label.Should().NotBeNull();
+cut.FindBySlot( "label" ).Should().NotBeNull();
+capturedCtx.Should().NotBeNull();
+var ctx = capturedCtx!.Value;
+ctx.Percentage.Should().Be( 30.0 );
+ctx.ClampedValue.Should().Be( 60.0 );
+ctx.Value.Should().Be( 60.0 );
+ctx.MaxValue.Should().Be( 200.0 );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/LumexUI.Tests/Components/ProgressBar/ProgressBarTests.cs` around lines
249 - 268, The test ProgressBar_LabelContent_ShouldHaveAccessToContext currently
performs assertions inside the LabelContent render callback which can be
silently skipped if the label isn't rendered; change it to capture the
LabelContent context into a local variable from the
RenderComponent<LumexProgressBar> invocation (e.g., assign the context provided
to LabelContent to a local variable), then after rendering assert on
context.Percentage, context.ClampedValue, context.Value and context.MaxValue,
and finally assert the label exists; ensure you still set ShowLabel, Value and
MaxValue when calling RenderComponent so the callback is invoked.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/LumexUI/Components/ProgressBar/ProgressBarContext.cs`:
- Line 18: Update the XML doc comment for the ClampedValue property so it no
longer says "normalized value": change the summary to "Gets the clamped value
(clamped between 0 and <see cref=\"MaxValue\"/>)." Locate the summary above the
ClampedValue property in ProgressBarContext (the XML <summary> for ClampedValue)
and replace the word "normalized" with "clamped" while preserving the rest of
the tag and cref reference.

---

Nitpick comments:
In `@tests/LumexUI.Tests/Components/ProgressBar/ProgressBarTests.cs`:
- Around line 249-268: The test
ProgressBar_LabelContent_ShouldHaveAccessToContext currently performs assertions
inside the LabelContent render callback which can be silently skipped if the
label isn't rendered; change it to capture the LabelContent context into a local
variable from the RenderComponent<LumexProgressBar> invocation (e.g., assign the
context provided to LabelContent to a local variable), then after rendering
assert on context.Percentage, context.ClampedValue, context.Value and
context.MaxValue, and finally assert the label exists; ensure you still set
ShowLabel, Value and MaxValue when calling RenderComponent so the callback is
invoked.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 74fb387 and 546a045.

📒 Files selected for processing (4)
  • src/LumexUI/Components/ProgressBar/LumexProgressBar.razor
  • src/LumexUI/Components/ProgressBar/LumexProgressBar.razor.cs
  • src/LumexUI/Components/ProgressBar/ProgressBarContext.cs
  • tests/LumexUI.Tests/Components/ProgressBar/ProgressBarTests.cs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/LumexUI/Components/ProgressBar/LumexProgressBar.razor

Copy link
Copy Markdown
Contributor

@desmondinho desmondinho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @kevinvenclovas,

Thank you very much for this PR! Overall, it looks good -- though there are a couple of points that need attention.

Please make sure that you follow the HeroUI styles and structure:

  1. https://github.com/heroui-inc/heroui/blob/main/packages/components/progress/src/progress.tsx|

  2. https://github.com/heroui-inc/heroui/blob/main/packages/core/theme/src/components/progress.ts#L25

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (5)
docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Label.razor (1)

2-2: Consider adding AriaLabel for accessibility completeness.

Other examples in this documentation set include AriaLabel alongside visual properties. If the Label parameter doesn't automatically provide ARIA labeling, screen reader users won't have context for this progress bar.

Suggested improvement
 <div class="w-full flex flex-col gap-4">
-    <LumexProgress Value="55" Label="Loading..." />
+    <LumexProgress Value="55" Label="Loading..." AriaLabel="Loading..." />
 </div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Label.razor` at
line 2, The Progress example uses the LumexProgress component with
Label="Loading..." but lacks an AriaLabel for screen readers; update the example
to pass an AriaLabel (e.g., AriaLabel="Loading progress") to LumexProgress so
assistive tech receives an explicit accessible name; ensure you add AriaLabel
alongside the existing Label parameter in the LumexProgress invocation and keep
the text meaningfully descriptive for screen-reader users.
docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Indeterminate.razor (1)

2-2: Consider adding AriaLabel for indeterminate state.

Indeterminate progress indicators especially benefit from accessible labels since they don't convey numeric progress. An AriaLabel would help screen reader users understand the purpose.

Suggested improvement
-    <LumexProgress IsIndeterminate="true" Color="@ThemeColor.Primary" Size="@Size.Small" />
+    <LumexProgress IsIndeterminate="true" Color="@ThemeColor.Primary" Size="@Size.Small" AriaLabel="Loading..." />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Indeterminate.razor`
at line 2, Add an accessible label to the indeterminate progress so screen
readers know its purpose: update the LumexProgress usage (the instance with
IsIndeterminate="true", Color="@ThemeColor.Primary", Size="@Size.Small") to
include the AriaLabel property with a meaningful string (e.g., "Loading" or
"Loading content") or a bound resource/parameter so the indeterminate state is
announced to assistive technology.
tests/LumexUI.Tests/Components/Progress/ProgressTests.cs (2)

117-127: Add a regression test for IsIndeterminate + DisableAnimation.

This interaction is currently untested and would catch animation-leak regressions.

🧪 Suggested test
 	[Fact]
 	public void Progress_IsIndeterminate_ShouldHaveAnimateProgressLoading()
 	{
 		var cut = RenderComponent<LumexProgress>( p => p
 			.Add( p => p.IsIndeterminate, true )
 		);

 		var indicator = cut.FindBySlot( "indicator" );

 		indicator.ClassList.Should().Contain( "animate-progress-loading" );
 	}
+
+	[Fact]
+	public void Progress_IsIndeterminate_WithDisableAnimation_ShouldDisableAnimation()
+	{
+		var cut = RenderComponent<LumexProgress>( p => p
+			.Add( p => p.IsIndeterminate, true )
+			.Add( p => p.DisableAnimation, true )
+		);
+
+		var indicator = cut.FindBySlot( "indicator" );
+		indicator.ClassList.Should().Contain( "!animate-none" );
+		indicator.ClassList.Should().NotContain( "animate-progress-loading" );
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/LumexUI.Tests/Components/Progress/ProgressTests.cs` around lines 117 -
127, Add a regression test to verify the interaction between
LumexProgress.IsIndeterminate and LumexProgress.DisableAnimation: create a test
similar to Progress_IsIndeterminate_ShouldHaveAnimateProgressLoading that
renders LumexProgress with both IsIndeterminate = true and DisableAnimation =
true, find the indicator slot (indicator) and assert that the
"animate-progress-loading" class is NOT present; also add a complementary
assertion ensuring when DisableAnimation = false the class is present to cover
both behaviors.

253-266: Add coverage for fractional ARIA values.

Current ARIA tests only validate integer inputs; the component API accepts double.

🧪 Suggested test
 	[Fact]
 	public void Progress_ShouldHaveCorrectAriaAttributes()
 	{
 		var cut = RenderComponent<LumexProgress>( p => p
 			.Add( p => p.Value, 50 )
 			.Add( p => p.MaxValue, 100 )
 		);

 		var base_ = cut.FindBySlot( "base" );
 		base_.GetAttribute( "role" ).Should().Be( "progressbar" );
 		base_.GetAttribute( "aria-valuenow" ).Should().Be( "50" );
 		base_.GetAttribute( "aria-valuemin" ).Should().Be( "0" );
 		base_.GetAttribute( "aria-valuemax" ).Should().Be( "100" );
 	}
+
+	[Fact]
+	public void Progress_WithFractionalRange_ShouldExposeFractionalAriaValues()
+	{
+		var cut = RenderComponent<LumexProgress>( p => p
+			.Add( p => p.MinValue, 0.5 )
+			.Add( p => p.MaxValue, 1.5 )
+			.Add( p => p.Value, 1.25 )
+		);
+
+		var base_ = cut.FindBySlot( "base" );
+		base_.GetAttribute( "aria-valuenow" ).Should().Be( "1.25" );
+		base_.GetAttribute( "aria-valuemin" ).Should().Be( "0.5" );
+		base_.GetAttribute( "aria-valuemax" ).Should().Be( "1.5" );
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/LumexUI.Tests/Components/Progress/ProgressTests.cs` around lines 253 -
266, Add a new unit test in ProgressTests.cs (alongside
Progress_ShouldHaveCorrectAriaAttributes) that renders LumexProgress with
fractional double values (e.g., Value = 12.34 and MaxValue = 100.5) and asserts
the base slot's aria attributes: role == "progressbar", aria-valuenow == "12.34"
(matching the component's string formatting), aria-valuemin == "0" and
aria-valuemax == "100.5"; reference the existing test name
Progress_ShouldHaveCorrectAriaAttributes, the LumexProgress component, and the
"base" slot to locate where to add the new test.
src/LumexUI/Styles/Progress.cs (1)

87-108: Keep indicator radius aligned with track radius.

Radius variants currently style only the track; the indicator keeps rounded-full, which can look off for Radius.None/Small/Medium/Large.

♻️ Suggested refactor
 					[nameof( Radius.None )] = new SlotCollection
 					{
 						[nameof( ProgressSlots.Track )] = "rounded-none",
+						[nameof( ProgressSlots.Indicator )] = "rounded-none",
 					},
 					[nameof( Radius.Small )] = new SlotCollection
 					{
 						[nameof( ProgressSlots.Track )] = "rounded-sm",
+						[nameof( ProgressSlots.Indicator )] = "rounded-sm",
 					},
 					[nameof( Radius.Medium )] = new SlotCollection
 					{
 						[nameof( ProgressSlots.Track )] = "rounded-md",
+						[nameof( ProgressSlots.Indicator )] = "rounded-md",
 					},
 					[nameof( Radius.Large )] = new SlotCollection
 					{
 						[nameof( ProgressSlots.Track )] = "rounded-lg",
+						[nameof( ProgressSlots.Indicator )] = "rounded-lg",
 					},
 					[nameof( Radius.Full )] = new SlotCollection
 					{
 						[nameof( ProgressSlots.Track )] = "rounded-full",
+						[nameof( ProgressSlots.Indicator )] = "rounded-full",
 					},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/LumexUI/Styles/Progress.cs` around lines 87 - 108, The radius variants
currently only set the track's classes, so the indicator stays rounded-full and
mismatches for Radius.None/Small/Medium/Large; update the VariantValueCollection
for nameof(LumexProgress.Radius) to include matching SlotCollection entries for
both nameof(ProgressSlots.Track) and nameof(ProgressSlots.Indicator) (e.g.,
"rounded-none", "rounded-sm", "rounded-md", "rounded-lg", "rounded-full") so the
indicator radius aligns with the track for each Radius value in the
LumexProgress.Radius mapping.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/LumexUI.Docs.Client/Pages/Components/Progress/Progress.razor`:
- Line 93: The description string in Progress.razor currently reads "Progress
display the progress..." which is grammatically incorrect; update the
description property (the value assigned to description) to use either "Progress
displays the progress of a task or operation, and can also be used as animated
loading indicators." or "Progress bars display the progress of a task or
operation, and can also be used as animated loading indicators." so the subject
and verb agree (edit the string literal used for description).
- Line 11: Update the docs to use the correct parameter name AriaLabel (not
AreaLabel): change both occurrences in Progress.razor documentation text to
reference AriaLabel and mention passing AriaLabel when Label is not provided;
ensure the accessibility note and any examples consistently match the
LumexProgress component parameter AriaLabel defined in LumexProgress.razor.cs.

In `@src/LumexUI/Components/Progress/LumexProgress.razor`:
- Around line 11-15: The ARIA attributes are truncating fractional values and
emitting determinate text in indeterminate mode; update the attributes in
LumexProgress.razor to use the original double values (do not cast ClampedValue,
MinValue, MaxValue to int) and format them as strings preserving fractional
precision (e.g., invariant/culture-aware ToString with an appropriate numeric
format) for aria-valuenow, aria-valuemin and aria-valuemax, and ensure
aria-valuetext is only emitted when IsIndeterminate is false (return null or
empty when IsIndeterminate is true) so indeterminate progressbars do not
announce a determinate percentage; keep references to ClampedValue, MinValue,
MaxValue, IsIndeterminate and ValueText/ComputedAriaLabel when making the
changes.

In `@src/LumexUI/Styles/Progress.cs`:
- Around line 111-125: The DisableAnimation variant currently only negates
transitions but does not remove the indeterminate animation class set by
IsIndeterminate, so add a negation for the animation class: in the
VariantValueCollection for LumexProgress.DisableAnimation update the
SlotCollection entry for ProgressSlots.Indicator to remove the
animate-progress-loading class (e.g. set it to "!animate-progress-loading" or
combine "!animate-progress-loading !transition-none" if you want to keep
disabling transitions too) so the indeterminate animation is actually disabled
when both flags are set.

---

Nitpick comments:
In
`@docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Indeterminate.razor`:
- Line 2: Add an accessible label to the indeterminate progress so screen
readers know its purpose: update the LumexProgress usage (the instance with
IsIndeterminate="true", Color="@ThemeColor.Primary", Size="@Size.Small") to
include the AriaLabel property with a meaningful string (e.g., "Loading" or
"Loading content") or a bound resource/parameter so the indeterminate state is
announced to assistive technology.

In `@docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Label.razor`:
- Line 2: The Progress example uses the LumexProgress component with
Label="Loading..." but lacks an AriaLabel for screen readers; update the example
to pass an AriaLabel (e.g., AriaLabel="Loading progress") to LumexProgress so
assistive tech receives an explicit accessible name; ensure you add AriaLabel
alongside the existing Label parameter in the LumexProgress invocation and keep
the text meaningfully descriptive for screen-reader users.

In `@src/LumexUI/Styles/Progress.cs`:
- Around line 87-108: The radius variants currently only set the track's
classes, so the indicator stays rounded-full and mismatches for
Radius.None/Small/Medium/Large; update the VariantValueCollection for
nameof(LumexProgress.Radius) to include matching SlotCollection entries for both
nameof(ProgressSlots.Track) and nameof(ProgressSlots.Indicator) (e.g.,
"rounded-none", "rounded-sm", "rounded-md", "rounded-lg", "rounded-full") so the
indicator radius aligns with the track for each Radius value in the
LumexProgress.Radius mapping.

In `@tests/LumexUI.Tests/Components/Progress/ProgressTests.cs`:
- Around line 117-127: Add a regression test to verify the interaction between
LumexProgress.IsIndeterminate and LumexProgress.DisableAnimation: create a test
similar to Progress_IsIndeterminate_ShouldHaveAnimateProgressLoading that
renders LumexProgress with both IsIndeterminate = true and DisableAnimation =
true, find the indicator slot (indicator) and assert that the
"animate-progress-loading" class is NOT present; also add a complementary
assertion ensuring when DisableAnimation = false the class is present to cover
both behaviors.
- Around line 253-266: Add a new unit test in ProgressTests.cs (alongside
Progress_ShouldHaveCorrectAriaAttributes) that renders LumexProgress with
fractional double values (e.g., Value = 12.34 and MaxValue = 100.5) and asserts
the base slot's aria attributes: role == "progressbar", aria-valuenow == "12.34"
(matching the component's string formatting), aria-valuemin == "0" and
aria-valuemax == "100.5"; reference the existing test name
Progress_ShouldHaveCorrectAriaAttributes, the LumexProgress component, and the
"base" slot to locate where to add the new test.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 546a045 and 31860f2.

📒 Files selected for processing (21)
  • docs/LumexUI.Docs.Client/Common/Navigation/NavigationStore.cs
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Colors.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/CustomStyles.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Indeterminate.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Label.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Sizes.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Usage.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Value.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Colors.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/CustomStyles.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Indeterminate.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Label.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Sizes.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Usage.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Value.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Progress.razor
  • src/LumexUI/Components/Progress/LumexProgress.razor
  • src/LumexUI/Components/Progress/LumexProgress.razor.cs
  • src/LumexUI/Components/Progress/ProgressSlots.cs
  • src/LumexUI/Styles/Progress.cs
  • tests/LumexUI.Tests/Components/Progress/ProgressTests.cs
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/LumexUI.Docs.Client/Common/Navigation/NavigationStore.cs

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
docs/LumexUI.Docs.Client/Pages/Components/Progress/Progress.razor (1)

11-11: ⚠️ Potential issue | 🟡 Minor

Fix typo: AreaLabel should be AriaLabel.

The property name AreaLabel on line 11 is incorrect. It should be AriaLabel to match the actual component parameter and the correct usage on line 41.

🐛 Proposed fix
-            Note: Make sure to pass the <code>AreaLabel</code> prop when the <code>Label</code> prop is not provided. This is required for accessibility.
+            Note: Make sure to pass the <code>AriaLabel</code> prop when the <code>Label</code> prop is not provided. This is required for accessibility.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/LumexUI.Docs.Client/Pages/Components/Progress/Progress.razor` at line
11, Typo: change the documentation text that references the prop name
"AreaLabel" to the correct prop "AriaLabel" so it matches the component
parameter and usage of "Label" in the same file; update the sentence that
currently reads "pass the AreaLabel prop" to "pass the AriaLabel prop" to ensure
consistency with the Progress component's AriaLabel parameter and other
references in the file.
🧹 Nitpick comments (1)
docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Label.razor (1)

3-3: Minor formatting inconsistency.

Other PreviewCodes files use @new(name: null, snippet: "...") without spaces inside the parentheses. Consider aligning for consistency.

✨ Suggested fix
-<PreviewCode Code="@new( name: null, snippet: "Progress.Code.Label" )">
+<PreviewCode Code="@new(name: null, snippet: "Progress.Code.Label")">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Label.razor`
at line 3, The PreviewCode instantiation currently has inconsistent spacing:
replace the spaced form used in PreviewCodes ("@new( name: null, snippet:
\"Progress.Code.Label\" )") with the consistent formatting used elsewhere by
changing the call to the compact form (e.g., use `@new`(name: null, snippet:
"Progress.Code.Label")) so the PreviewCode Code attribute matches other
PreviewCodes; update the occurrence in Label.razor where PreviewCode Code="@new(
name: null, snippet: "Progress.Code.Label" )" is declared.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@docs/LumexUI.Docs.Client/Pages/Components/Progress/Progress.razor`:
- Line 11: Typo: change the documentation text that references the prop name
"AreaLabel" to the correct prop "AriaLabel" so it matches the component
parameter and usage of "Label" in the same file; update the sentence that
currently reads "pass the AreaLabel prop" to "pass the AriaLabel prop" to ensure
consistency with the Progress component's AriaLabel parameter and other
references in the file.

---

Nitpick comments:
In `@docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Label.razor`:
- Line 3: The PreviewCode instantiation currently has inconsistent spacing:
replace the spaced form used in PreviewCodes ("@new( name: null, snippet:
\"Progress.Code.Label\" )") with the consistent formatting used elsewhere by
changing the call to the compact form (e.g., use `@new`(name: null, snippet:
"Progress.Code.Label")) so the PreviewCode Code attribute matches other
PreviewCodes; update the occurrence in Label.razor where PreviewCode Code="@new(
name: null, snippet: "Progress.Code.Label" )" is declared.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 31860f2 and b043dda.

📒 Files selected for processing (18)
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Colors.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/CustomStyles.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Indeterminate.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Label.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Sizes.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Usage.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Value.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Colors.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/CustomStyles.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Indeterminate.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Label.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Sizes.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Usage.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Value.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Progress.razor
  • src/LumexUI/Components/Progress/LumexProgress.razor
  • src/LumexUI/Styles/Progress.cs
  • src/LumexUI/Styles/_theme.css
🚧 Files skipped from review as they are similar to previous changes (11)
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/CustomStyles.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Colors.razor
  • src/LumexUI/Styles/Progress.cs
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Usage.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/CustomStyles.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Usage.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Value.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Indeterminate.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Label.razor
  • src/LumexUI/Components/Progress/LumexProgress.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Examples/Value.razor

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
docs/LumexUI.Docs.Client/Pages/Components/Progress/Progress.razor (1)

11-11: Use consistent Blazor terminology: replace prop with parameter.

Lines 11, 27, and 41 use React-style wording (prop) while the rest of the documentation uses parameter. Keeping this consistent avoids confusion for Blazor developers.

Suggested doc wording update
-            Note: Make sure to pass the <code>AriaLabel</code> prop when the <code>Label</code> prop is not provided. This is required for accessibility.
+            Note: Make sure to pass the <code>AriaLabel</code> parameter when the <code>Label</code> parameter is not provided. This is required for accessibility.
-            You can use the <code>IsIndeterminate</code> prop to display an indeterminate progress bar. This is useful when you don't know how long an operation will take.
+            You can use the <code>IsIndeterminate</code> parameter to display an indeterminate progress bar. This is useful when you don't know how long an operation will take.
-            Note: If you pass the <code>Label</code> prop you don't need to pass <code>AriaLabel</code> prop anymore.
+            Note: If you pass the <code>Label</code> parameter, you don't need to pass the <code>AriaLabel</code> parameter anymore.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/LumexUI.Docs.Client/Pages/Components/Progress/Progress.razor` at line
11, Replace the React-style word "prop" with Blazor terminology "parameter" in
the Progress component docs—update the sentences that reference AriaLabel and
Label (e.g., "AriaLabel prop" and "Label prop") to use "parameter" instead so
wording is consistent across Progress.razor; ensure all occurrences (notably the
instances at the current lines referencing AriaLabel and Label) are changed and
run a quick spellcheck to keep documentation consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@docs/LumexUI.Docs.Client/Pages/Components/Progress/Progress.razor`:
- Line 11: Replace the React-style word "prop" with Blazor terminology
"parameter" in the Progress component docs—update the sentences that reference
AriaLabel and Label (e.g., "AriaLabel prop" and "Label prop") to use "parameter"
instead so wording is consistent across Progress.razor; ensure all occurrences
(notably the instances at the current lines referencing AriaLabel and Label) are
changed and run a quick spellcheck to keep documentation consistent.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b043dda and 2ead3f4.

📒 Files selected for processing (2)
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Label.razor
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/Progress.razor
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/LumexUI.Docs.Client/Pages/Components/Progress/PreviewCodes/Label.razor

@kevinvenclovas
Copy link
Copy Markdown
Author

@desmondinho Reworked the progress component to match the HeroUI. Please let me know if I should adjust anything else

@desmondinho
Copy link
Copy Markdown
Contributor

desmondinho commented Mar 4, 2026

@desmondinho Reworked the progress component to match the HeroUI. Please let me know if I should adjust anything else

Hey! Sorry, I missed the notification somehow :/ Thank you for addressing the comments. I will check both your PRs tomorrow

Edit: I've just realized that the other one has already been reviewed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that a couple of things are missing or slightly off, so I will take a closer look tomorrow. I can also apply the changes in this file myself if you'd like

@desmondinho
Copy link
Copy Markdown
Contributor

desmondinho commented Mar 5, 2026

Hey @kevinvenclovas,

Very good job! We are almost done with this component. Thank you very much for contributing ❤️

@kevinvenclovas
Copy link
Copy Markdown
Author

@desmondinho I resolved your last requested changes. Please take a look and if you want you can finalize the component by yourself

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants