Theming
Customize @uploadkitdev/react components with CSS custom properties.
Components use CSS custom properties (not Tailwind classes) so they work in any React project, not just Tailwind projects.
CSS custom properties
All visual properties are controlled by CSS variables. Override them on :root or any ancestor element to theme the components.
Core tokens
| Variable | Light default | Dark default | Controls |
|---|---|---|---|
--uk-primary | #0070f3 | #0070f3 | Button background, dropzone border on hover, progress bar |
--uk-primary-hover | #005bb5 | #005bb5 | Button background on hover |
--uk-accent | #6366f1 | #6366f1 | Focus rings, subtle accent highlights |
--uk-bg | #ffffff | #0a0a0b | Component background |
--uk-bg-secondary | #fafafa | #141416 | File item backgrounds, icon container backgrounds |
--uk-border | #eaeaea | rgba(255,255,255,0.08) | Borders and dividers |
--uk-text | #171717 | #fafafa | Primary text color |
--uk-text-secondary | #666666 | #a1a1aa | Secondary text, labels, hints |
--uk-success | #00c853 | #00c853 | Success state (checkmark, button after upload) |
--uk-error | #dc2626 | #dc2626 | Error state (X icon, button on failure, toast text) |
--uk-beam-success | #22c55e | #22c55e | Animated border-beam success color |
--uk-beam-error | #ef4444 | #ef4444 | Animated border-beam error color |
--uk-radius | 12px | 12px | Border radius on buttons, dropzone, modal, file items |
--uk-font | System UI stack | System UI stack | Font family for all component text |
--uk-transition | 200ms ease-out | 200ms ease-out | Transition duration and easing |
Many components expose additional CSS variables specific to their visual language (e.g. --uk-aurora-from, --uk-brutal-shadow, --uk-terminal-fg). See the individual component reference pages for the full list.
Overriding tokens
Set variables on :root to change them globally, or on a specific ancestor to scope them:
/* Global override */
:root {
--uk-primary: #7c3aed; /* Purple instead of blue */
--uk-primary-hover: #6d28d9;
--uk-radius: 8px; /* Less rounded */
}
/* Scoped override — only affects components inside .upload-area */
.upload-area {
--uk-primary: #059669; /* Green for this section only */
}Dark mode
Dark mode works in two ways:
Automatic (prefers-color-scheme): The background, border, and text tokens switch automatically based on the system preference. No code required.
Explicit (data-theme attribute): Set data-theme="dark" on <html> (or any ancestor) to force dark mode regardless of system preference:
<html lang="en" data-theme="dark">Or toggle dynamically:
document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light');The --uk-primary, --uk-success, and --uk-error tokens are the same in light and dark mode by default. Only the background, border, and text tokens change.
Full brand color override
:root {
/* Primary — your brand color */
--uk-primary: #7c3aed;
--uk-primary-hover: #6d28d9;
/* Softer radius for a more conservative look */
--uk-radius: 6px;
/* Custom font stack */
--uk-font: 'Inter', -apple-system, sans-serif;
}
@media (prefers-color-scheme: dark) {
:root {
/* Lighten primary slightly for better contrast on dark bg */
--uk-primary: #a78bfa;
--uk-primary-hover: #8b5cf6;
}
}Tailwind integration
Use the className prop to add Tailwind utility classes to the outer wrapper, and the appearance prop to target inner elements:
<UploadButton
route="imageUploader"
className="w-full"
appearance={{
button: 'rounded-full font-semibold tracking-tight',
progressBar: 'h-0.5',
progressText: 'text-xs tabular-nums',
}}
/>
<UploadDropzone
route="imageUploader"
className="border-dashed"
appearance={{
container: 'min-h-48 rounded-2xl',
label: 'text-sm',
icon: 'opacity-60',
fileItem: 'bg-neutral-50 dark:bg-neutral-900/50',
}}
/>For deeper customization, override CSS variables in your Tailwind theme:
/* globals.css or your Tailwind CSS file */
@layer base {
:root {
--uk-primary: theme(colors.violet.600);
--uk-primary-hover: theme(colors.violet.700);
--uk-radius: theme(borderRadius.lg);
}
}data-uk-element targeting
Every rendered element in @uploadkitdev/react components has a data-uk-element attribute (no uk- prefix — just the element name). Use CSS attribute selectors to target and restyle specific elements without overriding CSS custom properties.
Element names
| Attribute value | Element |
|---|---|
button | The upload button |
container | The dropzone container |
label | The dropzone label |
upload-icon | The cloud/upload icon in the dropzone |
allowed-content | The "Images up to 4 MB" hint under the dropzone |
file-item | A single file row in the list |
preview | A file preview thumbnail |
progress-bar | The progress bar wrapper |
progress-text | The progress percentage text |
modal | The modal dialog |
submit-button | The modal's primary submit button |
data-state values
Elements also carry a data-state attribute reflecting the current lifecycle:
| Value | Meaning |
|---|---|
idle | No upload in progress (dropzone default) |
ready | Button is idle and ready to receive a click |
dragging | Dropzone is receiving a drag-over |
uploading | Upload in progress |
success | Upload finished successfully |
error | Upload failed |
Direct CSS targeting
/* Style the button */
[data-uk-element="button"] {
background: linear-gradient(135deg, #6366f1, #8b5cf6);
border-radius: 999px;
}
/* Style the dropzone during upload */
[data-uk-element="container"][data-state="uploading"] {
opacity: 0.6;
pointer-events: none;
}
/* Style file items */
[data-uk-element="file-item"] {
background: #f8f9fa;
border-radius: 8px;
}Tailwind withUk wrapper
@uploadkitdev/react ships a withUk Tailwind plugin that generates variants matching the data-uk-element and data-state attributes.
Setup
For Tailwind CSS v4:
/* globals.css */
@import "tailwindcss";
@plugin "@uploadkitdev/react/tailwind";For Tailwind CSS v3:
// tailwind.config.js
const { withUk } = require('@uploadkitdev/react/tailwind');
module.exports = withUk({
content: ['./src/**/*.{ts,tsx}'],
theme: { extend: {} },
plugins: [],
});Available variants
Element variants (target elements by data-uk-element):
| Variant | Targets |
|---|---|
uk-button: | [data-uk-element="button"] |
uk-container: | [data-uk-element="container"] |
uk-label: | [data-uk-element="label"] |
uk-upload-icon: | [data-uk-element="upload-icon"] |
uk-allowed-content: | [data-uk-element="allowed-content"] |
uk-file-item: | [data-uk-element="file-item"] |
uk-progress-bar: | [data-uk-element="progress-bar"] |
uk-preview: | [data-uk-element="preview"] |
uk-modal: | [data-uk-element="modal"] |
uk-submit: | [data-uk-element="submit-button"] |
State variants (target elements by data-state):
| Variant | Targets |
|---|---|
uk-ready: | [data-state="ready"] |
uk-idle: | [data-state="idle"] |
uk-dragging: | [data-state="dragging"] |
uk-uploading: | [data-state="uploading"] |
uk-success: | [data-state="success"] |
uk-error: | [data-state="error"] |
Usage examples
<UploadButton
route="imageUploader"
className="uk-button:rounded-full uk-button:bg-violet-600 uk-uploading:opacity-50"
/>
<UploadDropzone
route="imageUploader"
className="uk-error:border-red-500 uk-error:bg-red-50"
/>CSS custom properties (--uk-primary, --uk-radius, etc.) remain the recommended approach for color and spacing overrides. data-uk-element targeting is best suited for structural or layout changes that can't be expressed as token values.
CSS keyframes
The package defines these animations (used internally):
| Keyframe | Used by |
|---|---|
uk-spin | Spinning loader in UploadButton during upload |
uk-modal-enter | Modal scale-in on open |
uk-modal-exit | Modal scale-out on close |
uk-fade-in | File item appearance, error toast appearance |
uk-progress-indeterminate | Progress bar indeterminate state |
Reduced motion
All component transitions and animations are gated on prefers-reduced-motion. When the user has enabled reduced motion in their OS, durations drop to 0.01ms — effectively instant with no flicker.
@media (prefers-reduced-motion: reduce) {
.uk-button,
.uk-dropzone,
.uk-modal,
/* ... all component elements */
{
transition-duration: 0.01ms !important;
animation-duration: 0.01ms !important;
}
}