Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelogContact
Components
Buttons & Actions
ButtonButton GroupCopy ButtonDelete ButtonTheme ToggleToggleToggle Group
Inputs
Avatar UploadCalendarCheckboxColor PickerComboboxCountry SelectCron PickerCurrency InputDate PickerDate Range PickerDate Time PickerDuration PickerEmail InputEmoji PickerFile UploadFilter BuilderInputInput GroupListboxMasked InputMention InputMonth PickerMulti SelectNumber InputOTP InputPassword InputPhone InputRadio GroupRatingSearch InputSegmented ControlSelectSignature PadSliderSwitchTag InputTextareaTime PickerTimezone SelectTree Select
Forms
Address InputBooking WidgetCSV ImportFieldForm WizardInline EditInvoice line itemsRich Text EditorSchema Builder
Navigation
Back To TopBounce SidebarBreadcrumbCommand MenuGlobal SearchGooey NavHook SidebarNav MenuNav TabsPaginationProximity SidebarScroll ProgressSidebarStepsTable Of ContentsTabsTopbarUser MenuWorkspace Switcher
Overlays
Alert DialogContext MenuDialogDrawerDropdown MenuFamily DrawerHover CardPopoverShare DialogSheetShortcuts DialogTooltipTour
Feedback
AlertBannerCookie ConsentEmoji ReactionEmpty StateNotification BellNotification CenterProgressRoute ProgressSetup ChecklistSkeletonSpinnerToast
Data Display
Approval FlowAvatarBadgeCalendar ViewCode BlockComment ThreadContact cardCountdownDescription ListDiff ViewerFile ListFile managerFolderGanttJSON ViewerKbdLog ViewerMarkdownPresenceSchedulerTagTimelineTree View
Tables & Lists
Audit LogData TableDeal PipelineEditable GridKanbanListMembers tablePermissions MatrixTableTask ListVirtual List
Charts & Stats
Animated CounterArea chartBar chartDonut chartFunnel chartGaugeGitHub ActivityHeatmap calendarLeaderboardLine chartRadar chartRadial barSparklineStat CardTrackerTrend badge
Layout
AccordionApp ShellCardCollapsibleDetail LayoutEntity HeaderPage HeaderScroll AreaSeparatorSettings LayoutSplit ViewToolbar
Media
Audio PlayerCarouselCSV ViewerDOCX EditorDOCX ViewerExcel ViewerFile SystemImage compareImage CropperImage GalleryImage LightboxLocation MapPDF ViewerPowerPoint ViewerQR CodeStep PlayerVideo Player
AI Kit
Agent Status CardChat MessageChat ThreadChat WidgetConversation ListFluid OrbGrid RevealMatrix OrbModel PickerPrompt InputReasoning IndicatorRule BuilderSuggestion ChipsTool Call TimelineUsage MeterVoice InputWorkflow Canvas
Text & Effects
Background PatternGravity LettersMarqueeTerminalText AnimateText Rotate
Mobile
Action SheetBottom Tab BarFABHaptic ButtonHero HeaderInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker WheelPull To RefreshSlide To ConfirmSticky CTA BarSwipe DeckSwipeable Tabs
Commerce
Cart drawerCategory pickerCheckout stepsCoupon inputFavorite buttonFilter panelListing cardListing gridOrder trackerPricePrice rangePricing tableProduct galleryQuantity stepperReviewsSeller card
Marketing Sections
App Download SectionBlog Cards SectionCTA SectionFAQ SectionFeature GridFeature ShowcaseHero SectionIntegrations SectionLogo CloudMarketing FooterMarketing HeaderMarketing SectionNewsletter SectionPricing SectionStats SectionSteps SectionTeam SectionTestimonials SectionTimeline SectionVideo Section
Blocks
Admin Dashboard PageAdmin ShellAI Chat PageAPI Keys PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError PagesInbox PageInvoice PageKPI DashboardListing Detail PageLogin PageMarketplace Home PageMarketplace Search PageMarketplace ShellMobile App HomeOnboarding FlowOrder History PagePost Listing WizardPricing PageProfile PageRegister PageSettings PageUsers Admin Page
Templates
About PageAcademy PageAccessibility PageAffiliate PageAgency PageAI Product PageAppointment Booking PageBlog PageBlog Post PageBug Bounty PageCareers PageChangelog PageCommunity PageCompare PageContact PageCustomer Story PageCustomers PageDemo Booking PageDevelopers PageDocs Home PageDownload PageEnterprise PageEvents PageExperts PageFAQ PageFeature PageGlossary PageHelp Article PageHelp Center PageHome Services PageImpact PageIntegration Detail PageIntegrations PageJob Detail PageLanding PageLaunch PageLegal PageManifesto PagePortfolio PagePress PageProduct Tour PagePromo PageReal Estate PageReferral PageResearch Report PageRestaurant PageRoadmap PageROI Calculator PageSecurity PageSolutions PageStartups PageStatus PageStorefront PageSwitch PageTemplate Gallery PageTravel PageWaitlist PageYear in Review Page
Hooks & Utilities
AI ChatChart kitCommerceDate utilsFile exportFile typesFiltersForm validationHapticsInvoicingMotion presetsNavigationNumber formatRelative timeRomanian locationsSpreadsheetText matchTonesUIProvideruseClipboarduseConsentuseControllableStateuseCooldownuseDebounceuseKeyboardInsetuseLocaleuseLongPressuseMediaControlsuseMediaQueryuseOverflowItemsusePersistedStateuseScrollEdgesuseScrollStateuseSelectionuseShortcutuseStickToBottom
GalleryTheme

