File Input
v0.0.10
mix mishka.ui.gen.headless file_input
Overview of the Phoenix and LiveView Headless File Input Component
The Mishka Chelekom Headless File Input is the browser's own file picker, wired for plain forms and for LiveView uploads. It ships no styling. Unlike the other form controls it is not wrapped: the input is the root, so your classes go straight on it. That matters because the browser's button, ::file-selector-button, only exists on the input itself, and Tailwind's file: variant is how you reach it.
There are three ways to wire it up. Pass upload={@uploads.avatar} and the component renders live_file_input, so LiveView owns the name, the accepted types and the multiple flag. Pass field={@form[:attachment]} inside a Phoenix form to take the id and name from the form. Or pass name for a plain input. The input reflects its state in data-invalid and data-disabled, and class lands on the input itself.
Base UI File Input example - inside a field with a description (Phoenix headless)
Base UI File Input example - inside a field with a description (Phoenix headless)
PNG or JPG, up to 2MB.
<.field
:let={f}
id="baseui-file-field"
name="avatar"
label="Avatar"
class="flex w-full max-w-80 flex-col gap-1"
label_class="text-sm font-medium text-neutral-950 dark:text-white"
description_class="text-xs text-neutral-500"
>
<.file_input
id={f.id}
name={f.name}
accept="image/*"
describedby={f.describedby}
class="w-full max-w-80 rounded-md border border-neutral-200 text-sm text-neutral-950 dark:border-neutral-800 dark:text-white file:mr-3 file:cursor-pointer file:border-0 file:bg-neutral-950 file:px-3 file:py-1.5 file:text-sm file:text-white dark:file:bg-white dark:file:text-neutral-950"
/>
<:description>PNG or JPG, up to 2MB.</:description>
</.field>Uploads, forms and errors
With field, the id and name come from the form field. With multiple the name gets a [] suffix, so Plug builds a list. accept is a comma separated list of file types, and upload ignores it because LiveView owns the list. Pass name only for a plain input, since upload and field supply theirs.
<.file_input upload={@uploads.avatar} class="..." />
<.file_input field={@form[:attachment]} class="..." />
<.file_input field={@form[:gallery]} multiple accept="image/*" class="..." />
<.file_input name="attachment" class="..." />errors is a list of messages. A non-empty list marks the input invalid, with aria-invalid="true" and data-invalid. The input does not print the messages, so show them in a Field. With field, errors count only after the user has touched the input. With upload, errors on the upload itself, such as too many files, always mark it invalid. describedby sets aria-describedby. disabled sets data-disabled and, on a plain input, the native disabled attribute. required makes a plain input required.
Parts & data attributes
There is one part: the input. It carries data-part="input" and the chelekom-file-input class.
| Part | data-part | State / ARIA | Purpose |
|---|---|---|---|
| Input (root) | input | aria-invalid, aria-describedby, data-invalid, data-disabled | The native file input. It is the root, so classes and the file: variants apply to it directly. |
Accessibility
The control is the native file input, so Tab focuses it and Enter or Space opens the picker. It needs a visible label, which a Field provides, and describedby should point at hints and error text. An invalid input is announced through aria-invalid. A plain input with disabled is skipped by the tab order.
Attributes
| Name | Type | Default | Values | Required | Description |
|---|---|---|---|---|---|
id
|
string
| — | — | No | Unique id; taken from the form field or upload when given |
upload
|
any
| — | — | No | A `Phoenix.LiveView.UploadConfig` — renders a live file input and owns name/accept/multiple |
field
|
Phoenix.HTML.FormField
| — | — | No | A form field struct — supplies id, name and errors |
name
|
string
| — | — | No | Input name (ignored when `upload` or `field` is given) |
accept
|
string
| — | — | No | Comma-separated file types (ignored when `upload`) |
multiple
|
boolean
|
false
| — | No | Accept several files (ignored when `upload`) |
errors
|
list
|
[]
| — | No | Error messages; a non-empty list marks it invalid |
disabled
|
boolean
|
false
| — | No | Disable the picker (data-disabled) |
required
|
boolean
|
false
| — | No | Require a file for form submit |
describedby
|
string
| — | — | No | Id(s) of the description/error elements |
class
|
any
| — | — | No | Extra classes for the input |
rest
|
global
| — | — | No | Any input/global attrs |
Options
Each option takes one or more of its values, separated by commas.
| Option | Values |
|---|---|
--type
|
file_input
|
--module
| A module name of your own |
What it generates
mix mishka.ui.gen.headless file_input