Vanilla ยท React ยท Vue ยท Svelte ยท Solid ยท Web Components

A media library,
in one adapter.

A framework-agnostic file picker with search, folders, type filters, upload, inline edit and delete โ€” wired to your backend through one small adapter. Drop it into any framework, or none.

npm i @anil-labs/file-picker-core
  • 8adapter methods
  • 0runtime deps
  • 6framework adapters
Open it search ยท folders ยท upload ยท select

A full media library over an in-memory adapter โ€” no backend. Everything you do here runs the published build.

Live demos

Each button below opens the real picker with different options. There's no framework on this page โ€” every one is a direct new FilePicker() over the same in-memory adapter.

Single select picks one, closes on choose

multiple: false โ€” tap an item and the dialog confirms and closes immediately.

Multiple, capped select up to four

multiple: true with maxSelection: 4 โ€” gather a batch, then confirm them together.

Read-only browser browse & pick, no writes

allowUpload, allowEdit, allowDelete and manageFolders off โ€” a safe pick-only view.

Modal layout centered card, not fullscreen

layout: 'modal' renders a centered dialog on desktop instead of taking the whole screen.

Events every action, live

The picker emits change, select, upload, delete and error. Open it and pick something โ€” this panel is what the build's headless guard drives to prove the engine really runs.

Inside a form submits like any other field

The picker is not an <input>, so it posts nothing by itself. Mirror the selection into hidden inputs on change and it behaves like any other field โ€” submit below to see the exact FormData the browser would send.

Media


                

Theming

Every colour is a --fp-* custom property. The picker ships light and dark out of the box (with its own toggle in the dialog header), and one variable โ€” --fp-accent โ€” recolours the whole thing.

Accent live โ€” recolours every picker
selected tag
What just changed

                

Set --fp-accent on any ancestor โ€” a wrapper, or :root to recolour every picker at once. No class to add, no stylesheet to fork.

One adapter, eight methods

The picker knows nothing about your storage. Implement eight methods โ€” list, upload, update, delete, and the folder operations โ€” and the whole UI works against it. A ready-made in-memory adapter (used all over this page) and a REST adapter ship in the box.

Browse & search

Paginated grid, debounced search, type filters (image, video, audio, docsโ€ฆ) and tag filtering โ€” all driven by a single listMedia query.

Folders

Create, rename and delete folders, and move items between them โ€” or turn folder management off entirely with one option.

Upload

Drag-and-drop or click-to-upload with an accept filter, straight into the current folder, with a live pending state.

Inline edit

Rename, set alt text and manage tags in a side dialog โ€” each field saved through the adapter's updateMedia.

Accessible dialog

Focus is trapped and restored, the grid is a real listbox, and a live region announces loading and results.

Themeable & tiny

Zero runtime dependencies, light/dark built in, and every colour a --fp-* variable. Bring your own icons, colours and labels.

Keyboard & accessibility

The dialog is fully operable from the keyboard, with focus management and screen-reader announcements โ€” open any demo above and try it.

In the dialog
Tab Move through search, filters, grid and actions
โ†‘ โ†“ โ† โ†’ Move between items in the grid
Space / Enter Select or deselect the focused item
Esc Close the dialog and restore focus to the trigger
Built in
focus trap Focus stays within the open dialog
focus return Closing returns focus to whatever opened it
listbox The grid exposes proper selection semantics
aria-live Loading and result counts are announced

Per-framework playgrounds

This page is deliberately framework-free. Each adapter has its own playground showing the idiomatic binding for that framework.