Theming
All components are unstyled by default beyond functional defaults, and accept style, className, and per-sub-component style props. This means you can restyle anything without forking or replacing components.
Theme tokens
Section titled “Theme tokens”The core package exports design tokens consumed by both UI packages:
import { themeColors, // accent, error, border, bg variants, etc. themeRadius, // sm, md, lg, xl, pill themeFontScale, // xs, sm, md, lg, xl (pixel values) themeSpacingScale, // xxs, xs, sm, … cardX, cardY, dropZone, etc.} from "@hyperserve/upload";These are plain objects — use them in inline styles, CSS-in-JS, or when building your own components alongside the library.
Status config
Section titled “Status config”statusConfig maps every FileStatus to a background color, text color, and label:
import { statusConfig } from "@hyperserve/upload";
// statusConfig.uploading = { bg: "#eff6ff", text: "#2563eb", label: "Uploading" }// statusConfig.failed = { bg: "#fef2f2", text: "#dc2626", label: "Failed" }// ...Components like StatusBadge accept a statusConfig prop to override per-status values:
const statusConfig = { ready: { bg: "#dbeafe", text: "#1d4ed8", label: "Complete" }, failed: { bg: "#fee2e2", text: "#dc2626", label: "Error" },};
// Pass statusConfig to any StatusBadge — only overridden statuses change<StatusBadge status="uploading" statusConfig={statusConfig} /><StatusBadge status="ready" statusConfig={statusConfig} /><StatusBadge status="failed" statusConfig={statusConfig} />Style props
Section titled “Style props”All UI components accept style and className. Compound components like FileItem expose per-sub-component props so you can restyle individual elements without rebuilding the layout:
<FileItem file={file} style={{ background: "#1e293b", border: "1px solid #334155" }}> <FileItem.FileName style={{ color: "#f1f5f9" }} /> <FileItem.FileSize style={{ color: "#64748b" }} /> <FileItem.StatusIcon style={{ color: "#818cf8" }} /> <FileItem.UploadProgress fillStyle={{ background: "linear-gradient(90deg, #818cf8, #a78bfa)" }} /> <FileItem.ErrorMessage style={{ color: "#f87171" }} /></FileItem>DropZone also accepts activeStyle for the drag-active state:
<DropZone style={{ background: "#1e293b", border: "1px dashed #334155" }} activeStyle={{ background: "#1e1b4b", borderColor: "#818cf8" }}/>Complete example
Section titled “Complete example”The demo below applies a dark slate theme entirely through style props — combining DropZone, FileList, and FileItem in one cohesive theme:
<DropZone style={{ background: "#1e293b", border: "1px dashed #334155", borderRadius: 8 }} activeStyle={{ background: "#1e1b4b", borderColor: "#818cf8", borderStyle: "solid" }}> {({ isDragging, openPicker }) => ( <div style={{ display: "flex", gap: "0.5rem", justifyContent: "center", padding: "1rem" }}> <span style={{ color: isDragging ? "#a5b4fc" : "#94a3b8", fontSize: "0.875rem" }}> {isDragging ? "Release to add" : "Drag videos here or "} </span> {!isDragging && ( <button onClick={openPicker} style={{ border: "1px solid #4f46e5", borderRadius: 5, color: "#818cf8" }}> browse </button> )} </div> )}</DropZone>
<FileList> {(file) => ( <FileItem file={file} key={file.id} layout="column" style={{ background: "#1e293b", border: "1px solid #334155" }} > <div style={{ alignItems: "center", display: "flex", justifyContent: "space-between" }}> <FileItem.FileName style={{ color: "#f1f5f9" }} /> <FileItem.RemoveButton style={{ color: "#64748b" }} /> </div> <FileItem.Meta> <FileItem.FileSize style={{ color: "#64748b" }} /> <FileItem.StatusIcon style={{ color: "#818cf8" }} /> </FileItem.Meta> <FileItem.UploadProgress fillStyle={{ background: "linear-gradient(90deg, #818cf8, #a78bfa)" }} /> <FileItem.ErrorMessage style={{ color: "#f87171" }} /> <FileItem.RetryButton style={{ color: "#fb923c" }} /> </FileItem> )}</FileList>