Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,8 @@ yarn-debug.log*
yarn-error.log*

hidden
.cursorrules
.cursorrules
/examples/**/node_modules
/examples/**/.next
/examples/**/build
/examples/**/dist
162 changes: 161 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,167 @@
<h1 align="center">Files ui</h1>

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
Thils file also consider all dropzone-ui [releases](https://github.com/dropzone-ui/dropzone-ui-react/releases).
This file also consider all dropzone-ui [releases](https://github.com/dropzone-ui/dropzone-ui-react/releases).

## [2.0.0](https://github.com/files-ui/files-ui-react/releases/tag/v2.0.0) (2026-07-28)

## ✨ Major Release — Headless Architecture, Server Actions & RSC Boundaries

### Summary

v2.0.0 is a fully backward-compatible major release. All existing component APIs continue to work unchanged. The new capabilities are opt-in.

---

### New Features

#### Headless Hook — `useFilesUI`

A framework-agnostic hook that extracts all validation, upload orchestration, and state management from `<Dropzone>` and `<FileInputButton>`. Use it to build fully custom upload UIs without any of the library's default styling.

```tsx
import { useFilesUI } from "@files-ui/react";

function MyCustomUploader() {
const { files, isUploading, uploadFiles, getDragHandlers, getInputProps } = useFilesUI({
accept: "image/*",
maxFileSize: 5 * 1024 * 1024,
url: "/api/upload",
});
return (
<div {...getDragHandlers()}>
<input {...getInputProps()} />
<button onClick={() => uploadFiles()} disabled={isUploading}>Upload</button>
</div>
);
}
```

#### Server Actions — `action` prop

Native Next.js 16 App Router Server Actions support. Pass a Server Action directly to `<Dropzone>` or `<FileInputButton>` — no manual `fetch()` calls required.

```tsx
// app/actions/upload.ts
"use server";
export async function uploadFile(formData: FormData) {
const file = formData.get("file") as File;
return { success: true, message: `Received ${file.name}` };
}

// app/upload/UploadPanel.tsx
"use client";
import { Dropzone } from "@files-ui/react/client/dropzone";
import { uploadFile } from "../actions/upload";
export default function UploadPanel() {
return <Dropzone action={uploadFile} />;
}
```

New core exports:

- `uploadExtFileViaAction(extFile, action, uploadLabel?)` — uploads a single file via Server Action
- `uploadExtFilesViaAction(extFiles, action, uploadLabel?, maxConcurrency?, onFileComplete?)` — uploads multiple files

#### RSC Client Boundaries

Each interactive component now ships a dedicated client-only import path for safe use in Next.js 16 App Router without accidentally pulling browser code into Server Components.

```tsx
import { Dropzone } from "@files-ui/react/client/dropzone";
import { FileInputButton } from "@files-ui/react/client/file-input-button";
import { FileCard } from "@files-ui/react/client/file-card";
import { FileMosaic } from "@files-ui/react/client/file-mosaic";
import { Avatar } from "@files-ui/react/client/avatar";
import { FullScreen } from "@files-ui/react/client/full-screen";
```

The root import `from "@files-ui/react"` continues to work for non-Next.js consumers.

New named exports in root: `DropzoneClient`, `DropzoneContainer`, `FileInputButtonClient`, `FileInputButtonContainer`, `FileCardClient`, `FileCardContainer`, `FileMosaicClient`, `FileMosaicContainer`, `AvatarClient`, `AvatarContainer`, `FullScreenClient`, `FullScreenContainer`.


#### Font loading behavior (Poppins opt-in)

- Removed automatic Google Fonts `@import` from component stylesheets (`Avatar`, `Dropzone`, `FileCard`, `FileMosaic`, `MaterialButton`)
- Updated component font declarations to use fallback stack:
- `"Poppins", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif`
- Updated tooltip styles to use the same fallback stack
- Consumers who want `Poppins` should load it explicitly in their application
- Added documentation: `docs/react/Fonts.md`

#### Global `fontFamily` config via `FilesUiProvider`

- Added `fontFamily` prop to `FilesUIConfig`
- When set, `FilesUiProvider` injects a single `<style>` element that sets the CSS custom property `--files-ui-font-family` on `:root`
- All component CSS files now reference `var(--files-ui-font-family, "Poppins", ...)` instead of a hardcoded font stack
- Allows consumers to override fonts globally without per-component styling
- Standard system fallbacks are appended automatically to the user-provided font

```tsx
<FilesUiProvider config={{ fontFamily: "Inter" }}>
<App />
</FilesUiProvider>
```


#### `@files-ui/core` v2.1.0 — Pure JavaScript Source

The core package now ships JavaScript source files (`.js`) with TypeScript declarations (`.d.ts`) for improved readability and easier community contribution. The public TypeScript DX (types, autocomplete) is unchanged.

---

### Breaking Changes

None. All v1.x component props, hooks, and export paths remain fully operational.

### Deprecated (still functional, shown in docs as deprecated)

- `useDropzoneFileListUpdater`, `useDropzoneValidation`, `useNumberOfValidFiles`, `useIsUploading` — prefer `useFilesUI`

---

### Migration Guide (v1.x → v2.0)

#### No action required for most users

Standard usage of `<Dropzone>`, `<FileMosaic>`, `<FileCard>`, `<FileInputButton>`, `<Avatar>`, and `<FullScreen>` with their existing props requires no changes.

#### Opt-in: Server Actions

Replace `uploadConfig={{ url: "..." }}` with the `action` prop:

```tsx
// Before (v1.x — still works)
<Dropzone uploadConfig={{ url: "/api/upload" }} />

// After (v2.0 — Server Actions)
<Dropzone action={uploadServerAction} />
```

#### Opt-in: Headless pattern

```tsx
// Before (v1.x)
<Dropzone accept="image/*" maxFileSize={5e6} onChange={setFiles} onUploadFinish={handleUpload} />

// After (v2.0 headless)
const { files, uploadFiles, getDragHandlers, getInputProps } = useFilesUI({
accept: "image/*", maxFileSize: 5e6, onChange: setFiles, onUploadFinish: handleUpload,
});
```

#### Opt-in: Next.js 16 App Router client imports

```tsx
// Before (v1.x — root import still works in non-Next.js apps)
import { Dropzone } from "@files-ui/react";

// After (v2.0 — guaranteed client boundary in Next.js 16 App Router)
import { Dropzone } from "@files-ui/react/client/dropzone";
```

---

## [1.3.0](https://github.com/files-ui/files-ui-react/releases/tag/v1.3.0) (2026-07-05)

Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ UI components for file uploads with [React js](https://react.dev/).
<div align="center">

[![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/files-ui/react/blob/HEAD/LICENSE)
[![npm latest package](https://img.shields.io/npm/v/@files-ui/react.svg?logo=npm&logoColor=fff&label=NPM+package&color=limegreen)](https://www.npmjs.com/package/@files-ui/react) [![kandi X-Ray](https://kandi.openweaver.com/badges/xray.svg)](https://kandi.openweaver.com/typescript/files-ui/files-ui-react) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
[![npm latest package](https://img.shields.io/npm/v/@files-ui/react.svg?logo=npm&logoColor=fff&label=NPM+package&color=limegreen)](https://www.npmjs.com/package/@files-ui/react) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
[![GitHub Repo stars](https://img.shields.io/github/stars/files-ui/react?label=Star%20me%20please%20:D&style=social)](https://github.com/files-ui/react)
[![Node.js CI](https://github.com/files-ui/files-ui-react/actions/workflows/node.js.yml/badge.svg)](https://github.com/files-ui/files-ui-react)

Expand All @@ -25,9 +25,10 @@ UI components for file uploads with [React js](https://react.dev/).
</a>
</p>

- :heart: it ?, support us by giving a :star: on :octocat: [Github](https://github.com/dropzone-ui/dropzone-ui) :D

- :zap: Enjoying @files-ui/react? [Please leave a short review on Openbase](https://openbase.com/js/@files-ui/react#rate)

- :heart: it ?, support us by giving a :star: on :octocat: [Github](https://github.com/files-ui/files-ui-react) :D

- :eyes: More previews [here](#more-previews).

## Installation
Expand Down
141 changes: 141 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# @files-ui/react Examples

This directory contains complete, production-ready sample applications demonstrating the full feature set of `@files-ui/react` v2.0.

## Projects

### 1. [vite-file-manager](./vite-file-manager/)
**Vite + React 19 + Express Backend**

A document management dashboard showcasing:
- Standard Dropzone upload with validation
- Concurrent uploads (3 simultaneous)
- Chunked upload for large files (100MB+)
- Browse with grid/list toggle
- Size variants (xs/small/medium/large)
- Headless custom UI with `useFilesUI` hook
- Global font family and dark mode settings
- Express server with upload/download/delete endpoints

**Stack:** Vite 6, React 19, TypeScript, Express 5, multer

[View Documentation →](./vite-file-manager/README.md)

---

### 2. [nextjs-gallery](./nextjs-gallery/)
**Next.js 16 App Router + Server Actions**

An image gallery application demonstrating:
- Server-side rendering with React Server Components
- Upload via Next.js Server Actions (no XHR!)
- RSC client subpath imports
- Headless upload with `useFilesUI` + Server Actions
- Avatar upload component
- Full-screen image viewer
- Loading states with skeleton components
- Global font configuration

**Stack:** Next.js 16, React 19, TypeScript, Tailwind CSS 4

[View Documentation →](./nextjs-gallery/README.md)

---

## Feature Coverage Matrix

| Feature | Vite Project | Next.js Project |
|---------|:---:|:---:|
| **Components** |
| `<Dropzone>` | ✅ | ✅ |
| `<FileMosaic>` | ✅ | ✅ |
| `<FileCard>` | ✅ | — |
| `<Avatar>` | — | ✅ |
| `<FullScreen>` | — | ✅ |
| **v2.0 Features** |
| `useFilesUI` headless | ✅ | ✅ |
| Server Actions (`action` prop) | — | ✅ |
| RSC client subpaths | — | ✅ |
| Size `variant` prop | ✅ | — |
| `fontFamily` config | ✅ | ✅ |
| Skeleton components | ✅ | ✅ |
| **Upload Strategies** |
| Standard XHR | ✅ | — |
| Concurrent upload | ✅ | — |
| Chunked upload | ✅ | — |
| Server Actions | — | ✅ |
| **Backend** |
| Express + multer | ✅ | — |
| Next.js Server Actions | — | ✅ |

---

## Quick Start

### Vite File Manager

```bash
cd vite-file-manager
npm install
npm run dev
```

Runs frontend on http://localhost:3000 and backend on http://localhost:3001

### Next.js Gallery

```bash
cd nextjs-gallery
npm install
npm run dev
```

Runs on http://localhost:3000

---

## Common Setup

Both projects use `@files-ui/react` via local link. Before running either project:

1. Build the library:
```bash
cd ../../
npm run build
```

2. Install example dependencies:
```bash
cd examples/vite-file-manager # or nextjs-gallery
npm install
```

---

## Learning Path

1. **Start with Vite Project** - Demonstrates core upload functionality and all component variants
2. **Move to Next.js Project** - Shows RSC integration, Server Actions, and advanced Next.js patterns
3. **Compare Headless Pages** - See how the same `useFilesUI` hook works with different backends

---

## Production Notes

These examples use simplified "databases" for demonstration:
- **Vite:** In-memory object (resets on server restart)
- **Next.js:** JSON file in `data/photos.json`

For production:
- Replace with real databases (PostgreSQL, MongoDB, etc.)
- Add authentication
- Implement proper error handling
- Add file validation on server
- Use cloud storage (S3, Azure Blob, etc.) instead of local disk

---

## Issues or Questions?

- [Report Issues](https://github.com/files-ui/files-ui-react/issues)
- [View Documentation](https://files-ui.com)
Loading
Loading