Data Display

File manager

Data Display

File manager React component for Tailwind CSS v4

File ListFolder
Live props
Content
rootLabel
Appearance
defaultView
tileSize
variant
tone
color
Layout
showTree
showBreadcrumb
State
loading
skeletonCount12
error
defaultSearch
defaultFolderId
Behavior
persistKey
confirmDelete
previewImages
accept
maxFileSizeNo limit
uploadShortcut
locale
Code
import { FileManager } from "@/components/ui/file-manager"

<FileManager />
  1. Home
  2. Components
  3. Data Display
  4. File manager
Pro

File manager React component for Tailwind CSS v4

v1.0.0·Added in 1.0.0

A React file manager for the documents of a company or a record: folders and files in a grid or a list, a folder tree, uploads and bulk actions.

Click a file or a folder to select it, Cmd or Ctrl + click to add or remove one, Shift + click for a range, tick the checkbox that appears on hover, or click empty space to clear the selection; with anything selected the toolbar turns into the bulk bar (Move, Download, Delete, Select all). Double-click (or Enter) opens: a folder slides in, an image opens in the lightbox with the folder's other images, any other file goes to onOpen or its url in a new tab. Right-click or the ⋯ button opens the menu (Open, Rename, Move to, Download, your own entries, Delete); right-click on empty space offers New folder, Upload and Select all. Rename with F2, the menu or a slow second click on the name: the base name is selected, Enter saves, Escape cancels, and a rejected promise shows its message under the field. Drag files (the whole selection comes along) onto a folder, a crumb or a folder in the tree to move them; a folder never drops into itself, and the drag card shows a stop sign over a refused target. Drop files from the desktop anywhere on it to upload into the open folder, or onto a folder tile to upload there; pasting files uploads too, and the uploads panel in the bottom corner shows progress and rejected files, folds away and closes once nothing runs. Search looks through every folder, lists the results with their path and marks the matched letters. With the keyboard the files are one Tab stop: arrows move (Up and Down by a row of tiles), Home, End, Page Up and Page Down jump, letters jump to a name, Space toggles, Shift + arrows extend, Cmd or Ctrl + A selects all, Escape clears, Delete asks and removes, Backspace or Alt + Up goes to the parent folder, Shift + F10 opens the menu, and Cmd or Ctrl + Shift + N makes a folder from anywhere inside. On a phone it starts as a list under the folder's name as a large title with a back link: a tap opens, a long press starts selecting (checkboxes appear, taps add or remove, a floating bar offers Move, Download and Delete), hold and drag a selected file onto a folder to move it, and every menu, the Move dialog and the new folder dialog are bottom sheets. The layout follows the manager's own width, so in a narrow side panel it shows the compact list and two-column tiles even on a wide screen.

