Skip to content

Repository files navigation

Introduction

A FastPix React component for resumable uploads, built on the FastPix resumable web uploads SDK.

<FastPixUploader /> provides a complete upload experience, including file selection, drag-and-drop, upload progress, and pause, resume, and cancel controls. You can also compose it from individual components to customize the layout. Provide an upload URL, and the component uploads the file in resumable chunks, reports progress, and calls onSuccess when the upload completes.

Key Features

  • Resumable - pause, resume, and cancel an in-progress upload.
  • Eager or lazy URL - pass a URL string, or a function that returns one when a file is selected.
  • Customizable appearance - customize the accent color, border radius, sizing, and other UI elements using CSS variables or the appearance prop. No styling library is required.
  • Server-rendering ready - works in React Server Component setups (such as the Next.js App Router) without extra configuration.
  • Headless option - use a hook to access the upload state and controls while rendering your own UI.
  • Typed - ships with TypeScript definitions.
  • Accessible - status changes are announced to assistive technology, supports keyboard navigation.

Prerequisites

Getting Started with FastPix

To use this component, you need a signed upload URL.

To make API requests, you'll need a valid Access Token and Secret Key. See the Basic Authentication Guide for details on retrieving these credentials.

After you have your credentials, use the Upload media from device API to generate a signed URL. You pass that URL to the component, and it uploads the file in resumable chunks. Creating the upload URL, checking when the media is ready for playback, and rendering the player are handled in your own application.

your app ──── upload URL ────▶ <FastPixUploader /> ──── onSuccess ────▶ your app

Table of Contents

Installation

Install the component using your preferred package manager.

Using npm

npm install @fastpix/fp-react-uploader@latest

Using pnpm

pnpm add @fastpix/fp-react-uploader@latest

Using yarn

yarn add @fastpix/fp-react-uploader@latest

react and react-dom (v18 or later) are peer dependencies and should already be in your app.

Import the stylesheet once, anywhere in your app (for example, your root layout or entry file):

import"@fastpix/fp-react-uploader/styles.css";

Basic Usage

Import

import{FastPixUploader}from"@fastpix/fp-react-uploader";import"@fastpix/fp-react-uploader/styles.css";

Integration

The fastest path - a complete uploader with sensible defaults:

exportdefaultfunctionUploadPage(){return<FastPixUploaderendpoint="https://your-fastpix-upload-url"/>;}

Providing the upload URL

In practice you'll create the upload URL once a file is selected. Pass a function to endpoint instead of a string - it receives the selected File and returns the URL (it may be async). Here getSignedUrl is your own function that returns a FastPix upload URL for the file:

<FastPixUploaderendpoint={getSignedUrl}/>

Note: The signed URL is created through the Upload media from device API. Keep that call on your server so your credentials are never exposed to the browser.

Example project

A minimal, runnable React + Vite example lives in example/. Run npm install && npm run dev in that folder to try the uploader end to end.

Lifecycle Events

Pass callback props to respond to the upload lifecycle. All are optional.

<FastPixUploaderendpoint={getSignedUrl}accept="video/*"onProgress={(percent)=>console.log("Progress:",percent)}onChunkSuccess={({ chunkNumber, totalChunks })=>console.log(`Chunk ${chunkNumber}${totalChunks ? ` of ${totalChunks}` : ""}`)}onSuccess={()=>console.log("Upload complete")}onError={(err)=>console.error("Upload error:",err.message)}/>

onSuccess fires when the upload finishes. Anything after that - waiting for the media to be processed, then playing it - belongs to your application.

See Events for the full list.

Composition

Render the individual components as children to control layout and styling. Each one reads the upload state automatically, so they work wherever you place them and in any order.

import{FastPixUploader,FastPixDropZone,FastPixStatus,FastPixTrack,FastPixStartButton,FastPixPauseButton,FastPixResumeButton,FastPixAbortButton,}from"@fastpix/fp-react-uploader";<FastPixUploaderendpoint={getSignedUrl}autoStart={false}><FastPixDropZoneoverlay><p>Drag a video here, or click to browse</p></FastPixDropZone><FastPixStatus/><FastPixTrackshowLabel/><FastPixStartButton/><FastPixPauseButton/><FastPixResumeButton/><FastPixAbortButton/></FastPixUploader>;

Apply an appearance without writing any CSS:

<FastPixUploaderendpoint={getSignedUrl}size="lg"appearance={{accentColor: "#00d1ff",radius: "12px"}}/>

Drive it programmatically with a ref:

import{useRef}from"react";import{FastPixUploader,typeFastPixUploaderRef}from"@fastpix/fp-react-uploader";functionExample(){constuploader=useRef<FastPixUploaderRef>(null);return(<><FastPixUploaderref={uploader}endpoint={getSignedUrl}/><buttononClick={()=>uploader.current?.pause()}>Pause</button><buttononClick={()=>uploader.current?.reset()}>Start over</button></>);}

