Theming

Customize the appearance of all Dropper components with a simple theming system that allows you to match your brand colors.

Basic Theming

Set a primary color in the DropperProvider:

import { DropperProvider } from '@dropper/react'

<DropperProvider
  publishableKey="pk_dropper_test_xxx"
  theme={{ primary: '#10b981' }}
>
  <App />
</DropperProvider>

Theme Configuration

interface DropperTheme {
  primary: string          // Primary color (required)
  colors?: {              // Optional: Custom color shades
    primary50?: string
    primary100?: string
    primary200?: string
    primary300?: string
    primary400?: string
    primary500?: string
    primary600?: string
    primary700?: string
    primary800?: string
    primary900?: string
  }
}

primary

The main brand color used throughout components:

<DropperProvider
  publishableKey="pk_dropper_test_xxx"
  theme={{ primary: '#3b82f6' }}  // Blue
>
  <App />
</DropperProvider>

colors

Optionally provide custom color shades for fine-grained control:

<DropperProvider
  publishableKey="pk_dropper_test_xxx"
  theme={{
    primary: '#10b981',
    colors: {
      primary50: '#ecfdf5',
      primary100: '#d1fae5',
      primary200: '#a7f3d0',
      primary300: '#6ee7b7',
      primary400: '#34d399',
      primary500: '#10b981',  // Same as primary
      primary600: '#059669',
      primary700: '#047857',
      primary800: '#065f46',
      primary900: '#064e3b',
    },
  }}
>
  <App />
</DropperProvider>

Color Shades

If you only provide primary, color shades are auto-generated. The shades are used for:

  • 50-200: Light backgrounds, hover states
  • 300-400: Borders, secondary elements
  • 500: Primary color (buttons, links)
  • 600-700: Hover states, active states
  • 800-900: Text, dark elements

Preset Themes

Blue (Default)

<DropperProvider
  publishableKey="pk_dropper_test_xxx"
  theme={{ primary: '#3b82f6' }}
>
  <App />
</DropperProvider>

Green

<DropperProvider
  publishableKey="pk_dropper_test_xxx"
  theme={{ primary: '#10b981' }}
>
  <App />
</DropperProvider>

Purple

<DropperProvider
  publishableKey="pk_dropper_test_xxx"
  theme={{ primary: '#8b5cf6' }}
>
  <App />
</DropperProvider>

Red

<DropperProvider
  publishableKey="pk_dropper_test_xxx"
  theme={{ primary: '#ef4444' }}
>
  <App />
</DropperProvider>

Orange

<DropperProvider
  publishableKey="pk_dropper_test_xxx"
  theme={{ primary: '#f97316' }}
>
  <App />
</DropperProvider>

Pink

<DropperProvider
  publishableKey="pk_dropper_test_xxx"
  theme={{ primary: '#ec4899' }}
>
  <App />
</DropperProvider>

Using Theme in Components

useTheme Hook

Access theme values in your components:

import { useTheme } from '@dropper/react'

function CustomButton() {
  const theme = useTheme()
  
  return (
    <button
      style={{
        backgroundColor: theme.primary,
        color: 'white',
      }}
    >
      Click me
    </button>
  )
}

ResolvedTheme Interface

interface ResolvedTheme {
  primary: string
  primary50: string
  primary100: string
  primary200: string
  primary300: string
  primary400: string
  primary500: string
  primary600: string
  primary700: string
  primary800: string
  primary900: string
}

Complete Examples

Brand Color Theme

import { DropperProvider } from '@dropper/react'

function App() {
  return (
    <DropperProvider
      publishableKey={process.env.NEXT_PUBLIC_DROPPER_KEY!}
      theme={{ primary: '#FF6B6B' }}  // Your brand color
    >
      <YourApp />
    </DropperProvider>
  )
}

Dynamic Theme

import { DropperProvider } from '@dropper/react'
import { useState } from 'react'

function App() {
  const [theme, setTheme] = useState('#3b82f6')
  
  return (
    <div>
      <div className="theme-picker">
        <button onClick={() => setTheme('#3b82f6')}>Blue</button>
        <button onClick={() => setTheme('#10b981')}>Green</button>
        <button onClick={() => setTheme('#8b5cf6')}>Purple</button>
      </div>
      
      <DropperProvider
        publishableKey={process.env.NEXT_PUBLIC_DROPPER_KEY!}
        theme={{ primary: theme }}
      >
        <YourApp />
      </DropperProvider>
    </div>
  )
}

User Preference Theme

import { DropperProvider } from '@dropper/react'
import { useEffect, useState } from 'react'

function App() {
  const [theme, setTheme] = useState('#3b82f6')
  
  useEffect(() => {
    // Load user's preferred theme
    const savedTheme = localStorage.getItem('theme')
    if (savedTheme) {
      setTheme(savedTheme)
    }
  }, [])
  
  const updateTheme = (newTheme: string) => {
    setTheme(newTheme)
    localStorage.setItem('theme', newTheme)
  }
  
  return (
    <DropperProvider
      publishableKey={process.env.NEXT_PUBLIC_DROPPER_KEY!}
      theme={{ primary: theme }}
    >
      <YourApp onThemeChange={updateTheme} />
    </DropperProvider>
  )
}

Custom Themed Component

import { useTheme } from '@dropper/react'

function ThemedCard({ children }) {
  const theme = useTheme()
  
  return (
    <div
      style={{
        border: `2px solid ${theme.primary200}`,
        borderRadius: '8px',
        padding: '16px',
        backgroundColor: theme.primary50,
      }}
    >
      <div
        style={{
          color: theme.primary700,
          fontWeight: 'bold',
          marginBottom: '8px',
        }}
      >
        {children}
      </div>
    </div>
  )
}

Gradient Background

import { useTheme } from '@dropper/react'

function GradientHeader() {
  const theme = useTheme()
  
  return (
    <header
      style={{
        background: `linear-gradient(135deg, ${theme.primary500} 0%, ${theme.primary700} 100%)`,
        color: 'white',
        padding: '24px',
      }}
    >
      <h1>My App</h1>
    </header>
  )
}

CSS Variables

Theme colors are also available as CSS variables:

.custom-element {
  background-color: var(--dropper-primary);
  border-color: var(--dropper-primary-200);
  color: var(--dropper-primary-700);
}

Available variables:

--dropper-primary
--dropper-primary-50
--dropper-primary-100
--dropper-primary-200
--dropper-primary-300
--dropper-primary-400
--dropper-primary-500
--dropper-primary-600
--dropper-primary-700
--dropper-primary-800
--dropper-primary-900

Tailwind Integration

If using Tailwind CSS, extend your theme:

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        dropper: {
          50: 'var(--dropper-primary-50)',
          100: 'var(--dropper-primary-100)',
          200: 'var(--dropper-primary-200)',
          300: 'var(--dropper-primary-300)',
          400: 'var(--dropper-primary-400)',
          500: 'var(--dropper-primary-500)',
          600: 'var(--dropper-primary-600)',
          700: 'var(--dropper-primary-700)',
          800: 'var(--dropper-primary-800)',
          900: 'var(--dropper-primary-900)',
        },
      },
    },
  },
}

Then use in your components:

<div className="bg-dropper-500 text-white">
  Themed with Tailwind
</div>

Best Practices

1. Use Brand Colors

Match your brand identity:

<DropperProvider
  publishableKey="pk_dropper_test_xxx"
  theme={{ primary: '#YOUR_BRAND_COLOR' }}
>
  <App />
</DropperProvider>

2. Ensure Contrast

Choose colors with good contrast for accessibility:

// Good: High contrast
theme={{ primary: '#2563eb' }}

// Avoid: Low contrast
theme={{ primary: '#e0e0e0' }}

3. Test Dark Mode

If your app supports dark mode, test theme colors:

const theme = isDarkMode
  ? { primary: '#60a5fa' }  // Lighter for dark mode
  : { primary: '#2563eb' }  // Darker for light mode

<DropperProvider theme={theme}>
  <App />
</DropperProvider>

4. Provide Fallbacks

Always provide a fallback theme:

const userTheme = getUserTheme() || '#3b82f6'

<DropperProvider theme={{ primary: userTheme }}>
  <App />
</DropperProvider>

5. Use useTheme for Custom Components

Access theme in custom components:

import { useTheme } from '@dropper/react'

function CustomComponent() {
  const theme = useTheme()
  
  return (
    <div style={{ color: theme.primary }}>
      Themed content
    </div>
  )
}

Color Accessibility

Ensure your theme colors meet WCAG accessibility standards:

Contrast Ratios

  • Normal text: Minimum 4.5:1 contrast ratio
  • Large text: Minimum 3:1 contrast ratio
  • UI components: Minimum 3:1 contrast ratio

Testing Tools

TypeScript Support

Theme types are fully typed:

import type { DropperTheme, ResolvedTheme } from '@dropper/react'

const theme: DropperTheme = {
  primary: '#3b82f6',
  colors: {
    primary500: '#3b82f6',
    primary600: '#2563eb',
  },
}

<DropperProvider theme={theme}>
  <App />
</DropperProvider>

Default Theme

If no theme is provided, Dropper uses a default blue theme:

{
  primary: '#3b82f6',  // Tailwind blue-500
  primary50: '#eff6ff',
  primary100: '#dbeafe',
  primary200: '#bfdbfe',
  primary300: '#93c5fd',
  primary400: '#60a5fa',
  primary500: '#3b82f6',
  primary600: '#2563eb',
  primary700: '#1d4ed8',
  primary800: '#1e40af',
  primary900: '#1e3a8a',
}

Affected Components

Theming affects all Dropper components:

  • FileUpload: Upload button, progress bars, borders
  • FileList: Selection highlights, action buttons
  • FolderBrowser: Active folder, hover states
  • MediaLibrary: All UI elements
  • Buttons: Primary buttons, links
  • Modals: Headers, action buttons
  • Progress: Progress bars, status indicators

Next Steps