File manager is a Pro React component in the React data display components category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add file-manager, together with Alert Dialog, Avatar, Breadcrumb, Button, Checkbox and 27 more and the npm packages @dnd-kit/core, motion and lucide-react.

Add to a project

Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup

npx wingo-ui@latest add file-manager

File manager is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans

Usage

Import FileManager from @/components/ui/file-manager.

import { useState } from "react"
import { FileManager, type FileManagerItem, type FileManagerUpload } from "@/components/ui/file-manager"

export function Documents({ initial }: { initial: FileManagerItem[] }) {
  const [items, setItems] = useState(initial)
  const [uploads, setUploads] = useState<FileManagerUpload[]>([])

  return (
    <FileManager
      items={items}
      uploads={uploads}
      quota={{ used: 2.4 * 1024 ** 3, total: 10 * 1024 ** 3 }}
      locale="en-US"
      persistKey="crm:documents"
      labels={{ root: "Company files", search: "Search company files" }}
      onUpload={async (files, folderId) => {
        setUploads(files.map((file) => ({ id: file.name, name: file.name, size: file.size, progress: 0, status: "uploading", folderId })))
        const body = new FormData()
        files.forEach((file) => body.append("files", file))
        const saved: FileManagerItem[] = await (await fetch(`/api/files?folder=${folderId ?? ""}`, { method: "POST", body })).json()
        setItems((list) => [...list, ...saved])
        setUploads((list) => list.map((upload) => ({ ...upload, progress: 1, status: "done" })))
      }}
      onCreateFolder={async (name, parentId) => {
        const folder: FileManagerItem = await (await fetch("/api/folders", { method: "POST", body: JSON.stringify({ name, parentId }) })).json()
        setItems((list) => [...list, folder])
      }}
      onRename={async (item, name) => {
        await fetch(`/api/files/${item.id}`, { method: "PATCH", body: JSON.stringify({ name }) })
        setItems((list) => list.map((i) => (i.id === item.id ? { ...i, name } : i)))
      }}
      onMove={async (ids, parentId) => {
        await fetch("/api/files/move", { method: "POST", body: JSON.stringify({ ids, parentId }) })
        setItems((list) => list.map((i) => (ids.includes(i.id) ? { ...i, parentId } : i)))
      }}
      onDelete={async (ids) => {
        await fetch("/api/files", { method: "DELETE", body: JSON.stringify({ ids }) })
        setItems((list) => list.filter((i) => !ids.includes(i.id)))
      }}
    />
  )
}