Concepts

Upload states. The component is always in exactly one state. Child components and styling react to it.

StateMeaning
idleNo file selected yet.
readyA file is selected but the upload hasn't started (only when autoStart is false).
resolvingPreparing the upload (resolving the URL from your endpoint function).
uploadingSending chunks.
pausedUpload held; it can be resumed from where it stopped.
errorThe upload failed; it can be retried.
successAll bytes delivered.

Typical flow: idle → ready → resolving → uploading → success, with paused reachable from uploading, and error recoverable into a new attempt.

Endpoint. The endpoint prop is either a URL string (known up front) or a function (file) => string | Promise<string> that runs when the upload starts. Use the function form to create the URL per file.

Controlled file. If your app already has a File (for example, from your own picker), pass it via the file prop instead of using the built-in picker or drop zone.

Parameters Accepted

The <FastPixUploader> component accepts the following props:

NameTypeRequiredDescription
endpointstring or (file: File) => string | Promise<string>RequiredThe upload URL, or a function returning it when the upload starts.
fileFileOptionalSupply a file directly instead of using the picker / drop zone.
autoStartbooleanOptionalStart uploading as soon as a valid file is available. Default is true. Set false to require an explicit start.
acceptstringOptionalAllowed file types (e.g. "video/*", ".mp4"), enforced for both the picker and the drop zone. See File access on mobile.
maxFileSizenumber (in KB)OptionalReject files larger than this before uploading.
chunkSizenumber (in KB)OptionalSize of each upload chunk. Minimum: 5120 KB (5 MB), Maximum: 512000 KB (500 MB), in multiples of 256 KB.
retryChunkAttemptnumberOptionalNumber of retry attempts per chunk on failure.
delayRetrynumber (in seconds)OptionalDelay between retry attempts.
disabledbooleanOptionalDisable all interaction. Default is false.
size"sm" | "md" | "lg"OptionalOverall size of the rendered components. Default is "md".
appearanceFastPixAppearanceOptionalAppearance values applied as CSS variables (see Appearance).
classNamestringOptionalClass applied to the root element.
styleCSSPropertiesOptionalInline style applied to the root element.
childrenReactNodeOptionalProvide components to compose your own layout. Omit for the default rendering.

Example usage of integrating all parameters

<FastPixUploaderendpoint={getSignedUrl}autoStart={false}accept="video/*"maxFileSize={2_000_000}// 2 GBchunkSize={16_384}// 16 MB chunksretryChunkAttempt={6}delayRetry={2}size="lg"appearance={{accentColor: "#00d1ff"}}/>

Events

All events are optional callback props on <FastPixUploader>.

NameSignatureFires when
onFileSelect(file: File) => voidA valid, readable file is picked or dropped.
onFileReject(file: File, rejection: FileRejection) => voidA file fails accept, maxFileSize, or can't be read.
onUploadStart(file: File) => voidThe upload begins.
onProgress(percent: number) => voidProgress updates (0–100).
onChunkAttempt(info: ChunkInfo) => voidA chunk upload is attempted.
onChunkSuccess(info: ChunkInfo) => voidA chunk finishes successfully.
onChunkAttemptFailure(info: ChunkFailureInfo) => voidA chunk attempt fails and will be retried.
onPause() => voidThe upload is paused.
onResume() => voidThe upload is resumed.
onAbort() => voidThe upload is cancelled.
onError(error: { message: string }) => voidThe upload fails.
onSuccess() => voidThe upload completes.
onStateChange(state: UploaderState) => voidThe state changes.
onOffline() => voidThe browser loses its network connection (fires while idle or uploading).
onOnline() => voidThe browser regains its network connection.

onFileReject receives a FileRejection with a reason ("type" | "size" | "unreadable" | "busy") and a ready-to-display message. The "unreadable" reason covers files the browser hands over but won't let the page read - see File access on mobile. The "busy" reason fires when a file is selected while an upload is already in progress; cancel the current upload before selecting another.

The chunk events report which chunk is in flight and how many there are: ChunkInfo carries { chunkNumber, totalChunks?, chunkSize? }, and ChunkFailureInfo carries { chunkNumber, attempt, totalAttempts }. Failure events report only chunk counters. To determine the cause of a failure, use the onError callback.

Ref (imperative control)

Pass a ref typed as FastPixUploaderRef to control the component from outside.

MethodDescription
start()Start the upload (use with autoStart={false}).
pause()Pause the active upload.
resume()Resume a paused upload.
abort()Cancel the upload and return to idle.
reset()Clear the file and return to idle ("upload another").
getState()Returns the current UploaderState.
getFile()Returns the current File, or null.
constref=useRef<FastPixUploaderRef>(null);// later:ref.current?.start();if(ref.current?.getState()==="error")ref.current.reset();

