Universal UI plugin for Uppy file uploader providing comprehensive dashboard interface with drag-and-drop, file previews, metadata editing, and progress tracking.
—
Register and manage plugins that integrate with the dashboard interface.
Register a plugin as a dashboard target for integration with the dashboard interface.
/**
* Register plugin as dashboard target
* Only acquirer, progressindicator, and editor plugins are supported
* @param plugin - Plugin instance to register
* @returns Dashboard element for plugin mounting or null if invalid
*/
addTarget(plugin: UnknownPlugin): HTMLElement | null;Usage Examples:
import Dashboard from "@uppy/dashboard";
import GoogleDrive from "@uppy/google-drive";
import Webcam from "@uppy/webcam";
const dashboard = uppy.getPlugin("Dashboard") as Dashboard;
// Manual plugin registration
const googleDrive = new GoogleDrive(uppy, { /* options */ });
const dashboardElement = dashboard.addTarget(googleDrive);
// Automatic registration via plugin mounting
uppy.use(GoogleDrive, { /* options */ });
// Dashboard automatically calls addTarget for compatible plugins
// Custom plugin registration
class CustomAcquirer extends BasePlugin {
type = 'acquirer';
id = 'CustomAcquirer';
title = 'Custom Source';
mount(target, plugin) {
// Plugin-specific mounting logic
return dashboard.addTarget(this);
}
}
uppy.use(CustomAcquirer);Behavior:
Unregister a plugin target from the dashboard interface.
/**
* Unregister plugin target
* Removes plugin from dashboard targets and cleans up state
* @param plugin - Plugin instance to unregister
*/
removeTarget(plugin: UnknownPlugin): void;Usage Examples:
// Remove plugin programmatically
const googleDrive = uppy.getPlugin("GoogleDrive");
if (googleDrive) {
dashboard.removeTarget(googleDrive);
}
// Remove plugin on uninstall
uppy.removePlugin(googleDrive);
// Dashboard automatically calls removeTarget
// Conditional plugin removal
function removePluginIfUnsupported(pluginId: string) {
const plugin = uppy.getPlugin(pluginId);
if (plugin && !plugin.isSupported?.()) {
dashboard.removeTarget(plugin);
uppy.removePlugin(plugin);
}
}Behavior:
Structure and requirements for plugin targets.
/**
* Basic plugin target interface
*/
interface Target {
/** Unique plugin identifier */
id: string;
/** Human-readable plugin name */
name: string;
/** Plugin type classification */
type: 'acquirer' | 'progressindicator' | 'editor';
}
/**
* Enhanced target with render capabilities
*/
interface TargetWithRender extends Target {
/** Function to render plugin icon */
icon: () => ComponentChild;
/** Function to render plugin interface */
render: () => ComponentChild;
}Different types of plugins supported by the dashboard.
/**
* Acquirer plugins - File source providers
* Provide interfaces for selecting files from various sources
*/
interface AcquirerPlugin {
type: 'acquirer';
/** Plugin identifier */
id: string;
/** Display name */
title?: string;
/** Check if plugin is supported in current environment */
isSupported?(): boolean;
/** Render plugin interface */
render(): ComponentChild;
/** Optional icon for plugin */
icon?(): ComponentChild;
/** Handle root-level paste events */
handleRootPaste?(event: ClipboardEvent): void;
/** Handle root-level drop events */
handleRootDrop?(event: DragEvent): void;
/** Check if plugin can handle root drop */
canHandleRootDrop?(event: DragEvent): boolean;
}
/**
* Progress indicator plugins - Upload progress display
* Provide custom progress visualization
*/
interface ProgressIndicatorPlugin {
type: 'progressindicator';
id: string;
title?: string;
render(): ComponentChild;
}
/**
* Editor plugins - File editing capabilities
* Provide file editing and manipulation interfaces
*/
interface EditorPlugin {
type: 'editor';
id: string;
title?: string;
/** Check if plugin can edit specific file */
canEditFile(file: UppyFile): boolean;
/** Select file for editing */
selectFile(file: UppyFile): void;
/** Save editor changes */
save(): void;
/** Render editor interface */
render(): ComponentChild;
}Dashboard automatically discovers and integrates compatible plugins.
/**
* Automatic plugin discovery system
*/
interface AutoDiscovery {
/** Discover plugins on Uppy plugin addition */
onPluginAdded(plugin: UnknownPlugin): void;
/** Remove targets on plugin removal */
onPluginRemoved(plugin: UnknownPlugin): void;
/** Add supported plugin if no target specified */
addSupportedPluginIfNoTarget(plugin: UnknownPlugin): void;
}Auto-Discovery Examples:
// Plugins are automatically discovered when added to Uppy
uppy.use(GoogleDrive, {
companionUrl: 'https://companion.uppy.io'
});
// Dashboard automatically integrates GoogleDrive
uppy.use(Webcam, {
modes: ['picture', 'video']
});
// Dashboard automatically integrates Webcam
// Manual control over auto-discovery
uppy.use(Dashboard, {
plugins: ['GoogleDrive', 'Webcam'] // Only these plugins will be integrated
});
// Disable auto-discovery by providing empty plugins array
uppy.use(Dashboard, {
plugins: [] // No automatic plugin integration
});Configure which plugins are integrated with the dashboard.
/**
* Plugin integration configuration
*/
interface PluginIntegrationConfig {
/** Array of plugin IDs to integrate (empty array disables auto-discovery) */
plugins?: string[];
/** Default icon for plugins without custom icons */
defaultPickerIcon?: typeof defaultPickerIcon;
}Configuration Examples:
// Specific plugin integration
uppy.use(Dashboard, {
plugins: ['GoogleDrive', 'Dropbox', 'Instagram'],
defaultPickerIcon: CustomIcon
});
// All compatible plugins (default behavior)
uppy.use(Dashboard, {
plugins: [] // Will auto-discover all compatible plugins
});
// No plugin integration
uppy.use(Dashboard, {
plugins: [], // Empty array disables auto-discovery
// Must manually call addTarget for any integrations
});State management for integrated plugins and their targets.
/**
* Plugin state properties
*/
interface PluginState {
/** Array of registered plugin targets */
targets: Target[];
/** Currently active picker panel */
activePickerPanel: Target | undefined;
}
/**
* Plugin categorization helpers
*/
interface PluginCategories {
/** Get acquirer plugins (file sources) */
getAcquirers(targets: Target[]): TargetWithRender[];
/** Get progress indicator plugins */
getProgressIndicators(targets: Target[]): TargetWithRender[];
/** Get editor plugins */
getEditors(targets: Target[]): TargetWithRender[];
}Detect and handle plugin compatibility and support.
/**
* Plugin support detection
*/
interface PluginSupport {
/** Check if plugin is supported in current environment */
isTargetSupported(target: Target): boolean;
/** Attach render functions to supported targets */
attachRenderFunctionToTarget(target: Target): TargetWithRender;
}Support Detection Examples:
// Plugin with support detection
class WebRTCPlugin extends BasePlugin {
type = 'acquirer';
isSupported(): boolean {
return !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia);
}
}
// Conditional plugin loading
async function loadCompatiblePlugins() {
const plugins = [
{ Plugin: GoogleDrive, supported: () => true },
{ Plugin: Webcam, supported: () => !!navigator.mediaDevices },
{ Plugin: ScreenCapture, supported: () => !!navigator.mediaDevices.getDisplayMedia }
];
for (const { Plugin, supported } of plugins) {
if (supported()) {
uppy.use(Plugin);
}
}
}
// Runtime support checking
function checkPluginSupport() {
const dashboard = uppy.getPlugin('Dashboard');
const state = dashboard.getPluginState();
state.targets.forEach(target => {
const plugin = uppy.getPlugin(target.id);
if (plugin.isSupported && !plugin.isSupported()) {
console.warn(`Plugin ${target.id} is not supported in this environment`);
dashboard.removeTarget(plugin);
}
});
}Event system for plugin communication and lifecycle management.
/**
* Plugin lifecycle events
*/
interface PluginLifecycleEvents {
/** Plugin added to Uppy */
'plugin-added': (plugin: UnknownPlugin) => void;
/** Plugin removed from Uppy */
'plugin-remove': (plugin: UnknownPlugin) => void;
}Event Examples:
// Listen for plugin lifecycle
uppy.on('plugin-added', (plugin) => {
console.log(`Plugin added: ${plugin.id}`);
if (plugin.type === 'acquirer') {
setupAcquirerIntegration(plugin);
}
});
uppy.on('plugin-remove', (plugin) => {
console.log(`Plugin removed: ${plugin.id}`);
cleanupPluginIntegration(plugin);
});
// Plugin communication
function setupPluginCommunication() {
const dashboard = uppy.getPlugin('Dashboard');
const googleDrive = uppy.getPlugin('GoogleDrive');
if (googleDrive) {
googleDrive.on('folder-selected', (folder) => {
dashboard.showPanel('GoogleDrive');
});
googleDrive.on('files-selected', (files) => {
dashboard.hideAllPanels();
});
}
}Guidelines for developing plugins compatible with dashboard integration.
/**
* Custom plugin development interface
*/
interface CustomPluginRequirements {
/** Unique plugin identifier */
id: string;
/** Plugin type for dashboard integration */
type: 'acquirer' | 'progressindicator' | 'editor';
/** Human-readable title */
title?: string;
/** Render function for plugin interface */
render(): ComponentChild;
/** Optional icon function */
icon?(): ComponentChild;
/** Optional support detection */
isSupported?(): boolean;
/** Mount function for dashboard integration */
mount?(target: any, plugin: any): HTMLElement | null;
}Custom Plugin Examples:
// Custom file source plugin
class CustomCloudStorage extends BasePlugin {
static VERSION = '1.0.0';
type = 'acquirer';
id = 'CustomCloudStorage';
title = 'My Cloud Storage';
constructor(uppy, opts) {
super(uppy, opts);
this.id = this.opts.id || 'CustomCloudStorage';
}
isSupported() {
return typeof window !== 'undefined' && window.fetch;
}
mount(target, plugin) {
const dashboard = target;
return dashboard.addTarget(this);
}
render() {
return h('div', { className: 'custom-cloud-storage' }, [
h('h3', null, 'Select from My Cloud Storage'),
h('button', {
onclick: this.openFilePicker.bind(this)
}, 'Browse Files')
]);
}
icon() {
return h('svg', { /* icon properties */ }, [
// SVG paths for custom icon
]);
}
async openFilePicker() {
const files = await this.fetchFilesFromAPI();
files.forEach(file => this.uppy.addFile(file));
}
}
// Usage
uppy.use(CustomCloudStorage, {
apiKey: 'your-api-key',
serverUrl: 'https://api.example.com'
});Recommended patterns for plugin integration and development.
/**
* Integration best practices
*/
interface IntegrationBestPractices {
/** Provide meaningful plugin IDs and titles */
naming: 'Use descriptive, unique identifiers';
/** Implement proper support detection */
supportDetection: 'Check environment capabilities';
/** Handle errors gracefully */
errorHandling: 'Provide user-friendly error messages';
/** Clean up resources properly */
cleanup: 'Remove event listeners and clean state';
/** Follow accessibility guidelines */
accessibility: 'Support keyboard navigation and screen readers';
/** Provide consistent user experience */
ux: 'Match dashboard styling and interaction patterns';
}Best Practice Examples:
class WellDesignedPlugin extends BasePlugin {
constructor(uppy, opts) {
super(uppy, opts);
this.id = this.opts.id || 'WellDesignedPlugin';
this.title = this.opts.title || 'Well Designed Plugin';
// Validate required options
if (!this.opts.apiKey) {
throw new Error('WellDesignedPlugin: apiKey is required');
}
}
isSupported() {
return !!(window.fetch && window.FileReader);
}
mount(target, plugin) {
this.target = target;
return target.addTarget(this);
}
unmount() {
if (this.target) {
this.target.removeTarget(this);
}
this.cleanup();
}
cleanup() {
// Clean up event listeners, timers, etc.
if (this.pollInterval) {
clearInterval(this.pollInterval);
}
}
render() {
return h('div', {
className: 'uppy-Plugin-panel',
'aria-label': `${this.title} file picker`
}, [
this.renderContent()
]);
}
handleError(error) {
this.uppy.log(`[${this.id}] ${error.message}`, 'error');
this.uppy.info(`${this.title}: ${error.message}`, 'error');
}
}Install with Tessl CLI
npx tessl i tessl/npm-uppy--dashboard