Props

  • items*default "[]"
    FileManagerItem[]

    The whole tree, flat: { id, kind: "folder" | "file", name, parentId (null at the root), size? (bytes), type? (mime), url?, thumbnailUrl?, modifiedAt?, modifiedBy?: { name, avatar? }, itemCount?, shared?, starred?, locked? }. The component filters by parentId; a parentId loop never hangs. Locked items cannot be renamed, moved or deleted; Move and Delete on a selection that holds some skip them. Tiles use content-visibility past 60 items; page from the server beyond about 2.000 files in one folder.

  • rootLabeldefault ""
    string

    The root's name in the breadcrumb, the folder tree and search paths. Empty uses labels.root ("All files").

  • quota
    { used: number; total: number }

    Bytes used and available: a thin bar with "2,4 GB of 10 GB" next to the breadcrumb, amber past 80% and red past 95%.

  • uploadsdefault "[]"
    FileManagerUpload[]

    The uploads you are running: { id, name, size, progress (0 to 1), status: "uploading" | "done" | "error", error?, folderId }. They show in a floating panel at the bottom corner (collapsible, dismissible once nothing is running), next to the files the picker or a drop rejected.

  • emptyState
    ReactNode

    Replaces the empty folder state (by default an icon, a line of text and New folder / Upload when those handlers exist).

  • labels
    Partial<FileManagerLabels>

    Every string, English by default (DEFAULT_FILE_MANAGER_LABELS): root, region, folders, search, newFolder, folderName, create, cancel, upload, dropHere(folder), move, moveTo, moveHere, moveDescription(count, name), rename, download, delete, deleteTitle(count, name), deleteDescription, open, preview, select(name), selectAll, clearSelection, selected(count, formatted), items(count, formatted), results(count, formatted), name, modified, size, owner, type, sort, ascending, descending, view, grid, list, actions(name), sheetTitle, uploads, uploading(count, formatted), uploadsDone(count, formatted), uploadsFailed(count, formatted), uploadDone, uploadFailed, rejectedType, rejectedSize(max), collapse, expand, dismiss, storage, quota(used, total), empty, emptyDescription, noResults, noResultsDescription(query), clearSearch, loading, errorTitle, retry, moved(count, folder), renamed(name), deleted(count), created(name), failed, locked, shared, starred, folder, modifiedOn(when), dragging(count, name), pickedUp(count, name), dropped, dragCancelled, kinds (names per file kind).

  • defaultViewdefault "grid"
    "grid" | "list"

    The first layout while uncontrolled: tiles with previews, or rows with Modified, Size and Owner columns. Phones start with the list until someone picks a view; search results are always a list.

  • view
    "grid" | "list"

    The layout, controlled. Pair it with onViewChange.

  • onViewChange
    (view: "grid" | "list") => void

    Called when the view switch in the toolbar changes.

  • tileSizedefault "md"
    "sm" | "md" | "lg"

    The smallest tile width in the grid, 120 / 160 / 200px; the grid fits as many columns as it can. Below 512px of width (phones, side panels) it shows two columns.

  • variantdefault "surface"
    "surface" | "plain"

    surface sits the manager in a raised panel; plain drops the panel, for a section card that already has one.

  • tonedefault "neutral"
    "neutral" | "brand" | "success" | "warning" | "danger" | "info"

    Selected tiles and rows, drop targets, checkboxes, the tree's current folder, progress bars and the Upload button of the empty state.

  • colordefault ""
    string

    Any CSS color in place of the tone.

  • showTreedefault true
    boolean

    The folder tree beside the files once the manager itself is 768px wide (a container query, so it also hides in a narrow panel on a wide screen). Its folders are drop targets too.

  • showBreadcrumbdefault true
    boolean

    The path from the root to the open folder; every crumb is a drop target. Phones show a back link to the parent.

  • loadingdefault false
    boolean

    Skeleton tiles or rows with the real shape while the first page loads.

  • skeletonCountdefault 12
    number

    How many skeletons show while loading.

  • errordefault ""
    ReactNode

    Replaces the files with an error state and its message; add onRetry for a Try again button.

  • onRetry
    () => (void | Promise<unknown>)

    The error state's Try again button.

  • defaultSearchdefault ""
    string

    A search to start with. Search looks through every folder, ignoring case and diacritics, and lists the results with their folder path.

  • search
    string

    The search, controlled. Pair it with onSearchChange.

  • onSearchChange
    (search: string) => void

    Called with the debounced query, and with "" when a folder is opened from the results.

  • folderId
    string | null

    The open folder, controlled (null is the root). If it disappears from items, the nearest folder that still exists opens.

  • defaultFolderIddefault "null"
    string | null

    The folder that opens first while uncontrolled (null is the root). The playground offers folders of the demo.

  • onFolderChange
    (folderId: string | null) => void

    Called when a folder opens: a double-click, a crumb, the tree, Backspace.

  • sort
    FileManagerSort

    The sort, controlled: { by: "name" | "modified" | "size" | "type", direction: "asc" | "desc" }. Folders always come first.

  • defaultSortdefault "DEFAULT_FILE_MANAGER_SORT"
    FileManagerSort

    The first sort while uncontrolled: { by: "name", direction: "asc" }. Picking Modified or Size in the menu starts with the newest or largest.

  • onSortChange
    (sort: FileManagerSort) => void

    Called from the sort menu and from the column headers of the list.

  • selectedKeys
    string[]

    The selected ids, controlled. Pair it with onSelectedKeysChange.

  • defaultSelectedKeysdefault "[]"
    string[]

    The ids selected at first while uncontrolled; with any selected the toolbar is the bulk bar.

  • onSelectedKeysChange
    (keys: string[]) => void

    Called when the selection changes. Opening another folder clears it.

  • persistKeydefault ""
    string

    Remembers the view and the sort in localStorage under this key ("<key>:view", "<key>:sort"). Empty remembers nothing.

  • confirmDeletedefault true
    boolean

    Ask before deleting, in an alert dialog that names the file or the count. Off, Delete runs at once.

  • previewImagesdefault true
    boolean

    Images open in the built-in lightbox with the folder's other images. Off, they go to onOpen like any other file.

  • acceptdefault ""
    string

    What the upload picker offers, like the input's accept ("image/*,.pdf"). Dropped or pasted files outside it are listed as rejected in the uploads panel instead of reaching onUpload.

  • maxFileSizedefault 0
    number

    The largest file in bytes; bigger ones are listed as rejected with the limit. 0 means no limit.

  • uploadShortcutdefault ""
    string

    A key combo that opens the upload picker from anywhere on the page ("mod+u" notation). Empty binds nothing.

  • localedefault ""
    string

    Formats sizes ("2,4 MB"), dates, counts and the sort order. Empty uses the UIProvider locale, then the browser's.

  • now
    Date | number

    The reference time for "modified 5 min ago". Defaults to a live clock that ticks every minute; demos pin 24.09.2026 16:40.

  • onOpen
    (item: FileManagerItem) => void

    Opens a file. Folders always open in place and images in the lightbox (while previewImages is on). Without it a file with a url opens in a new tab.

  • onUpload
    (files: File[], folderId: string | null) => (void | Promise<unknown>)

    Turns on the Upload button, dropping files from the desktop and pasting them. folderId is the open folder, or the folder tile the files were dropped on. Report progress back through uploads.

  • onCreateFolder
    (name: string, parentId: string | null) => (void | Promise<unknown>)

    Turns on New folder (a dialog, a sheet on phones). A rejected promise keeps the dialog open with its message, so you decide about duplicate names.

  • onRename
    (item: FileManagerItem, name: string) => (void | Promise<unknown>)

    Turns on renaming in place. The field stays busy while the promise runs; a rejection shows its message under it and keeps it open.

  • onMove
    (ids: string[], targetFolderId: string | null) => (void | Promise<unknown>)

    Turns on dragging onto folders, crumbs and tree nodes, and Move to (a dialog with the folder tree, a sheet on phones). Moves into the current folder, into itself or into a subfolder are refused before it runs.

  • onDelete
    (ids: string[]) => (void | Promise<unknown>)

    Turns on Delete in the menus, the bulk bar and the Delete key. The confirmation stays loading while the promise runs.

  • onDownload
    (items: FileManagerItem[]) => void

    Download for files and selections. Without it Download appears when every file has a url and saves them through links.

  • getActions
    (item: FileManagerItem) => MenuEntry[]

    Extra menu entries per item (Share, Copy link, Star), between Download and Delete, in the W1 MenuEntry shape.

  • classNames
    Partial<Record<"toolbar" | "breadcrumb" | "title" | "quota" | "body" | "tree" | "content" | "header" | "tile" | "row" | "select" | "icon" | "name" | "meta" | "actions" | "drop" | "uploads" | "empty" | "move" | "newFolder", string>>

    Extra classes for the parts. title is the phone's folder title, move and newFolder go on the dialogs' bodies, uploads on the floating panel.

  • className
    string

    Extra classes for the root, merged last. Other props (id, aria-*, data-*, handlers) spread onto it.