Components

All components accept className and style. They must be rendered inside <FastPixUploader>.

<FastPixFilePicker>

A standalone button that opens the file picker. Use it on its own or alongside FastPixDropZone. Do not place it inside FastPixDropZone, because the drop zone already opens the file picker when clicked.

NameTypeDescription
childrenReactNodeCustom button label (default: "Browse…").
<FastPixFilePicker>Select a video</FastPixFilePicker>

<FastPixDropZone>

A drop area that also opens the file dialog when clicked or activated with the keyboard. Put inline, non-interactive content inside it (text or an icon) - not another button.

NameTypeDescription
overlaybooleanShow a highlight overlay while a file is dragged over.
labelstringAccessible label for the zone (default: "Drag a file here, or press to browse").
childrenReactNodeInline content shown inside the zone.
<FastPixDropZoneoverlay><p>Drag a video here, or click to browse</p></FastPixDropZone>

<FastPixTrack>

The progress indicator.

NameTypeDescription
variant"linear" | "radial"Bar or circular indicator. Default is "linear".
showLabelbooleanShow the percentage. Default is false.
<FastPixTrackvariant="radial"showLabel/>

<FastPixStatus>

Text describing the current state.

NameTypeDescription
labelsPartial<Record<UploaderState, string>>Override the text shown for any state (for wording or translation).
<FastPixStatuslabels={{idle: "Pick a video to begin",uploading: "Uploading your video…",success: "All done!",}}/>

<FastPixStartButton>

Starts the upload. Active when a file is ready (or to retry after an error). Pair with autoStart={false}.

NameTypeDescription
childrenReactNodeCustom label (default: "Upload").
<FastPixStartButton>Start upload</FastPixStartButton>

<FastPixPauseButton>

Pauses an active upload.

NameTypeDescription
childrenReactNodeCustom label (default: "Pause").
<FastPixPauseButton>Hold</FastPixPauseButton>

<FastPixResumeButton>

Resumes a paused upload.

NameTypeDescription
childrenReactNodeCustom label (default: "Resume").
<FastPixResumeButton>Continue</FastPixResumeButton>

<FastPixAbortButton>

Cancels the upload and returns to idle.

NameTypeDescription
childrenReactNodeCustom label (default: "Cancel").
<FastPixAbortButton>Cancel</FastPixAbortButton>

Hooks

useUploaderContext()

Access the upload state and controls from within a custom child component of <FastPixUploader>. Use this hook to build custom components that integrate with the uploader.

import{useUploaderContext}from"@fastpix/fp-react-uploader";functionMyProgress(){const{ state, progress }=useUploaderContext();return<div>{state==="uploading" ? `${progress}%` : state}</div>;}// then render <MyProgress /> inside <FastPixUploader>…</FastPixUploader>

It returns:

NameTypeDescription
stateUploaderStateCurrent state.
progressnumber0–100.
fileFile | nullSelected file.
error{ message: string } | nullLast error.
isOfflinebooleanLive network status, tracked in all states including idle.
disabledbooleanWhether interaction is disabled.
acceptstring | undefinedThe configured file filter.
selectFile(file: File) => voidSelect a file (runs validation).
start / pause / resume / abort / reset() => voidControl actions.

useUploader(props)

Build a completely custom uploader with no provided markup. It takes the same options as <FastPixUploader> and returns the same controls as useUploaderContext(), for you to wire into your own components.

import{useUploader}from"@fastpix/fp-react-uploader";functionHeadlessUploader(){const{ state, progress, selectFile, start }=useUploader({endpoint: getSignedUrl,autoStart: false,});return(<div><inputtype="file"onChange={(e)=>e.target.files?.[0]&&selectFile(e.target.files[0])}/><buttononClick={start}disabled={state!=="ready"}>
Upload
</button><progressvalue={progress}max={100}/></div>);}

Appearance

There are three ways to customize the appearance, from lightest to most involved. They can be combined.

1. CSS variables. Set any --fastpix-* variable on the component (or globally on :root). This covers most cases.

.fastpix-uploader {
--fastpix-accent-color:#00d1ff;
--fastpix-radius:12px;
--fastpix-surface:#111;
}

2. The appearance prop. The same variables as a typed object, when you'd rather not write CSS.

<FastPixUploaderendpoint={getSignedUrl}appearance={{accentColor: "#00d1ff",radius: "12px"}}/>

3. className / style. Every component accepts these for full control.

CSS variables

