Skip to content

feat(FileUpload): new component #4102

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
wants to merge 40 commits into
base: v3
Choose a base branch
from
Open

Conversation

vachmara
Copy link
Contributor

@vachmara vachmara commented May 7, 2025

πŸ”— Linked issue

Resolves #1945

❓ Type of change

  • πŸ“– Documentation (updates to the documentation or readme)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • πŸ‘Œ Enhancement (improving an existing functionality)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

πŸ“š Description

This PR introduces the FileUpload component, a long-requested feature by the Nuxt UI community (see #1945).

The FileUpload component provides a customizable and accessible file input that supports:

  • File selection via input or drag-and-drop
  • Multiple file selection
  • File preview (only for images if not display an icon)
  • Removal of selected files
  • Customization via slots

πŸ“ Checklist

  • I have linked an issue or discussion.
  • The component is available in the playground.
  • I have updated the documentation accordingly.
  • I have added tests to cover this component.

Copy link

pkg-pr-new bot commented May 7, 2025

npm i https://pkg.pr.new/@nuxt/ui@4102

commit: 07e0845

@vachmara
Copy link
Contributor Author

vachmara commented May 7, 2025

Would love to hear your feedback on this when you have a moment, @rdjanuar @benjamincanac, happy to iterate based on your suggestions!

@rdjanuar
Copy link
Contributor

rdjanuar commented May 7, 2025

Thank you for continuing this development @vachmara, actually i'm already done working on this feature but missing only style of component and forget to push it, you can take a look my implementation #2814. maybe on this week i can finish it @benjamincanac

@kaspernowak
Copy link

@vachmara Thank you for this! And also for mentioning it on #1945 which I follow :)

@rdjanuar good to hear that your implementation of this feature is near completion!
I took the time to compare the features in @vachmara's component with the features in #2814, and I feel like these features would be very useful implementations worth to consider:

  1. Image-preview management (essential IMO)
    • Automatically creates and revokes URL.createObjectURL thumbnails for image files.
    • Cleans up previews on file removal and component unmount.
  2. Form-field integration
    • Uses a useFormField composable to wire up blur/focus/change events and aria- attributes automatically.
  3. Themed size-variants & slots
    • size variants (xsβ†’xl) that adjust dimensions, padding, icon/avatar sizes.
    • Fully overridable slot props (ui.empty, ui.file, etc.) via tv() + appConfig.ui.fileUpload overrides.
  4. Custom loading state
    • loading boolean + loadingIcon prop so consumers can show a spinner while files upload.
  5. Built-in file-list UI
    • A <ul> of selected files with filename, size (in MB), avatar/icon preview, and β€œremove” button.
  6. Customizable icons
    • Separate uploadIcon, fileIcon and close icons exposed as props.

@vachmara
Copy link
Contributor Author

vachmara commented May 8, 2025

Hey @rdjanuar,

I noticed you've already done an excellent job on the logic. I honestly thought the feature was abandoned, and I should’ve checked in earlier, sorry about that. I’d be more than happy to help polish and push this component forward with you!

@kaspernowak, thanks for pointing out the main functionalities I implemented; spot on!

I’d also like to mention that the file type validation, which you handled nicely, was something I intentionally left out to maintain compatibility with FormField and Form, with the idea of using external validation libraries for that kind of logic. That said, I'm totally open to discussing the best approach here.

I think both of our implementations bring valuable logic, and it'd be great to merge the best of both. There’s still a bit of work to be done, proper testing (for Vue & Nuxt), improving some functionality (UI/UX, core logic like disabled etc..), and writing the proper documentation.

Don’t hesitate to share how you'd like to collaborate or areas you'd prefer me to focus on. Looking forward to working together!

@rdjanuar
Copy link
Contributor

Hi @vachmara ,

I think I’ll keep my file validation as the default since it already covers all aspects of file upload. Later, I might create a function to allow overriding it based on a given schema. For now, I’ll focus on finishing my work first, and then we can collaborate on it.

@benjamincanac
Copy link
Member

You're not making it easy guys haha

Can't we just keep one open and work together on it? I'd go for this one because it's most recent and follows the latest Nuxt UI components architecture pattern. You will both get the contribution anyway.

@rdjanuar
Copy link
Contributor

sounds good @benjamincanac

@vachmara vachmara marked this pull request as ready for review May 15, 2025 10:09
@vachmara
Copy link
Contributor Author

I’ve added tests and a minimal doc to get everyone started. If anything’s unclear or you’d like to see extra examples or features, just let me know, happy to iterate!

@larseberhardt larseberhardt mentioned this pull request May 19, 2025
8 tasks
@genu
Copy link
Member

genu commented May 21, 2025

Thanks for this PR, I think it looks great!

Questions

  1. Should we expose some methods to be able to have more control over the files? For example, if we want to build a wrapper around the input to clear all the files, for example. (And possibly other helpers that could be helpful)
  2. Without adding to the scope of this effort, would it make sense to allow customizing the File type? That is rather than maintaining an internal list of Files and FileList to wrap those in special type to allow adding custom meta. What I mean by this:say, we're building an upload queue, and you want to track which of the files have been uploaded or in progress. In this case, the extra meta about the file state (uploading, complete, etc) wouldn't be in the File it self, but would be useful in the file slot be show an appropriate status for the file.

Let me know your thoughts.

@vachmara
Copy link
Contributor Author

vachmara commented May 21, 2025

Thanks for the thoughtful feedback!

  1. Exposing methods:
    I think that exposing the fileInputRef is enough for most advanced use cases, such as clearing files or triggering the file dialog. This keeps the API simple while allowing to implement custom helpers as needed.

  2. Custom file type:
    Create a custom type that gives users more control is an excellente idea, I can implement this for example:

export type FileUploadItem<Meta = Record<string, any>> = {
  file: File
} & Meta

So people would be able to extend it as needed, like:

type UploadWithStatus = FileUploadItem<{ status: 'pending' | 'uploading' | 'done'; progress?: number }>

Let me know if you have any preferences or further suggestions

@benjamincanac benjamincanac changed the title feat(FileUpload): add new component FileUpload feat(FileUpload): new component May 22, 2025
@genu
Copy link
Member

genu commented May 22, 2025

I like that idea @vachmara ! Looking forward to trying it out πŸ˜„

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.

Add file upload component
5 participants