Skip to content

Apply BitFileInput improvements (#12742) - #12744

Open
msynk wants to merge 3 commits into
bitfoundation:developfrom
msynk:12742-blazorui-fileinput-choicegroup-improvements
Open

Apply BitFileInput improvements (#12742)#12744
msynk wants to merge 3 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
    • Added optional image previews (with optional dimensions), directory selection, and capture mode.
    • Added configurable limits (min/size/count/total size) plus per-file validation.
    • Expanded styling customization with style/class hooks across all FileInput regions.
    • Improved drag-and-drop support (drop/paste) and directory drop handling.
  • Bug Fixes
    • Refined file removal/reset to keep browser state, UI, and callbacks in sync; better accept generation (including omitting when it would allow everything).
    • Enhanced accessibility with clearer ARIA wiring and a live status region.
  • Documentation
    • Updated and expanded FileInput demos, including a new route and examples for accessibility/public API.
  • Tests
    • Added coverage for accept/ARIA/attributes and preview-related behavior.

@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

Walkthrough

BitFileInput adds validation options, previews, removal callbacks, browser file handling, accessibility attributes, customizable styles, color and size variants, expanded demos, and tests covering the new behavior.

Changes

BitFileInput improvements

Layer / File(s) Summary
Component API and validation
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs, src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputInfo.cs, src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputClassStyles.cs
Adds file-selection parameters, metadata, accept-value generation, centralized validation, asynchronous removal, callbacks, announcements, and styling contracts.
Browser file lifecycle and interop
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts, src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputJsRuntimeExtensions.cs
Adds preview URL creation and cleanup, image-dimension reading, drag-and-drop and directory handling, browser-side removal, and expanded JavaScript interop options.
Rendered markup and theming
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor, src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.scss
Adds dynamic input and ARIA attributes, per-part class/style overrides, preview rendering, live status output, disabled controls, and color- and size-based CSS variables.
Demo examples and metadata
src/BlazorUI/Demo/Client/.../FileInput/*
Expands documentation and examples for validation, events, public APIs, accessibility, previews, styling, sizing, icons, directory selection, and RTL.
Behavior and rendering tests
src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs
Tests accept generation, directory and capture attributes, asynchronous removal, styling, list semantics, live regions, and ARIA output.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant BitFileInput
  participant FileInput
  participant Browser
  User->>BitFileInput: Select, drop, or paste files
  BitFileInput->>FileInput: Initialize file and drag/drop handlers
  FileInput->>Browser: Assign files and dispatch change
  Browser->>BitFileInput: Return metadata, previews, and dimensions
  BitFileInput->>BitFileInput: Validate files and invoke callbacks
  User->>BitFileInput: Remove a file
  BitFileInput->>FileInput: Remove file and revoke preview URL
  BitFileInput->>BitFileInput: Invoke OnRemove and OnChange
Loading

Suggested reviewers: mhrastegari, yasmoradi

Poem

A bunny browsed files, fluffy and bright,
Previewed each image in soft pixel light.
It hopped through validation,
Styled every station,
And logged every change just right. 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.73% 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 is concise and clearly points to the BitFileInput improvements, which matches the changeset.
Linked Issues check ✅ Passed The PR adds missing BitFileInput features, demo examples, and improved descriptions/page copy, matching #12742.
Out of Scope Changes check ✅ Passed The changes are focused on BitFileInput, its demos, styling, and tests, with no clear unrelated additions.
✨ 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

@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

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