Rewrote all the docs - more noob friendly now.

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
2026-05-05 23:55:26 +05:00
parent e483bf73e7
commit f6ae86617c
35 changed files with 2159 additions and 2341 deletions
+51 -64
View File
@@ -1,35 +1,23 @@
# FileInput
A styled file upload field with an optional visible label and description. Supports `accept` MIME types, multiple file selection, and HTMX attributes for server-driven interactions.
A styled file upload field. Use it when you need users to attach files to a form — profile pictures, documents, CSV imports, and so on.
---
## HTML structure
## Quick example
```
div.flex.flex-col.gap-1.5
label[for={id}].text-sm.font-medium ← omitted when label is empty
{label text}
input[type=file, id, name, accept, class, $$Multiple$$, $$HxAttrs$$]
p.text-sm.text-muted-foreground ← omitted when description is empty
{description text}
```csharp
new FileInput(
id: "avatar",
name: "avatar",
accept: "image/*",
label: "Profile picture",
description: "PNG, JPG or GIF up to 2 MB")
```
---
## CSS mechanics
| Class | Effect |
|---|---|
| `file:mr-4 file:py-2 file:px-4 file:rounded-md` | Styles the browser's "Choose file" button via `::file-selector-button` |
| `file:border-0 file:bg-primary file:text-primary-foreground` | Gives the file button the primary color |
| `file:text-sm file:font-semibold file:cursor-pointer` | Consistent text treatment |
| `hover:file:bg-primary/90` | Slight darkening on hover |
| `w-full rounded-md border border-input bg-background text-sm` | Full-width field with border |
---
## Constructor signature
## All the options
```csharp
public FileInput(
@@ -43,71 +31,70 @@ public FileInput(
string hxAttrs = "")
```
| Parameter | Description |
| Parameter | What it does |
|---|---|
| `id` | Element id and label `for` target |
| `name` | Form field name |
| `accept` | MIME types or file extensions, e.g. `"image/*"` or `".pdf,.docx"` |
| `multiple` | Allows selecting more than one file |
| `label` | Visible label above the field |
| `description` | Helper text below the field |
| `extraClasses` | Additional Tailwind classes on the input |
| `hxAttrs` | Verbatim HTMX / data attributes appended to the input |
| `id` | The element id. Also used by the `<label for="...">`. |
| `name` | Form field name — required if you want the file submitted with the form. |
| `accept` | MIME types or extensions to filter the picker, e.g. `"image/*"` or `".pdf,.docx"`. Does not validate server-side. |
| `multiple` | Allow selecting more than one file at a time. |
| `label` | Visible text label above the field. |
| `description` | Hint text below the field (e.g. "Max 5 MB"). |
| `extraClasses` | Additional Tailwind classes on the `<input>` element. |
| `hxAttrs` | Extra HTML attributes appended verbatim (HTMX, `data-*`, etc.). |
---
## Usage examples
## Real-world examples
### Basic single file
### Multiple document attachments
```csharp
new FileInput(
id: "avatar",
name: "avatar",
accept: "image/*",
label: "Profile picture",
description: "PNG, JPG or GIF up to 2 MB")
```
### Multiple files
```csharp
new FileInput(
id: "attachments",
name: "attachments",
accept: ".pdf,.docx,.xlsx",
multiple: true,
label: "Attachments",
id: "attachments",
name: "attachments",
accept: ".pdf,.docx,.xlsx",
multiple: true,
label: "Attachments",
description: "Select one or more documents")
```
### HTMX auto-upload on change
### Auto-upload on file selection (HTMX)
```csharp
new FileInput(
id: "import-csv",
name: "csv",
accept: ".csv",
label: "Import CSV",
hxAttrs: """hx-post="/import" hx-encoding="multipart/form-data" hx-target="#result" hx-trigger="change"""")
id: "import-csv",
name: "csv",
accept: ".csv",
label: "Import CSV",
hxAttrs: """hx-post="/import" hx-encoding="multipart/form-data" hx-target="#result" hx-trigger="change"""")
```
### No label
When using HTMX for file uploads, always include `hx-encoding="multipart/form-data"` — HTMX does not infer it from the input type.
### Reading uploaded files in a handler
```csharp
new FileInput(id: "doc", name: "document", accept: ".pdf")
public static IResult Handle(HttpContext ctx, IFormFile? avatar)
{
if (avatar is null || avatar.Length == 0)
return Results.BadRequest("No file uploaded");
// validate file type server-side (accept= only filters in the browser)
var allowed = new[] { "image/jpeg", "image/png", "image/gif" };
if (!allowed.Contains(avatar.ContentType))
return Results.BadRequest("Invalid file type");
using var stream = avatar.OpenReadStream();
// save the file...
return Results.Ok();
}
```
---
## Tips and tricks
## How it works
- `accept` filters in the browser's file picker dialog but does not validate server-side — always validate the uploaded file type in your handler.
- For HTMX file uploads set `hx-encoding="multipart/form-data"` in `hxAttrs`; HTMX does not infer encoding from the input type.
- Multiple files are bound as a list: `IFormFileCollection` or `List<IFormFile>` in the handler. `FromForm` attribute on the command record field is required.
- To show a preview of the selected image before upload, add a small JS snippet that listens to the `change` event and sets `src` on an `<img>` element via `URL.createObjectURL(e.target.files[0])`.
- `extraClasses` is added to the `<input>` element, not the wrapper `<div>` — use it for overriding width, borders, or custom ring colors.
- `extraClasses` is added to the `<input>` element, not the wrapper `<div>` — use it for overriding width, borders, or custom ring colors.
FileInput renders a standard `<input type="file">`. The browser's built-in "Choose file" button is styled using `::file-selector-button` CSS pseudo-element (via Tailwind's `file:` prefix) so it matches the rest of the UI.
---