Skip to content

Clicking Label does not open file picker when used in a Field with an Input type="file" #3680

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
EPurwanto opened this issue Apr 9, 2025 · 1 comment

Comments

@EPurwanto
Copy link

EPurwanto commented Apr 9, 2025

What package within Headless UI are you using?

@headlessui/react

What version of that package are you using?

2.2.1

What browser are you using?

Tested in Chrome and Firefox

Reproduction URL

https://codesandbox.io/p/devbox/headless-ui-file-label-v5rlnq

The structure is just this:

      <Field className="mb-4 flex flex-col">
        <Label>Headless UI Field and Label</Label>
        <Input type={'file'} />
      </Field>
      <div className="mb-4 flex flex-col">
        <label htmlFor={'raw-input'}>Raw HTML Label</label>
        <Input id={'raw-input'} type={'file'} />
      </div>

Describe your issue

Clicking on a Label component that is attached to an Input element of type "file" does not open the file picker. This is different to a standard HTML <label>, which will open the file picker when clicked, both with a standard <input> element and the Headless UI Input component.

@Saf3ty1nnumb3rs
Copy link

Saf3ty1nnumb3rs commented Apr 10, 2025

Hello @EPurwanto
Thanks for the clear reproduction - I’ve also run into this exact problem.

The core issue is that Headless UI’s <Label> component does not replicate native <label> behavior for <input type="file">. While it successfully manages focus and accessibility for ARIA widgets, it uses a synthetic .click() on the target element, which browsers block for file inputs unless the event is a trusted, native user gesture. This prevents the file picker from opening.(see MDN, Chromium source)

Additionally, the component always applies aria-labelledby, even when it’s empty. According to the ARIA in HTML spec and accessible name computation spec, this overrides the implicit htmlFor → id linkage, further breaking expected behavior.


Limitations:


Workaround (which you are already aware, sorry, not a fix 😓 ):

For file uploads, use standard HTML elements:

<label htmlFor="file-upload">Upload</label>
<input id="file-upload" type="file" />

This ensures native interaction is preserved.


Hope this helps others running into the same limitation or at least describes the cause.

Edit: neglected to tag OP

Update: Even with a native <input type="file">, using Headless UI’s <Label> inside a <Field> can still block the file picker. This happens because <Label> participates in internal context and calls event.preventDefault(), which suppresses the browser’s native 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

No branches or pull requests

2 participants