Skip to content
navius

File Upload

A drag-and-drop file field built on a real hidden file input, with client-side validation, a rejection channel and a rendered file list.

Drop files here, or Images or PDF, up to 4 files

    Features

    • The hidden <input type="file"> (the Input part) carries the form value but sits outside the tab order and accessibility tree (tabindex="-1", aria-hidden); the Dropzone (role="button" with a default label) and the Trigger button are the accessible controls that relay to it to open the OS dialog.
    • A drop anywhere on the root copies files into the input; data-dragging mirrors the engine's drag state onto the root and dropzone.
    • Each selection is validated against Accept / MaxSize / MaxFiles; accepted files raise OnAccepted, refused ones raise OnRejected with a reason.
    • Controlled via @bind-Files or uncontrolled; a polite live region announces added / rejected / removed counts.

    Installation

    Reference the Navius.Primitives package for the headless primitive, or vendor a styled version with the CLI: navius add copies the styled zits/ui component plus the brain files it depends on.

    Anatomy

    Import the parts and assemble them. The Input must live inside the Dropzone (or the root); the List renders one Item per file.

    API Reference

    NaviusFileUpload. Owns the file list, validation and the drag/drop relay. Renders a div with a visually-hidden polite status region. Files is two-way bindable.

    Prop Type Default
    Files IReadOnlyList<IBrowserFile>? -
    FilesChanged EventCallback<IReadOnlyList<IBrowserFile>> -
    Accept string? -
    Multiple bool false
    MaxFiles int? -
    MaxSize long 0
    Directory bool false
    Capture string? -
    Disabled bool false
    Name string? -
    OnAccepted EventCallback<IReadOnlyList<IBrowserFile>> -
    OnRejected EventCallback<IReadOnlyList<NaviusFileRejection>> -
    ChildContent RenderFragment? -
    …attributes IDictionary<string, object>? -
    Data attribute Values
    [data-navius-file-upload] Present on the root
    [data-disabled] Present when disabled
    [data-invalid] Present when the last selection had a rejection
    [data-dragging] Present while files are dragged over the root

    NaviusFileUploadDropzone. A focusable drop target; Enter/Space open the file dialog. Renders a div with role=button.

    Prop Type Default
    AriaLabel string? "Drop files here or press Enter to browse"
    ChildContent RenderFragment? -
    …attributes IDictionary<string, object>? -
    Data attribute Values
    [data-navius-file-upload-dropzone] Present on the drop target
    [data-dragging] Present while files are dragged over it
    [data-disabled] Present when disabled

    NaviusFileUploadInput. The real, visually-hidden InputFile that carries the form value (tabindex -1, aria-hidden). accept / multiple / webkitdirectory / capture / name flow from the root. Renders an input.

    Prop Type Default
    …attributes IDictionary<string, object>? -

    NaviusFileUploadTrigger. A plain button that opens the OS dialog by relaying to the input. Renders a button.

    Prop Type Default
    ChildContent RenderFragment? -
    …attributes IDictionary<string, object>? -
    Data attribute Values
    [data-navius-file-upload-trigger] Present on the trigger button
    [data-disabled] Present when disabled

    NaviusFileUploadList. The selected-files list; auto-renders one Item per file via ItemTemplate, or takes explicit children. Renders a ul with role=list.

    Prop Type Default
    ItemTemplate RenderFragment<IBrowserFile>? -
    ChildContent RenderFragment? -
    …attributes IDictionary<string, object>? -

    NaviusFileUploadItem. One file row; cascades a context so its name/size/delete children know their file. Renders an li with role=listitem.

    Prop Type Default
    File IBrowserFile required
    Invalid bool false
    ChildContent RenderFragment? -
    …attributes IDictionary<string, object>? -
    Data attribute Values
    [data-navius-file-upload-item] Present on each row
    [data-invalid] Present when the row is marked invalid

    Inside an Item: the file name (span), the human-readable size (span) and a per-file remove button (button, aria-label 'Remove {name}'). Each takes an optional child + splat.

    Prop Type Default
    ChildContent RenderFragment? -
    …attributes IDictionary<string, object>? -

    NaviusFileUploadClear. Clears all files; disabled when the list is already empty. Renders a button.

    Prop Type Default
    ChildContent RenderFragment? -
    …attributes IDictionary<string, object>? -
    Data attribute Values
    [data-navius-file-upload-clear] Present on the clear button
    [data-disabled] Present when disabled or the list is empty

    Accessibility

    The hidden file input carries the form value but is kept out of the tab order and accessibility tree (tabindex="-1", aria-hidden); the accessible controls are the Dropzone and the Trigger. The Dropzone follows react-aria's DropZone (role="button" with a default label, Enter / Space to browse) and the Trigger is a plain button that opens the OS dialog; drag-and-drop is pointer-only sugar. A visually-hidden role="status" aria-live="polite" region announces added / rejected / removed counts. Rejections arrive as NaviusFileRejection with a FileRejectionReason (TooLarge / TooMany / WrongType).