Skip to content

Apply BitFileInput improvements (#12742)#12744

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

Apply BitFileInput improvements (#12742)#12744
msynk wants to merge 2 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 image previews, folder selection, camera capture, and configurable file limits and validation.
    • Added removal callbacks and improved file metadata, including modification dates and preview URLs.
    • Added customization for colors, sizes, CSS classes, inline styles, labels, previews, and file actions.
    • Improved drag-and-drop behavior and accessibility attributes.
  • Documentation
    • Expanded the file input demonstrations with examples for validation, styling, accessibility, events, RTL, and public APIs.
  • Bug Fixes
    • File removal now updates callbacks and browser state consistently.

@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

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 40a05ae2-b153-4f4a-a97c-717880ffdca3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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 capture, directory, preview, styling, count, minimum-size, and custom-validator parameters, plus removal callbacks and file metadata.
Browser file lifecycle and interop
src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.ts, src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInputJsRuntimeExtensions.cs, src/BlazorUI/Bit.BlazorUI/Components/Inputs/FileInput/BitFileInput.razor.cs
Adds preview URL creation and cleanup, drag-depth handling, single-file drop behavior, JavaScript removal, and asynchronous callback sequencing.
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 style/class overrides, preview rendering, 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, and RTL.
Behavior and rendering tests
src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/FileInput/BitFileInputTests.cs
Tests accept, directory, capture, asynchronous removal, styling, list semantics, and ARIA output.

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

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant BitFileInput
  participant JavaScriptFileInput
  participant Browser
  User->>BitFileInput: Select, drop, or paste files
  BitFileInput->>JavaScriptFileInput: Initialize input and drag/drop handlers
  JavaScriptFileInput->>Browser: Assign files and dispatch change
  Browser->>BitFileInput: Return file metadata and preview URLs
  BitFileInput->>BitFileInput: Validate files and invoke OnChange
  User->>BitFileInput: Remove a file
  BitFileInput->>JavaScriptFileInput: 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 18.92% 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 accurately summarizes the BitFileInput improvements in the PR.
Linked Issues check ✅ Passed The changes add missing file-input features, demo examples, descriptions, and demo page copy required by #12742.
Out of Scope Changes check ✅ Passed The added tests, styles, JS interop, and demo updates all support the BitFileInput improvements and appear in scope.
✨ 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

Comment on lines +76 to +89
@if (ShowRemoveButton)
{
var removeIcon = BitIconInfo.From(RemoveButtonIcon, RemoveButtonIconName ?? "Delete");

<button @onclick="() => RemoveFile(file)"
type="button"
title="Remove"
aria-label="@($"Remove {file.Name}")"
style="@Styles?.RemoveButton"
class="bit-fin-rbt @Classes?.RemoveButton">
<i style="@Styles?.RemoveIcon" class="@removeIcon?.GetCssClasses() @Classes?.RemoveIcon" aria-hidden="true" />
</button>
}
</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Remove button isn't gated by IsEnabled.

The remove button has no disabled attribute and its @onclick="() => RemoveFile(file)" isn't guarded, so files can be removed while the component is disabled. See consolidated comment.

🤖 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 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.

Comment on lines +252 to 256
public async Task RemoveFile(BitFileInputInfo? fileInfo = null)
{
if (_files.Any() is false) return;

if (fileInfo is null)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

RemoveFile doesn't check IsEnabled, unlike Browse()/ReadContentAsync().

Browse() and ReadContentAsync() both early-return if (IsEnabled is false). RemoveFile skips this guard, so files can still be removed programmatically (and via the remove button, see BitFileInput.razor) while the component is disabled. See consolidated comment.

🤖 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 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.

Comment on lines +252 to 281
public async Task RemoveFile(BitFileInputInfo? fileInfo = null)
{
if (_files.Any() is false) return;

if (fileInfo is null)
{
var removedFiles = _files.ToArray();

_files.Clear();

await _js.BitFileInputClear(UniqueId);

foreach (var file in removedFiles)
{
await OnRemove.InvokeAsync(file);
}
}
else
{
_files.Remove(fileInfo);
if (_files.Remove(fileInfo) is false) return;

await _js.BitFileInputRemoveFile(UniqueId, fileInfo.FileId);

await OnRemove.InvokeAsync(fileInfo);
}

await OnChange.InvokeAsync([.. _files]);

StateHasChanged();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

RemoveFile doesn't recompute MaxCount validity after mutating _files.

HandleOnChange invalidates files beyond MaxCount by position (_files.Skip(MaxCount)), but RemoveFile never re-runs this check. After a single-file removal, files that should now fall back within the limit stay marked invalid (stale MaxCountErrorMessage), while the actual current excess may go unflagged. Note ValidateFile never resets IsValid = true, so simply re-invoking it won't fix this — the reset needs to be explicit.

Example: 5 files, MaxCount = 3 → files at index 3,4 invalid. Remove file at index 0 → new list [F1,F2,F3,F4] (count 4, only F4 should now be invalid), but F3 stays incorrectly invalid since it was never reset.

🐛 Proposed fix
     public async Task RemoveFile(BitFileInputInfo? fileInfo = null)
     {
         if (_files.Any() is false) return;

         if (fileInfo is null)
         {
             var removedFiles = _files.ToArray();

             _files.Clear();

             await _js.BitFileInputClear(UniqueId);

             foreach (var file in removedFiles)
             {
                 await OnRemove.InvokeAsync(file);
             }
         }
         else
         {
             if (_files.Remove(fileInfo) is false) return;

             await _js.BitFileInputRemoveFile(UniqueId, fileInfo.FileId);

             await OnRemove.InvokeAsync(fileInfo);
         }

+        var maxCountMessage = MaxCountErrorMessage ?? "The maximum number of files is exceeded";
+        foreach (var file in _files.Where(f => f.Message == maxCountMessage))
+        {
+            file.IsValid = true;
+            file.Message = null;
+        }
+
+        if (MaxCount > 0 && _files.Count > MaxCount)
+        {
+            foreach (var file in _files.Skip(MaxCount))
+            {
+                if (file.IsValid is false) continue;
+
+                file.IsValid = false;
+                file.Message = maxCountMessage;
+            }
+        }
+
         await OnChange.InvokeAsync([.. _files]);

         StateHasChanged();
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public async Task RemoveFile(BitFileInputInfo? fileInfo = null)
{
if (_files.Any() is false) return;
if (fileInfo is null)
{
var removedFiles = _files.ToArray();
_files.Clear();
await _js.BitFileInputClear(UniqueId);
foreach (var file in removedFiles)
{
await OnRemove.InvokeAsync(file);
}
}
else
{
_files.Remove(fileInfo);
if (_files.Remove(fileInfo) is false) return;
await _js.BitFileInputRemoveFile(UniqueId, fileInfo.FileId);
await OnRemove.InvokeAsync(fileInfo);
}
await OnChange.InvokeAsync([.. _files]);
StateHasChanged();
}
public async Task RemoveFile(BitFileInputInfo? fileInfo = null)
{
if (_files.Any() is false) return;
if (fileInfo is null)
{
var removedFiles = _files.ToArray();
_files.Clear();
await _js.BitFileInputClear(UniqueId);
foreach (var file in removedFiles)
{
await OnRemove.InvokeAsync(file);
}
}
else
{
if (_files.Remove(fileInfo) is false) return;
await _js.BitFileInputRemoveFile(UniqueId, fileInfo.FileId);
await OnRemove.InvokeAsync(fileInfo);
}
var maxCountMessage = MaxCountErrorMessage ?? "The maximum number of files is exceeded";
foreach (var file in _files.Where(f => f.Message == maxCountMessage))
{
file.IsValid = true;
file.Message = null;
}
if (MaxCount > 0 && _files.Count > MaxCount)
{
foreach (var file in _files.Skip(MaxCount))
{
if (file.IsValid is false) continue;
file.IsValid = false;
file.Message = maxCountMessage;
}
}
await OnChange.InvokeAsync([.. _files]);
StateHasChanged();
}
🤖 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 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.

Comment on lines +45 to +66
function onDragEnter(e: DragEvent) {
e.preventDefault();
if (!hasFiles(e)) return;

dragCounter++;
dropZoneElement.classList.add(...dragClasses);
}

function onDragLeave(e: DragEvent) {
function onDragOver(e: DragEvent) {
e.preventDefault();
}

function onDrop(e: DragEvent) {
function onDragLeave(e: DragEvent) {
e.preventDefault();
inputElement.files = e.dataTransfer!.files;
if (!hasFiles(e)) return;

dragCounter--;
if (dragCounter <= 0) {
dragCounter = 0;
dropZoneElement.classList.remove(...dragClasses);
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Dragging highlight shown even when the input is disabled.

onDragEnter/onDragLeave only gate on hasFiles(e), not inputElement.disabled. So a disabled BitFileInput still shows the "dragging" highlight on drag-over, even though onDrop silently no-ops for disabled inputs. This misleads users into thinking the drop will succeed.

🐛 Proposed fix — skip the highlight when disabled
         function onDragEnter(e: DragEvent) {
             e.preventDefault();
-            if (!hasFiles(e)) return;
+            if (inputElement.disabled || !hasFiles(e)) return;

             dragCounter++;
             dropZoneElement.classList.add(...dragClasses);
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function onDragEnter(e: DragEvent) {
e.preventDefault();
if (!hasFiles(e)) return;
dragCounter++;
dropZoneElement.classList.add(...dragClasses);
}
function onDragLeave(e: DragEvent) {
function onDragOver(e: DragEvent) {
e.preventDefault();
}
function onDrop(e: DragEvent) {
function onDragLeave(e: DragEvent) {
e.preventDefault();
inputElement.files = e.dataTransfer!.files;
if (!hasFiles(e)) return;
dragCounter--;
if (dragCounter <= 0) {
dragCounter = 0;
dropZoneElement.classList.remove(...dragClasses);
}
}
function onDragEnter(e: DragEvent) {
e.preventDefault();
if (inputElement.disabled || !hasFiles(e)) return;
dragCounter++;
dropZoneElement.classList.add(...dragClasses);
}
function onDragOver(e: DragEvent) {
e.preventDefault();
}
function onDragLeave(e: DragEvent) {
e.preventDefault();
if (!hasFiles(e)) return;
dragCounter--;
if (dragCounter <= 0) {
dragCounter = 0;
dropZoneElement.classList.remove(...dragClasses);
}
}
🤖 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 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.

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