VariableControlsDefault
--fastpix-accent-colorAccent: progress fill, active borders, primary buttons#3b82f6
--fastpix-bgComponent backgroundtransparent
--fastpix-surfaceInner surfaces (drop zone)#0f0f0f
--fastpix-text-colorPrimary text#e5e5e5
--fastpix-text-mutedSecondary text#8a8a8a
--fastpix-border-colorBorders#333
--fastpix-border-color-hoverHover border#555
--fastpix-radiusCorner radius8px
--fastpix-font-familyFont stacksystem-ui, sans-serif
--fastpix-error-colorError text / border#ef4444
--fastpix-success-colorSuccess text / border#22c55e
--fastpix-gapInternal spacing1rem
--fastpix-paddingComponent padding2rem
--fastpix-track-heightProgress bar thickness8px
--fastpix-track-bgEmpty track#222
--fastpix-track-fillFilled trackvar(--fastpix-accent-color)
--fastpix-track-radiusTrack radius999px
--fastpix-dropzone-borderDrop zone border (idle)2px dashed var(--fastpix-border-color)
--fastpix-dropzone-border-activeDrop zone border (dragging)var(--fastpix-accent-color)
--fastpix-dropzone-bgDrop zone background (idle)var(--fastpix-surface)
--fastpix-dropzone-bg-activeDrop zone background (dragging)accent tint
--fastpix-overlay-bgDrag overlayrgba(0,0,0,.6)
--fastpix-button-bgButton backgroundvar(--fastpix-accent-color)
--fastpix-button-textButton label#fff
--fastpix-button-bg-hoverButton hover backgrounddarker accent
--fastpix-button-radiusButton radiusvar(--fastpix-radius)

appearance prop keys

accentColor, background, surface, textColor, mutedColor, borderColor, radius, fontFamily, trackHeight, trackFill, errorColor, successColor.

Styling by state

The root carries the current state as a data attribute, so you can style any phase in plain CSS:

.fastpix-uploader[data-fastpix-state="error"] {
/* error look */
}
.fastpix-uploader[data-fastpix-state="success"] {
/* success look */
}
.fastpix-dropzone[data-fastpix-dragging] {
/* while dragging */
}

Available hooks: data-fastpix-state (the current state), data-fastpix-dragging (on the drop zone), data-fastpix-size (sm/md/lg), and data-fastpix-disabled.

Size

The size prop ("sm" | "md" | "lg") scales padding, spacing, text, and control sizes together.

<FastPixUploaderendpoint={getSignedUrl}size="sm"/>

Types

All types are exported for use in your own code:

FastPixUploaderProps, FastPixUploaderRef, FastPixAppearance, UploaderState, UploaderError, UploaderContextValue, Endpoint, EndpointResolver, FileRejection, ChunkInfo, ChunkFailureInfo, and the prop types for each component (FastPixFilePickerProps, FastPixDropZoneProps, FastPixTrackProps, FastPixStatusProps, FastPixStartButtonProps, FastPixPauseButtonProps, FastPixResumeButtonProps, FastPixAbortButtonProps).

File access on mobile

A browser provides a File object that your application cannot read. This commonly occurs on Android when using accept="video/*", which opens the Photos or Gallery app. The selected file might be sandboxed, preventing the browser from reading its contents for upload.

The component guards against this: when a file is selected, it verifies the bytes are readable before accepting it. If they aren't, the file is rejected through onFileReject with reason: "unreadable" and a message that names the user's browser and OS and tells them to pick the video from their device's file manager instead of the Photos/Gallery picker.

Note: To reduce how often this happens, you can broaden accept (for example "video/*,audio/*") or omit it entirely, which makes Android open the system file manager rather than the media picker. Since you can't force a particular accept, the readability check is always on as a safety net.

Framework and browser support

  • React 18 and later.
  • Next.js (App Router) and other RSC setups - the components are client components and can be rendered directly inside server components with no extra setup.
  • Vite, Create React App, and other bundlers - supported with no configuration.
  • Browsers - modern evergreen browsers. The default styles use color-mix() for accent tints; if you target older browsers, override the affected variables with explicit colors.

Accessibility

  • Status text is announced to assistive technology (role="status", aria-live="polite"), so screen-reader users hear state and progress changes.
  • All controls - including the drop zone - are real buttons: keyboard focusable, activatable with Enter or Space, and shown with visible focus rings.
  • The disabled state is reflected for both pointer and assistive interaction.

References

FastPix Homepage

FastPix Dashboard

Resumable Web Uploads SDK

Basic Authentication Guide

FastPix Documentation

Detailed Usage

For more detailed steps and advanced usage of the underlying upload engine, refer to the official FastPix Documentation.

License

MIT

About

FastPix React Uploader is a customizable React component for chunked, resumable file uploads with drag-and-drop, progress, and pause/resume.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages