Skip to content

Apply BitFileInput improvements (#12742) - #12744

Merged
msynk merged 17 commits into
bitfoundation:developfrom
msynk:12742-blazorui-fileinput-choicegroup-improvements
Jul 28, 2026
Merged

Apply BitFileInput improvements (#12742)#12744
msynk merged 17 commits into
bitfoundation:developfrom
msynk:12742-blazorui-fileinput-choicegroup-improvements

Conversation

@msynk

@msynk msynk commented Jul 21, 2026

Copy link
Copy Markdown
Member

closes #12742

Summary by CodeRabbit

  • New Features
    • Expanded FileInput options: camera/microphone capture, directory selection, previews, image width/height decoding, and directory-aware drag/drop expansion.
    • Added richer validation and constraints (extensions/MIME support, custom per-file validator, size/count/duplicate limits) with new OnInvalid and OnRemove callbacks.
    • Improved metadata (preview URL, last-modified info).
  • Accessibility
    • Updated ARIA labeling/descriptions, list semantics, and added polite live-region announcements.
  • Styling/Theming
    • Added BitFileInputClassStyles and refreshed UI styling via CSS variables.
  • Documentation / Demo
    • Reworked the FileInput demo and samples, plus expanded “class-styles” guidance.

@msynk
msynk requested a review from yasmoradi July 21, 2026 14:50
@msynk
msynk requested a review from mhrastegari July 21, 2026 14:50
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d5ca0a63-7cb0-47ae-b695-88bd5182dd08

📥 Commits

Reviewing files that changed from the base of the PR and between 826c1ad and 737e5b0.

📒 Files selected for processing (16)
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputClassStyles.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputInfo.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputJsRuntimeExtensions.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.scss
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/ThemingPage.razor
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Bit.BlazorUI.Tests.csproj
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitComponentCssVariablesContractTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/component-css-variables.md

Walkthrough

BitFileInput now supports richer validation, previews, image metadata, directory and capture selection, asynchronous removal, accessibility wiring, customizable styling, expanded demos, and broader automated coverage.

Changes

BitFileInput improvements

Layer / File(s) Summary
Component API and validation
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/*
Adds capture, directory, preview, styling, validation-limit, callback, metadata, and asynchronous file-management capabilities.
Browser file lifecycle and interop
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts, BitFileInputJsRuntimeExtensions.cs
Adds image decoding, preview URL management, drag/drop normalization, directory traversal, and per-file browser removal.
Rendered markup and theming
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/*, src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/component-css-variables.md
Adds ARIA relationships, live announcements, list semantics, templated styling hooks, previews, disabled states, and CSS variables.
Demo examples and metadata
src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/*
Expands routes, examples, documentation, samples, event handling, accessibility scenarios, theming, sizing, icons, and RTL coverage.
Behavior and rendering tests
src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs
Adds coverage for accept handling, accessibility, removal callbacks, validation recovery, browser attributes, styling, icons, and list roles.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant BitFileInput
  participant FileInputJS
  participant Browser
  User->>BitFileInput: Select, drop, paste, or remove files
  BitFileInput->>FileInputJS: Configure selection and drag/drop behavior
  FileInputJS->>Browser: Read files, directories, previews, and dimensions
  Browser-->>BitFileInput: Return file metadata and validation inputs
  BitFileInput->>BitFileInput: Validate files and recompute list limits
  BitFileInput-->>User: Render files, errors, announcements, and callbacks
Loading

Suggested reviewers: yasmoradi, mhrastegari

Poem

I’m a bunny with files in my den,
Previewing pictures again and again.
I hop through each folder,
Keep errors in order,
And announce every change with a grin. 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.68% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly names the main change and stays concise.
Linked Issues check ✅ Passed The PR adds BitFileInput features, demo examples, and updated descriptions requested by issue #12742.
Out of Scope Changes check ✅ Passed The extra tests and theme/docs updates support the BitFileInput work and don't appear unrelated.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@msynk

msynk commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full-review

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

@msynk: Starting a full review of the PR, including all changes and their interactions with the existing codebase.

✅ Action performed

Full review finished.


Your plan includes PR reviews subject to rate limits. More reviews will be available in 8 minutes.

@msynk

msynk commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full-review

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

@msynk: Starting a fresh full review of the PR, including all changes and their interactions with the existing codebase.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts (1)

15-25: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Index can collide after removeFile + append.

lastIndex is derived from the current count of items for id, not the max existing index. After a file is removed mid-list and then more files are appended, the new item's index can collide with a remaining item's index (different fileId, same id+index). This metadata is returned to the Blazor side, so any consumer relying on index for ordering/keys can get duplicate/inconsistent values.

Repro: append 3 files (indices 0,1,2) → remove the item at index 1 → append 1 more file → new item gets index 0 + 2 = 2, colliding with the surviving item at index 2.

🐛 Proposed fix — derive next index from max existing index, not count
-            const lastIndex = append ? FileInput._fileInputs.filter(f => f.id === id).length : 0;
+            const existingItems = FileInput._fileInputs.filter(f => f.id === id);
+            const lastIndex = append && existingItems.length > 0
+                ? Math.max(...existingItems.map(f => f.index)) + 1
+                : 0;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts` around
lines 15 - 25, Update the `lastIndex` calculation in the file-mapping flow to
derive the next index from the maximum existing `index` for the same `id`,
rather than the current item count; use zero as the starting offset when no
items exist. Preserve the existing `index + lastIndex` assignment and all other
file metadata behavior.
🧹 Nitpick comments (1)
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor (1)

34-35: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Avoid setting both aria-label and aria-labelledby simultaneously.

When AriaLabel is set and the label button is rendered, both attributes end up on the <input>. Per spec, aria-labelledby will take precedence over aria-label if both are applied, making the user-supplied AriaLabel silently ignored in that case.

♻️ Proposed fix
-           aria-label="`@AriaLabel`"
-           aria-labelledby="@(LabelTemplate is null && HideLabel is false ? _buttonId : null)"
+           aria-label="@(LabelTemplate is null && HideLabel is false ? null : AriaLabel)"
+           aria-labelledby="@(LabelTemplate is null && HideLabel is false ? _buttonId : null)"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor`
around lines 34 - 35, Update the accessibility attributes on the input in
BitFileInput so aria-labelledby is assigned only when AriaLabel is not set,
while preserving the existing label-button condition. Ensure AriaLabel takes
precedence and never renders simultaneously with aria-labelledby.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor`:
- Around line 76-89: Update the remove-button markup in BitFileInput so it is
disabled and cannot invoke RemoveFile(file) when IsEnabled is false. Preserve
the existing enabled-state behavior, styling, and accessibility attributes.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs`:
- Around line 252-256: Update RemoveFile to return immediately when IsEnabled is
false, before performing any file-removal logic. Keep the existing empty-file
guard and removal behavior unchanged when the component is enabled.
- Around line 252-281: Update RemoveFile after mutating _files to explicitly
reset each remaining file’s IsValid state and MaxCountErrorMessage, then reapply
the MaxCount validation by position so only files beyond MaxCount remain
invalid. Ensure this recalculation occurs before invoking OnChange and
StateHasChanged, while preserving the existing removal callbacks and JavaScript
operations.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts`:
- Around line 45-66: Update onDragEnter and onDragLeave to also return
immediately when inputElement.disabled is true, preventing drag highlight
classes and dragCounter changes for disabled inputs while preserving the
existing file checks and enabled-input behavior.

---

Outside diff comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts`:
- Around line 15-25: Update the `lastIndex` calculation in the file-mapping flow
to derive the next index from the maximum existing `index` for the same `id`,
rather than the current item count; use zero as the starting offset when no
items exist. Preserve the existing `index + lastIndex` assignment and all other
file metadata behavior.

---

Nitpick comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor`:
- Around line 34-35: Update the accessibility attributes on the input in
BitFileInput so aria-labelledby is assigned only when AriaLabel is not set,
while preserving the existing label-button condition. Ensure AriaLabel takes
precedence and never renders simultaneously with aria-labelledby.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 0fa0f64f-63d1-4da0-b8e9-4874782194c8

📥 Commits

Reviewing files that changed from the base of the PR and between f1b4232 and 8957ae6.

📒 Files selected for processing (12)
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputClassStyles.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputInfo.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputJsRuntimeExtensions.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.scss
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs

@msynk

msynk commented Jul 27, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full-review

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

@msynk: Starting a fresh full review of the PR, including the complete change set and cross-file interactions.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (6)
src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs (2)

516-527: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

This test no longer exercises removal.

RemoveFile now returns at if (_files.Any() is false) return;, so with an empty file list nothing after the guard runs — the assertion is trivially true. It still guards against a throw, but consider renaming it to reflect that (e.g. ...ShouldBeNoOpWhenNoFilesSelected) so the gap isn't mistaken for real removal coverage.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs`
around lines 516 - 527, Rename
BitFileInputRemoveFileShouldClearAllFilesWhenNullProvided to reflect that
calling RemoveFile(null) with no selected files is a no-op, such as a name
ending in ShouldBeNoOpWhenNoFilesSelected. Keep the existing empty-state setup
and assertion unchanged.

647-719: 🎯 Functional Correctness | 🔵 Trivial | 🏗️ Heavy lift

Test gap: none of the new validation logic is covered.

The added tests are all render/attribute assertions. The riskiest new code in this PR — ApplyListValidations (MaxCount/MaxTotalSize re-validation and the ListValidationFailed reset after removals), MinSize, FileValidator including its exception path, duplicate detection, and the OnRemove/OnInvalid callback ordering — has no coverage. Since these paths run through HandleOnChange, they need a stubbed BitBlazorUI.FileInput.setup via bunit's JSInterop. Happy to draft those tests if useful.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs`
around lines 647 - 719, Add bUnit tests for BitFileInput.HandleOnChange using a
JSInterop stub for BitBlazorUI.FileInput.setup, covering ApplyListValidations
MaxCount/MaxTotalSize revalidation, ListValidationFailed reset after removals,
MinSize, FileValidator success and exception paths, duplicate detection, and
OnRemove/OnInvalid callback ordering. Assert each validation result and callback
sequence while preserving the existing render and attribute tests.
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor (1)

19-24: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

AriaLabel on the browse button overrides its visible text.

The button renders visible text (Label ?? "Browse") and also gets aria-label="@AriaLabel". When AriaLabel is set and doesn't contain the visible label, the accessible name no longer matches the visible one (WCAG 2.5.3 Label in Name), which breaks speech-input users. Consider scoping AriaLabel to the input element only, or documenting that it replaces the button's accessible name.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor`
around lines 19 - 24, Update the browse button markup in BitFileInput so
AriaLabel does not override the accessible name of its visible Label ?? "Browse"
text; scope AriaLabel to the file input element instead, or otherwise ensure the
button’s accessible name contains its visible label.
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.scss (1)

78-82: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

.bit-fin-dsc borrows --bit-fin-fs-fontsize, which is the file-size variable.

Coupling the description size to the file-size token means a theme can't tune one without the other. A dedicated --bit-fin-dsc-fontsize in each size class would keep the two independent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.scss`
around lines 78 - 82, Update the .bit-fin-dsc rule to use a dedicated
--bit-fin-dsc-fontsize token, and define that token independently in each
relevant size class alongside the existing file-size variable. Remove the
description’s dependency on --bit-fin-fs-fontsize while preserving the current
sizing behavior through matching defaults.
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs (1)

596-635: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

HandleOnChange has no IsEnabled guard, unlike the other public entry points.

The DOM disabled attribute and the JS drop/paste handlers both gate on disabled state, so this isn't reachable today. Still, a synthetic change dispatch (or a future markup change that drops the disabled binding) would bypass every guard. A single if (IsEnabled is false) return; next to the IsDisposed check keeps the invariant local.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs`
around lines 596 - 635, Update HandleOnChange to return immediately when
IsEnabled is false, placing the guard next to the existing IsDisposed check.
Preserve the current file processing behavior for enabled, non-disposed inputs.
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts (1)

291-319: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Unbounded recursion/enumeration when expanding dropped directories.

collectEntry recurses with no depth or file-count cap, so a deep or very large dropped tree keeps the UI awaiting indefinitely and can exhaust memory before setFiles ever runs. Consider a depth limit and/or a max-file cutoff (and ideally aligning the cutoff with MaxCount).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts` around
lines 291 - 319, Update FileInput.collectEntry to enforce bounded directory
traversal, propagating the current depth and accumulated file limit through
recursive calls. Stop reading or recursing once the configured maximum file
count, preferably aligned with MaxCount, is reached, and add a depth cap so
deeply nested dropped directories terminate before setFiles is delayed
indefinitely.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor`:
- Around line 59-69: Update the Files list rendering in BitFileInput so each
iteration always has a keyed wrapper with role="listitem" surrounding both the
FileViewTemplate and default rendering branches. Move the existing
`@key`="file.FileId" and role="listitem" attributes outside the conditional while
preserving the current template and fallback content.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts`:
- Around line 16-17: Update the lastIndex calculation in the FileInput
initialization flow to determine the maximum existing index using reduce rather
than spreading existingItems into Math.max. Preserve the current empty-list
fallback of 0 and increment the computed maximum by 1 for appended items.

---

Nitpick comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor`:
- Around line 19-24: Update the browse button markup in BitFileInput so
AriaLabel does not override the accessible name of its visible Label ?? "Browse"
text; scope AriaLabel to the file input element instead, or otherwise ensure the
button’s accessible name contains its visible label.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs`:
- Around line 596-635: Update HandleOnChange to return immediately when
IsEnabled is false, placing the guard next to the existing IsDisposed check.
Preserve the current file processing behavior for enabled, non-disposed inputs.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.scss`:
- Around line 78-82: Update the .bit-fin-dsc rule to use a dedicated
--bit-fin-dsc-fontsize token, and define that token independently in each
relevant size class alongside the existing file-size variable. Remove the
description’s dependency on --bit-fin-fs-fontsize while preserving the current
sizing behavior through matching defaults.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts`:
- Around line 291-319: Update FileInput.collectEntry to enforce bounded
directory traversal, propagating the current depth and accumulated file limit
through recursive calls. Stop reading or recursing once the configured maximum
file count, preferably aligned with MaxCount, is reached, and add a depth cap so
deeply nested dropped directories terminate before setFiles is delayed
indefinitely.

In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs`:
- Around line 516-527: Rename
BitFileInputRemoveFileShouldClearAllFilesWhenNullProvided to reflect that
calling RemoveFile(null) with no selected files is a no-op, such as a name
ending in ShouldBeNoOpWhenNoFilesSelected. Keep the existing empty-state setup
and assertion unchanged.
- Around line 647-719: Add bUnit tests for BitFileInput.HandleOnChange using a
JSInterop stub for BitBlazorUI.FileInput.setup, covering ApplyListValidations
MaxCount/MaxTotalSize revalidation, ListValidationFailed reset after removals,
MinSize, FileValidator success and exception paths, duplicate detection, and
OnRemove/OnInvalid callback ordering. Assert each validation result and callback
sequence while preserving the existing render and attribute tests.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 11cb2986-2535-4c4c-864d-d4b7b820dd1f

📥 Commits

Reviewing files that changed from the base of the PR and between f1b4232 and ea4e6f1.

📒 Files selected for processing (12)
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputClassStyles.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputInfo.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputJsRuntimeExtensions.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.scss
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs

Comment thread src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts Outdated
@msynk

msynk commented Jul 27, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full-review

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

@msynk: Starting a fresh full review of the complete change set and its cross-file interactions.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

♻️ Duplicate comments (2)
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts (1)

16-17: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Math.max(...) spread can throw RangeError for very large directory selections.

Still unaddressed from the earlier review: with Directory + Append, the existing item count can exceed the engine's argument limit. A reduce avoids it.

🐛 Proposed fix
-            const existingItems = append ? FileInput._fileInputs.filter(f => f.id === id) : [];
-            const lastIndex = existingItems.length ? Math.max(...existingItems.map(f => f.index)) + 1 : 0;
+            const existingItems = append ? FileInput._fileInputs.filter(f => f.id === id) : [];
+            const lastIndex = existingItems.reduce((max, f) => f.index > max ? f.index : max, -1) + 1;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts` around
lines 16 - 17, Update the lastIndex calculation in the FileInput initialization
flow to avoid spreading existingItems.map(...) into Math.max. Use a reduce-based
maximum over existingItems, preserving the current empty-list fallback of 0 and
incrementing the computed maximum by one for appended items.
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor (1)

59-69: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

role="list" still gets non-listitem children when FileViewTemplate is used.

The role="listitem" wrapper (and @key) only exists in the else branch, so a custom template produces an invalid ARIA list structure.

♿ Proposed fix
             `@foreach` (var file in Files)
             {
                 if (FileViewTemplate is not null)
                 {
-                    `@FileViewTemplate`(file)
+                    <div `@key`="file.FileId" role="listitem">
+                        `@FileViewTemplate`(file)
+                    </div>
                 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor`
around lines 59 - 69, Update the Files rendering loop in BitFileInput so every
direct child of the role="list" container, including custom FileViewTemplate
output, is wrapped in a keyed element with role="listitem". Preserve the
existing default file-content rendering and ensure `@key`="file.FileId" remains
applied per file.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor`:
- Around line 59-69: Update the Files rendering loop in BitFileInput so every
direct child of the role="list" container, including custom FileViewTemplate
output, is wrapped in a keyed element with role="listitem". Preserve the
existing default file-content rendering and ensure `@key`="file.FileId" remains
applied per file.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts`:
- Around line 16-17: Update the lastIndex calculation in the FileInput
initialization flow to avoid spreading existingItems.map(...) into Math.max. Use
a reduce-based maximum over existingItems, preserving the current empty-list
fallback of 0 and incrementing the computed maximum by one for appended items.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5c425802-92a8-400f-9a1b-a2fda16b0b79

📥 Commits

Reviewing files that changed from the base of the PR and between f1b4232 and ea4e6f1.

📒 Files selected for processing (12)
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputClassStyles.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputInfo.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputJsRuntimeExtensions.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.scss
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs

@msynk

msynk commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full-review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

@msynk: Starting a fresh full review of the complete change set and its cross-file interactions.

✅ Action performed

Full review finished.

…into 12742-blazorui-fileinput-choicegroup-improvements

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.scss (1)

210-217: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Visually-hidden live region can still wrap and clip its text.

With width: 1px; height: 1px; overflow: hidden and no white-space: nowrap, longer announcements are laid out in a 1px box; most screen readers still read it, but adding white-space: nowrap (and clip-path: inset(50%)) matches the standard sr-only recipe.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.scss`
around lines 210 - 217, Update the .bit-fin-lvr visually hidden live-region
styles to prevent announcement wrapping by adding white-space: nowrap and apply
clip-path: inset(50%) alongside the existing off-screen positioning and clipping
rules.
src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.cs (1)

663-670: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Non-image files get an "image could not be decoded" message.

Width/Height are also null for any non-image file, and drop/paste bypasses the Accept="image/*" dialog filter, so dropping a PDF into the demo reports a decoding failure. Gating on file.ContentType.StartsWith("image/") makes the sample read better.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.cs`
around lines 663 - 670, Update ValidateImageDimensions to check file.ContentType
before reporting image decoding or dimension errors. Only apply the existing
width/height validation when the content type starts with "image/"; allow
non-image files, including dropped or pasted files, to bypass this
image-specific validation.
src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs (1)

517-527: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Test passes vacuously.

With no files selected, RemoveFile early-returns on _files.Any() is false, so nothing about the clear-all path is exercised and Assert.IsEmpty holds trivially. Either rename it to reflect the "no-op when empty" contract, or seed files (via a JSInterop-backed change) and dispatch through component.InvokeAsync(() => instance.RemoveFile(null)) to actually cover clearing.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs`
around lines 517 - 527, Update
BitFileInputRemoveFileShouldClearAllFilesWhenNullProvided so it exercises the
clear-all behavior: seed the component with files using the existing
JSInterop-backed setup, then invoke RemoveFile(null) through
component.InvokeAsync and assert Files is empty; alternatively, if retaining an
empty initial state, rename the test to describe the no-op contract.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.scss`:
- Around line 210-217: Update the .bit-fin-lvr visually hidden live-region
styles to prevent announcement wrapping by adding white-space: nowrap and apply
clip-path: inset(50%) alongside the existing off-screen positioning and clipping
rules.

In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.cs`:
- Around line 663-670: Update ValidateImageDimensions to check file.ContentType
before reporting image decoding or dimension errors. Only apply the existing
width/height validation when the content type starts with "image/"; allow
non-image files, including dropped or pasted files, to bypass this
image-specific validation.

In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs`:
- Around line 517-527: Update
BitFileInputRemoveFileShouldClearAllFilesWhenNullProvided so it exercises the
clear-all behavior: seed the component with files using the existing
JSInterop-backed setup, then invoke RemoveFile(null) through
component.InvokeAsync and assert Files is empty; alternatively, if retaining an
empty initial state, rename the test to describe the no-op contract.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: aac685ff-35a0-4769-bdb3-a16dd275d342

📥 Commits

Reviewing files that changed from the base of the PR and between 826c1ad and ad634b8.

📒 Files selected for processing (12)
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputClassStyles.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputInfo.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputJsRuntimeExtensions.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.scss
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs

@msynk

msynk commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full-review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

@msynk: Starting a fresh full review of the complete change set and its cross-file interactions.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs (1)

517-537: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Missing test coverage for the new list-level/per-file validation and callback surface.

No tests exercise MaxCount, MaxTotalSize, MinSize, AllowDuplicates/DuplicateErrorMessage, FileValidator, OnRemove, or OnInvalid in BitFileInput.razor.cs. This is exactly the area where prior review rounds already caught real bugs (RemoveFile skipping the IsEnabled guard, and RemoveFile not recomputing MaxCount validity), so it's a high-value area to lock down with tests using the same Change() + bUnit JSInterop.Setup<BitFileInputInfo[]> pattern already used here (e.g., simulate selecting files beyond MaxCount/MaxTotalSize, remove one, and assert the remaining files' validity/OnInvalid payload).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs`
around lines 517 - 537, Expand BitFileInput tests around the existing Change()
and JSInterop.Setup<BitFileInputInfo[]> pattern to cover MaxCount, MaxTotalSize,
MinSize, AllowDuplicates with DuplicateErrorMessage, FileValidator, OnRemove,
and OnInvalid. Include selection and removal scenarios that verify validation
state and OnInvalid payloads are recomputed for remaining files, and assert
RemoveFile respects IsEnabled while preserving the existing null-removal
behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs`:
- Around line 359-396: Add an IsDisposed guard to RemoveFile, checking before
state mutation or JS interop and again after each awaited operation before
continuing with further JS calls, callbacks, validation,
InvokeChangeCallbacksAsync, or StateHasChanged. Preserve the existing removal
behavior while returning immediately once disposal is detected.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts`:
- Around line 153-170: Update the promise chain in onDrop so
FileInput.collectEntries(entries) calls setFiles(fallback) in a catch handler
when directory collection fails, while preserving the existing then behavior
that uses collected files when available and fallback otherwise.

---

Nitpick comments:
In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs`:
- Around line 517-537: Expand BitFileInput tests around the existing Change()
and JSInterop.Setup<BitFileInputInfo[]> pattern to cover MaxCount, MaxTotalSize,
MinSize, AllowDuplicates with DuplicateErrorMessage, FileValidator, OnRemove,
and OnInvalid. Include selection and removal scenarios that verify validation
state and OnInvalid payloads are recomputed for remaining files, and assert
RemoveFile respects IsEnabled while preserving the existing null-removal
behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 77cbeaef-1f2d-46a3-8ae7-c38986ef19b5

📥 Commits

Reviewing files that changed from the base of the PR and between 826c1ad and 14022c5.

📒 Files selected for processing (13)
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputClassStyles.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputInfo.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputJsRuntimeExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/component-css-variables.md
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.scss
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs
💤 Files with no reviewable changes (1)
  • src/BlazorUI/Bit.BlazorUI/component-css-variables.md

@msynk

msynk commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full-review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

@msynk: Starting a fresh full review of the complete change set and cross-file interactions.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.scss (1)

39-58: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

.files-info / .invalid-file look dead after the demo rewrite.

The rewritten BitFileInputDemo.razor no longer renders a files-info block or invalid-file element; consider dropping these rules.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.scss`
around lines 39 - 58, Remove the unused .files-info rule set, including its
nested strong, div, and .invalid-file styles, from the BitFileInputDemo
stylesheet because the rewritten demo no longer renders those elements.
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor (1)

73-82: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Preview alt duplicates the adjacent file name for screen readers.

The thumbnail is decorative next to the name text rendered right below it, so alt="@file.Name" causes the name to be announced twice. alt="" is the conventional choice here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor`
around lines 73 - 82, Update the preview <img> in the ShowPreview block of
BitFileInput so its alt attribute is empty, treating the thumbnail as decorative
and avoiding duplication with the adjacent file name text. Leave the preview
source and other image attributes unchanged.
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts (1)

20-31: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Returned items carry the raw File object across interop.

file: file is included in the objects returned to .NET; File has no own enumerable properties so it serializes to {} — harmless but pure overhead per selected file. Consider building the interop payload without it (keep f.file only in the local mapping used for readImageSize).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts` around
lines 20 - 31, The interop payload created in the file-selection mapping
includes the raw File object unnecessarily. Remove the file property from the
objects returned by the mapping, while retaining the File reference in the local
mapping used by readImageSize.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs`:
- Around line 322-331: Update BitFileInput.Reset to return immediately when
IsDisposed is true, before clearing files or performing JS interop. Preserve the
existing reset, announcement, and StateHasChanged flow for active instances,
including calls routed from Browse when AutoReset is enabled.

---

Nitpick comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor`:
- Around line 73-82: Update the preview <img> in the ShowPreview block of
BitFileInput so its alt attribute is empty, treating the thumbnail as decorative
and avoiding duplication with the adjacent file name text. Leave the preview
source and other image attributes unchanged.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts`:
- Around line 20-31: The interop payload created in the file-selection mapping
includes the raw File object unnecessarily. Remove the file property from the
objects returned by the mapping, while retaining the File reference in the local
mapping used by readImageSize.

In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.scss`:
- Around line 39-58: Remove the unused .files-info rule set, including its
nested strong, div, and .invalid-file styles, from the BitFileInputDemo
stylesheet because the rewritten demo no longer renders those elements.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 15a5eebd-7615-4c4f-beda-f62b803b2a1d

📥 Commits

Reviewing files that changed from the base of the PR and between 826c1ad and 139003f.

📒 Files selected for processing (13)
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputClassStyles.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputInfo.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputJsRuntimeExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/component-css-variables.md
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.scss
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs

@msynk

msynk commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full-review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

@msynk: Starting a fresh full review of the complete change set and cross-file interactions.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.cs (1)

663-673: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use an ordinal comparison for the MIME prefix check.

StartsWith(string) is culture-sensitive (CA1310). MIME types are ASCII protocol tokens, so ordinal is both correct and faster — and this snippet is copied verbatim into example12CsharpCode, so it's the pattern users will paste.

♻️ Proposed change
-        if (file.ContentType.StartsWith("image/") is false) return null;
+        if (file.ContentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase) is false) return null;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.cs`
around lines 663 - 673, Update the ContentType prefix check in
ValidateImageDimensions to use an explicit ordinal string comparison for the
"image/" MIME prefix, preserving the existing non-image early return and
validation behavior.
src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.samples.cs (1)

219-330: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Sample <style> block has already drifted from the demo's own SCSS.

The rules embedded here duplicate BitFileInputDemo.razor.scss, but the copies are not identical — the SCSS has .browse-file:hover, .remove-ico:hover and .file-info-name that this sample omits. Users copying the sample get a visibly different drop zone than the one rendered above it. Same applies to example26RazorCode vs the ::deep block. Worth keeping the two in sync (or generating one from the other).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.samples.cs`
around lines 219 - 330, Synchronize the embedded style blocks in
example20RazorCode and example26RazorCode with the demo’s
BitFileInputDemo.razor.scss, including the missing browse-file hover, remove-ico
hover, file-info-name, and corresponding ::deep rules. Ensure copied samples
render with the same styling as the demo, preferably by deriving the embedded
styles from the shared SCSS to prevent future drift.
src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs (1)

766-769: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Move the SetupFiles helper out of the middle of the test methods.

It sits between BitFileInputRemoveFileShouldRespectIsEnabled and the remaining [TestMethod]s; placing private helpers at the end of the class keeps the test list readable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs`
around lines 766 - 769, Move the private SetupFiles helper to the end of the
BitFileInputTests class, after all [TestMethod] methods, without changing its
implementation or callers.
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts (1)

105-128: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Drag highlight can stick when the drag is cancelled.

dragCounter is only decremented on dragleave/drop. Cancelling a drag with Esc (or a drag ending outside the window) leaves the counter positive and the drag classes/inline style applied until the next drop. A dragend/window-level drop listener calling removeDragState(true) would clear it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts` around
lines 105 - 128, Add cancellation cleanup for the drag state managed by
dragCounter: register dragend and window-level drop handlers that call
removeDragState(true). Ensure cancelled or externally completed drags clear the
drag classes and inline styles even without a preceding dragleave or drop, while
preserving existing onDragLeave and drop behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.scss`:
- Line 7: Update the repository’s Stylelint configuration to whitelist the
Blazor ::deep pseudo-element under selector-pseudo-element-no-unknown, reusing
the existing rule configuration and preserving validation for other unknown
pseudo-elements. Verify the configuration applies to SCSS files using ::deep,
including BitFileInputDemo.

---

Nitpick comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts`:
- Around line 105-128: Add cancellation cleanup for the drag state managed by
dragCounter: register dragend and window-level drop handlers that call
removeDragState(true). Ensure cancelled or externally completed drags clear the
drag classes and inline styles even without a preceding dragleave or drop, while
preserving existing onDragLeave and drop behavior.

In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.cs`:
- Around line 663-673: Update the ContentType prefix check in
ValidateImageDimensions to use an explicit ordinal string comparison for the
"image/" MIME prefix, preserving the existing non-image early return and
validation behavior.

In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.samples.cs`:
- Around line 219-330: Synchronize the embedded style blocks in
example20RazorCode and example26RazorCode with the demo’s
BitFileInputDemo.razor.scss, including the missing browse-file hover, remove-ico
hover, file-info-name, and corresponding ::deep rules. Ensure copied samples
render with the same styling as the demo, preferably by deriving the embedded
styles from the shared SCSS to prevent future drift.

In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs`:
- Around line 766-769: Move the private SetupFiles helper to the end of the
BitFileInputTests class, after all [TestMethod] methods, without changing its
implementation or callers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a0138d02-e873-495b-bf1c-ca7ff9135aee

📥 Commits

Reviewing files that changed from the base of the PR and between 826c1ad and c8d9a1f.

📒 Files selected for processing (13)
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputClassStyles.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputInfo.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputJsRuntimeExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/component-css-variables.md
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.scss
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs

@msynk

msynk commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full-review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

@msynk: Starting a fresh full review of the complete change set and its cross-file interactions.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs (1)

519-539: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reuse the new SetupFiles helper here.

This test still inlines the BitBlazorUI.FileInput.setup JSInterop registration that SetupFiles (line 1025) now encapsulates; every other new test uses the helper.

♻️ Proposed refactor
-        Context.JSInterop.Setup<BitFileInputInfo[]>("BitBlazorUI.FileInput.setup", _ => true)
-                         .SetResult([new() { Name = "file1.txt", Size = 10, FileId = "1" },
-                                     new() { Name = "file2.txt", Size = 20, FileId = "2" }]);
+        SetupFiles([new() { Name = "file1.txt", Size = 10, FileId = "1" },
+                    new() { Name = "file2.txt", Size = 20, FileId = "2" }]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs`
around lines 519 - 539, Update
BitFileInputRemoveFileShouldClearAllFilesWhenNullProvided to use the existing
SetupFiles helper for the BitBlazorUI.FileInput.setup registration, removing the
duplicated inline JSInterop setup while preserving the two-file test data and
assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.samples.cs`:
- Around line 85-96: The example12CsharpCode sample’s ValidateImageDimensions
method uses the culture-sensitive single-argument StartsWith overload. Update it
to match the runtime handler by using the StringComparison.OrdinalIgnoreCase
overload, preserving the existing validation behavior.

---

Nitpick comments:
In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs`:
- Around line 519-539: Update
BitFileInputRemoveFileShouldClearAllFilesWhenNullProvided to use the existing
SetupFiles helper for the BitBlazorUI.FileInput.setup registration, removing the
duplicated inline JSInterop setup while preserving the two-file test data and
assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 339690af-58b5-4b3c-b649-10b94ec8335a

📥 Commits

Reviewing files that changed from the base of the PR and between 826c1ad and 3fbcf6c.

📒 Files selected for processing (13)
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputClassStyles.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputInfo.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputJsRuntimeExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/component-css-variables.md
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.scss
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs

@msynk

msynk commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full-review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

@msynk: Starting a fresh full review of the complete change set and cross-file interactions.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs (2)

468-498: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Drag settings can go stale if parameters change while first-render setup is awaiting.

OnParametersSetAsync bails out when _dropZoneRef is null, but it still writes the new values into _allowDrop/_allowPaste/_expandDirectories. If a parameter change lands during the BitFileInputSetupDragDrop await, the JS side is initialized with the pre-change values while the fields already hold the new ones, so the equality check will suppress the later update. Re-syncing after the await closes the window.

Separately, dragClass/dragStyle are captured once, so a later Classes?.Dragging change is never propagated.

🐛 Proposed fix
         _dropZoneRef = await _js.BitFileInputSetupDragDrop(RootElement, _inputRef, dragClass, Styles?.Dragging,
                                                            _allowDrop, _allowPaste, _expandDirectories);
+
+        if (_allowDrop != AllowDrop || _allowPaste != AllowPaste || _expandDirectories != Directory)
+        {
+            _allowDrop = AllowDrop;
+            _allowPaste = AllowPaste;
+            _expandDirectories = Directory;
+
+            await _dropZoneRef.InvokeVoidAsync("update", _allowDrop, _allowPaste, _expandDirectories);
+        }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs`
around lines 468 - 498, Update the first-render setup in OnAfterRenderAsync so
that, after BitFileInputSetupDragDrop completes, it rechecks the current drag
parameters and invokes the drop-zone update when they differ from the values
used during initialization, ensuring changes that arrived during the await are
synchronized. Also track changes to Classes?.Dragging and Styles?.Dragging after
setup, updating the JS drag class/style through the existing drop-zone
integration rather than leaving the initially captured values stale.

88-97: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider [ResetClassBuilder] / [ResetStyleBuilder] on Classes / Styles.

Color and Size carry [ResetClassBuilder], but Classes?.Root (registered in RegisterCssClasses) and Styles?.Root (in RegisterCssStyles) are only recomputed when something else invalidates the builders. Swapping the Classes/Styles instance at runtime may not refresh the root class/style.

#!/bin/bash
# How do sibling components annotate Classes/Styles parameters?
rg -nP -B3 'public\s+Bit\w+ClassStyles\?\s+(Classes|Styles)\s*\{' --type=cs -g '!**/FileInput/**' | head -60
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs`
around lines 88 - 97, Annotate the Classes parameter with ResetClassBuilder and
the Styles parameter with ResetStyleBuilder in BitFileInput. Ensure replacing
either parameter invalidates its corresponding builder so Classes?.Root and
Styles?.Root are recomputed through RegisterCssClasses and RegisterCssStyles.
src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs (1)

519-763: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider covering the live-region text, not just its ARIA attributes.

BitFileInputShouldRenderAPoliteLiveRegion only asserts role/aria-live/aria-atomic. The Announce() logic (count text, invalid-count suffix, zero-width-space marker alternation) is the part most likely to regress silently — asserting .bit-fin-lvr text after a selection and after a removal would pin it down.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs`
around lines 519 - 763, Extend BitFileInputShouldRenderAPoliteLiveRegion to
assert the .bit-fin-lvr live-region text after files are selected and after a
file is removed. Verify the announced file count, invalid-count suffix when
applicable, and zero-width-space marker alternation produced by Announce(),
while retaining the existing role, aria-live, and aria-atomic assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs`:
- Around line 630-643: Update duplicate handling in the file-validation flow
around GetFileIdentity and ApplyListValidations so duplicate failures are
tracked as list-level validation, like ListValidationFailed. Re-run duplicate
detection when list validations are reapplied, and clear the stale duplicate
invalid state/message when the original file has been removed.

---

Nitpick comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs`:
- Around line 468-498: Update the first-render setup in OnAfterRenderAsync so
that, after BitFileInputSetupDragDrop completes, it rechecks the current drag
parameters and invokes the drop-zone update when they differ from the values
used during initialization, ensuring changes that arrived during the await are
synchronized. Also track changes to Classes?.Dragging and Styles?.Dragging after
setup, updating the JS drag class/style through the existing drop-zone
integration rather than leaving the initially captured values stale.
- Around line 88-97: Annotate the Classes parameter with ResetClassBuilder and
the Styles parameter with ResetStyleBuilder in BitFileInput. Ensure replacing
either parameter invalidates its corresponding builder so Classes?.Root and
Styles?.Root are recomputed through RegisterCssClasses and RegisterCssStyles.

In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs`:
- Around line 519-763: Extend BitFileInputShouldRenderAPoliteLiveRegion to
assert the .bit-fin-lvr live-region text after files are selected and after a
file is removed. Verify the announced file count, invalid-count suffix when
applicable, and zero-width-space marker alternation produced by Announce(),
while retaining the existing role, aria-live, and aria-atomic assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 13939925-81bb-4534-a715-2dfae346769c

📥 Commits

Reviewing files that changed from the base of the PR and between 826c1ad and cfdb134.

📒 Files selected for processing (13)
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputClassStyles.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputInfo.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputJsRuntimeExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/component-css-variables.md
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.scss
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs

@msynk

msynk commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full-review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

@msynk: Starting a fresh full review of the complete change set and its cross-file interactions.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (1)
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts (1)

42-50: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Unbounded concurrent image decoding.

Promise.all over every image kicks off all decodes at once. Combined with Directory selection (which the same PR adds and which can yield thousands of entries), this can spike memory hard. A small concurrency window keeps the cost bounded.

♻️ Proposed fix — bounded concurrency
             if (readImageDimensions) {
-                await Promise.all(files
-                    .filter(f => f.type.startsWith('image/'))
-                    .map(async f => {
-                        const size = await FileInput.readImageSize(f.file);
-                        f.width = size.width;
-                        f.height = size.height;
-                    }));
+                const images = files.filter(f => f.type.startsWith('image/'));
+                const limit = 8;
+                let next = 0;
+                const worker = async () => {
+                    while (next < images.length) {
+                        const f = images[next++];
+                        const size = await FileInput.readImageSize(f.file);
+                        f.width = size.width;
+                        f.height = size.height;
+                    }
+                };
+                await Promise.all(Array.from({ length: Math.min(limit, images.length) }, worker));
             }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts` around
lines 42 - 50, Update the image-dimension processing in BitFileInput so
FileInput.readImageSize is executed through a small bounded-concurrency worker
window rather than Promise.all over every image. Preserve filtering to image
files and assigning each result’s width and height, while ensuring directory
selections with many files do not decode all images simultaneously.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/BlazorUI/Bit.BlazorUI/component-css-variables.md`:
- Line 13: Regenerate component-css-variables.md using the output produced by
BitComponentCssVariablesContractTests.cs so the inventory includes
--bit-fin-clr-txt and --bit-fin-clr-active, and update the header count from 280
to 282 variables while preserving the generated ordering and content.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs`:
- Around line 91-94: Mark the Classes parameter with [ResetClassBuilder] and the
corresponding Styles parameter with [ResetStyleBuilder]. Update only these
parameter declarations so changes to their references reset the cached
ClassBuilder and StyleBuilder and reflect Root overrides at runtime.

In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor`:
- Around line 4-8: Review the public descriptions in the FileInput demo page,
especially the PageOutlet and DemoPage Description attributes, and replace every
stray double space where two clauses run together with the intended em dash or
en dash separator. Apply the same correction throughout the other affected copy
locations while preserving the existing wording.

In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.scss`:
- Around line 8-37: Wrap the FileInput demo usages in a plain owning div within
the Razor component, before the existing ::deep styles, so the scoped selectors
can resolve against this page’s scope attribute. Ensure the wrapper encompasses
the BitFileInput examples using .custom-class, .custom-dragging, .custom-item,
.custom-remove, and .custom-drop-zone .browse-file without changing the styles
themselves.

---

Nitpick comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts`:
- Around line 42-50: Update the image-dimension processing in BitFileInput so
FileInput.readImageSize is executed through a small bounded-concurrency worker
window rather than Promise.all over every image. Preserve filtering to image
files and assigning each result’s width and height, while ensuring directory
selections with many files do not decode all images simultaneously.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6ae9d1b0-eba7-4733-a4e7-029a38fae276

📥 Commits

Reviewing files that changed from the base of the PR and between 826c1ad and 81ef3f9.

📒 Files selected for processing (13)
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputClassStyles.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputInfo.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputJsRuntimeExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/component-css-variables.md
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.scss
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs

Comment thread src/BlazorUI/Bit.BlazorUI/component-css-variables.md Outdated
@msynk

msynk commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full-review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

@msynk: Starting a fresh full review of the complete change set and its cross-file interactions.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.samples.cs (1)

219-410: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Sample <style> blocks duplicate the page's SCSS.

example20RazorCode and example27RazorCode re-declare the same rules that live in BitFileInputDemo.razor.scss; they will drift once one side is edited. Not blocking for a copy-pasteable sample, just worth keeping in mind.

Also applies to: 518-563

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.samples.cs`
around lines 219 - 410, Update the sample markup in example20RazorCode and
example27RazorCode to avoid duplicating the file-input styles defined by the
page’s SCSS, while preserving the sample’s copy-pasteable appearance and class
names. Remove or replace the embedded style declarations and ensure any required
styling is sourced through the existing shared SCSS.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.samples.cs`:
- Around line 219-410: Update the sample markup in example20RazorCode and
example27RazorCode to avoid duplicating the file-input styles defined by the
page’s SCSS, while preserving the sample’s copy-pasteable appearance and class
names. Remove or replace the embedded style declarations and ensure any required
styling is sourced through the existing shared SCSS.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4eaa6d97-238e-47eb-98bb-6cc0cda37c76

📥 Commits

Reviewing files that changed from the base of the PR and between 826c1ad and 209892f.

📒 Files selected for processing (13)
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputClassStyles.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputInfo.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputJsRuntimeExtensions.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/FileInput/BitFileInputDemo.razor.scss
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/component-css-variables.md

@msynk

msynk commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full-review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

@msynk: Starting a fresh full review of the complete change set and cross-file interactions.

✅ Action performed

Full review finished.

@msynk
msynk merged commit 59c2556 into bitfoundation:develop Jul 28, 2026
3 checks passed
@msynk
msynk deleted the 12742-blazorui-fileinput-choicegroup-improvements branch July 28, 2026 15:14
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.

The BitFileInput improvements

1 participant