Parts

  • buildFolderTree

    function

    The folders as nested tree-view nodes with folder icons, sorted by name; a parentId loop is broken (a folder is never listed twice). Pure, so a server can call it. Signature: (items: FileManagerItem[], options?: { locale?: string }) => TreeNode[].

  • getFolderPath

    function

    The trail from the root to a folder as breadcrumb entries (the root's id is "file-manager-root"). Pure and cycle-safe. Signature: (items: FileManagerItem[], folderId: string | null, options?: { rootLabel?: string }) => BreadcrumbEntry[].

  • DEFAULT_FILE_MANAGER_LABELS

    constant

    The English strings, to spread under a translation. Type: FileManagerLabels.

  • DEFAULT_FILE_MANAGER_SORT

    constant

    { by: "name", direction: "asc" }, the default sort. Type: FileManagerSort.

Examples

Search as a list

Invoices from every folder, largest first, each with its path.

A record's files

One client's documents: re-rooted, no tree, small tiles in brand orange.

Phone selection

Long press to select, then the floating bar for bulk actions.

Move dialog

Pick a destination in the folder tree; drops into the same folder are refused.

Loading, empty, uploading

Skeletons, an empty folder with its actions, and the uploads panel.

Read-only viewer

No handlers: browse, search, preview and open only.

Dependencies

@dnd-kit/coremotionlucide-reactalert-dialogavatarbreadcrumbbuttoncheckboxcontext-menudialogdropdown-menuempty-statefile-uploadimage-lightboxinputprogresssegmented-controlskeletontoolbartooltiptree-viewuse-controllable-stateuse-localeuse-long-pressuse-media-queryuse-persisted-stateuse-selectionuse-shortcutfile-typesmotionnumber-formatrelative-timetext-matchtonesui-config

Files

  • components/ui/file-manager.tsx

FAQ

Is the React File manager component free?

The preview, props and docs are free; copying the source needs a Pro plan. See plans.

How do I install File manager?

Run npx wingo-ui@latest add file-manager. It also adds the Wingo UI items it builds on (Alert Dialog, Avatar, Breadcrumb, Button, Checkbox and 27 more) and the npm packages @dnd-kit/core, motion and lucide-react. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/file-manager.

How does File manager behave on phones?

On a phone it starts as a list under the folder's name as a large title with a back link: a tap opens, a long press starts selecting (checkboxes appear, taps add or remove, a floating bar offers Move, Download and Delete), hold and drag a selected file onto a folder to move it, and every menu, the Move dialog and the new folder dialog are bottom sheets.

See also

File ListFile UploadTree ViewImage LightboxBreadcrumb

More React data display components

CountdownApproval FlowAvatarCalendar ViewCode BlockComment Thread
All 23 React data display components

Articles using this component

  • React File Manager: Folders, Uploads and the Backend API

    Component guides · Nov 6, 2026 · 10 min read

  • React Tree View: Checkboxes, Lazy Loading, Drag to Move

    Component guides · Oct 19, 2026 · 10 min read

PreviousFile ListNext Folder
  1. All files
  1. All files
2.4 GB of 10 GB

All files

2.4 GB of 10 GB
  • All files
    • Clients
    • Contracts 2026
    • Human resources
    • Invoices
    • Marketing
    • Quotes
Clients3 items · yesterday
Contracts 20265 items · 2 days ago
Human resources3 items · 1 wk. ago
Invoices4 items · 4 hr. ago
Marketing6 items · 4 days ago
Quotes4 items · 3 days ago
PPTXAcme CRM overview.pptx6.8 MB · 6 days ago
XLSXBudget 2027.xlsx84 KB · 28 min. ago
PDFEmployee handbook.pdf1.2 MB · 3 wk. ago
DOCXMaster agreement.docx212 KB · 2 wk. ago
Owner
Clients3 items · yesterday
yesterday
3 items
Liam Walker
Contracts 20265 items · 2 days ago
2 days ago
5 items
Ryan Brooks
Human resources3 items · 1 wk. ago
1 wk. ago
3 items
Ryan Brooks
Invoices4 items · 4 hr. ago
4 hr. ago
4 items
Olivia Bennett
Marketing6 items · 4 days ago
4 days ago
6 items
Mia Turner
Quotes4 items · 3 days ago
3 days ago
4 items
Noah Hayes
Acme CRM overview.pptx6.8 MB · 6 days ago
6 days ago
6.8 MB
Mia Turner
Budget 2027.xlsx84 KB · 28 min. ago
28 min. ago
84 KB
Olivia Bennett
Employee handbook.pdf1.2 MB · 3 wk. ago
3 wk. ago
1.2 MB
Ryan Brooks
Master agreement.docx212 KB · 2 wk. ago
2 wk. ago
212 KB
Ryan Brooks

Drag files onto a folder or a crumb to move them, drop files from your desktop to upload (over 10 MB fails), right-click for the menu.

confirmDelete: true · previewImages: true · accept: "" · maxFileSize: 0 · uploadShortcut: "" · persistKey: "" · skeletonCount: 12