6.3 KiB
6.3 KiB
ErrorDisplay Component API Design
Date: 2025-01-27
Action: 3.1.1.1 - Design ErrorDisplay component API
Status: ✅ Complete
Overview
This document defines the API for a reusable ErrorDisplay component that standardizes error presentation across the application, replacing inconsistent toast notifications and inline error divs.
Component Purpose
The ErrorDisplay component provides:
- Consistent error UI across the application
- Contextual error information (error type, message, details)
- Recovery actions (retry, dismiss, show details)
- Accessibility (ARIA labels, keyboard navigation)
- Flexible placement (inline, modal, banner)
Component API
Props Interface
interface ErrorDisplayProps {
/**
* The error to display
* Can be Error object, ApiError, string, or error-like object
*/
error:
| Error
| ApiError
| string
| {
message: string;
code?: string | number;
status?: number;
details?: Record<string, any>;
};
/**
* Callback when user clicks retry button
* If not provided, retry button is hidden
*/
onRetry?: () => void | Promise<void>;
/**
* Callback when user dismisses the error
* If not provided, dismiss button is hidden
*/
onDismiss?: () => void;
/**
* Whether to show detailed error information
* Default: false (only shows user-friendly message)
* In development, defaults to true
*/
showDetails?: boolean;
/**
* Additional context about where/why the error occurred
* Used for logging and debugging
*/
context?: {
action?: string; // e.g., "fetching tracks", "uploading file"
resource?: string; // e.g., "tracks", "playlist"
resourceId?: string; // e.g., track ID, playlist ID
[key: string]: any; // Additional context
};
/**
* Variant/style of error display
* - "inline": Inline error within content (default)
* - "banner": Full-width banner at top of page
* - "modal": Modal dialog overlay
* - "card": Card-style error display
*/
variant?: 'inline' | 'banner' | 'modal' | 'card';
/**
* Error severity/category
* Affects visual styling (color, icon)
* - "error": Critical errors (default)
* - "warning": Warnings that don't block functionality
* - "info": Informational messages
*/
severity?: 'error' | 'warning' | 'info';
/**
* Size of the error display
* - "sm": Small, compact
* - "md": Medium (default)
* - "lg": Large, prominent
*/
size?: 'sm' | 'md' | 'lg';
/**
* Custom className for styling
*/
className?: string;
/**
* Whether error is dismissible
* Default: true (if onDismiss provided)
*/
dismissible?: boolean;
/**
* Custom title override
* If not provided, uses default title based on error type
*/
title?: string;
/**
* Custom icon override
* If not provided, uses default icon based on severity
*/
icon?: React.ReactNode;
/**
* Additional actions to display alongside retry/dismiss
* Array of { label, onClick, variant } objects
*/
actions?: Array<{
label: string;
onClick: () => void;
variant?: 'default' | 'outline' | 'ghost';
}>;
}
Error Type Handling
Error Object Normalization
The component normalizes different error types:
-
Error Object:
new Error('Failed to fetch tracks');- Message:
error.message - Stack: Available in details (dev mode)
- Message:
-
ApiError (from generated types):
{ code: 404, message: 'Track not found', ... }- Message:
error.message - Code:
error.code - Status:
error.status
- Message:
-
String:
'Network error occurred';- Message: The string itself
-
Axios Error:
axiosError.response.data.error;- Extracts error message from response
- Includes HTTP status code
Default Behavior
Error Message Extraction
-
Priority order:
error.message(if Error object)error.error?.message(if ApiError)error.toString()(fallback)String(error)(final fallback)
-
User-friendly messages:
- Maps technical error codes to user-friendly messages
- Example:
ERR_NETWORK→ "Unable to connect to server. Please check your internet connection."
Visual Styling
- Error severity: Red/error colors
- Warning severity: Yellow/warning colors
- Info severity: Blue/info colors
Icons
- Error:
AlertTriangle(red) - Warning:
AlertCircle(yellow) - Info:
Info(blue)
Usage Examples
Basic Inline Error
<ErrorDisplay
error={error}
onRetry={() => refetch()}
/>
Error with Context
<ErrorDisplay
error={error}
context={{
action: 'fetching tracks',
resource: 'tracks',
}}
onRetry={handleRetry}
showDetails={isDev}
/>
Banner Error
<ErrorDisplay
error={error}
variant="banner"
onDismiss={() => setError(null)}
/>
Modal Error
<ErrorDisplay
error={error}
variant="modal"
onRetry={handleRetry}
onDismiss={() => setShowError(false)}
/>
Error with Custom Actions
<ErrorDisplay
error={error}
onRetry={handleRetry}
actions={[
{
label: 'Report Issue',
onClick: () => reportIssue(error),
variant: 'outline',
},
]}
/>
Integration Points
Replace Toast Errors
Before:
toast.error('Failed to fetch tracks');
After:
<ErrorDisplay
error={error}
variant="inline"
onRetry={() => refetch()}
/>
Replace Inline Error Divs
Before:
{error && (
<div className="text-red-500">{error.message}</div>
)}
After:
{error && (
<ErrorDisplay
error={error}
variant="inline"
size="sm"
/>
)}
Accessibility
- ARIA labels:
role="alert",aria-live="polite" - Keyboard navigation: Tab to retry/dismiss buttons
- Screen reader support: Announces error message
- Focus management: Focuses retry button on mount
Validation
✅ Component API designed
✅ Props interface defined
✅ Error type handling specified
✅ Usage examples provided
✅ Integration points identified
⏭️ Next: Action 3.1.1.2 - Implement ErrorDisplay component