Feedback Components
Feedback components communicate status, progress, loading states, and errors to users. They range from inline indicators to fullscreen overlays.
import {
Loading,
ProgressBar,
Skeleton,
Snackbar,
EmptyState,
ErrorBoundary,
} from '@/common/components';Loading
An activity indicator with optional message text. Can render inline or as a fullscreen overlay.
Inline
<Loading />
<Loading message="Fetching data..." />
<Loading size="small" message="Please wait" />Fullscreen
Covers the entire screen with a centered spinner — useful during initial data loads or authentication checks.
<Loading fullScreen message="Loading your profile..." />Props
| Prop | Type | Default | Description |
|---|---|---|---|
message | string | — | Text displayed below the spinner |
fullScreen | boolean | false | Fill the entire screen |
size | 'small' | 'large' | 'large' | Activity indicator size |
accessibilityLabel | string | message or 'Loading' | Custom screen reader label |
ProgressBar
A horizontal progress indicator supporting both determinate (0-100) and indeterminate modes with 5 color schemes and 3 sizes.
Determinate
<ProgressBar value={45} />
<ProgressBar value={80} colorScheme="success" size="lg" />Indeterminate
An animated bar that loops continuously, used when progress percentage is unknown.
<ProgressBar indeterminate />
<ProgressBar indeterminate colorScheme="info" />Color Schemes
<ProgressBar value={20} colorScheme="primary" />
<ProgressBar value={40} colorScheme="success" />
<ProgressBar value={60} colorScheme="warning" />
<ProgressBar value={80} colorScheme="error" />
<ProgressBar value={100} colorScheme="info" />Sizes
| Size | Description |
|---|---|
sm | Thin track |
md | Standard height (default) |
lg | Thick track for high visibility |
Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | number | 0 | Progress value between 0 and 100 (ignored when indeterminate) |
size | 'sm' | 'md' | 'lg' | 'md' | Track height variant |
colorScheme | 'primary' | 'success' | 'error' | 'warning' | 'info' | 'primary' | Fill color scheme |
indeterminate | boolean | false | Animated looping indicator |
accessibilityLabel | string | 'Progress' | Screen reader label |
Skeleton
A placeholder component that mimics content layout during loading. Supports text, circle, and rectangle shapes with a pulse animation.
Shapes
{/* Text line placeholder */}
<Skeleton variant="text" width="80%" height={16} />
{/* Avatar placeholder */}
<Skeleton variant="circle" width={40} height={40} />
{/* Image or card placeholder */}
<Skeleton variant="rect" width="100%" height={200} />Composite Loading State
<View style={{ flexDirection: 'row', gap: 12 }}>
<Skeleton variant="circle" width={48} height={48} />
<View style={{ flex: 1, gap: 8 }}>
<Skeleton variant="text" width="60%" height={14} />
<Skeleton variant="text" width="90%" height={14} />
<Skeleton variant="text" width="40%" height={14} />
</View>
</View>Disabling Animation
<Skeleton variant="rect" width={100} height={100} animated={false} />Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'text' | 'circle' | 'rect' | 'rect' | Shape of the placeholder |
width | DimensionValue | — | Width (number or percentage string) |
height | DimensionValue | — | Height (number or percentage string) |
animated | boolean | true | Enable pulse animation |
The circle variant automatically applies borderRadius equal to half the width, creating a perfect circle. For the text variant, a subtle border radius is applied to match text line appearance.
Snackbar
A brief notification that appears at the bottom of the screen and auto-dismisses after a configurable duration. Supports an optional action button.
Basic Usage
const [visible, setVisible] = useState(false);
<Snackbar
visible={visible}
message="Item saved successfully"
onDismiss={() => setVisible(false)}
/>Variants
<Snackbar visible message="Default notification" variant="neutral" onDismiss={dismiss} />
<Snackbar visible message="Operation completed!" variant="success" onDismiss={dismiss} />
<Snackbar visible message="Something went wrong" variant="error" onDismiss={dismiss} />With Action
<Snackbar
visible={visible}
message="Item deleted"
variant="neutral"
action={{ label: 'Undo', onPress: handleUndo }}
onDismiss={() => setVisible(false)}
/>Custom Duration
<Snackbar
visible={visible}
message="Quick notice"
duration={2000}
onDismiss={() => setVisible(false)}
/>Props
| Prop | Type | Default | Description |
|---|---|---|---|
visible | boolean | required | Whether the snackbar is shown |
message | string | required | Notification text |
variant | 'neutral' | 'success' | 'error' | 'neutral' | Visual variant controlling color |
onDismiss | () => void | required | Callback when the snackbar is dismissed |
duration | number | 4000 | Auto-dismiss delay in milliseconds |
action | { label: string; onPress: () => void } | — | Optional action button |
The Snackbar manages its own auto-dismiss timer. Always update your visible state in the onDismiss callback to keep the UI in sync.
EmptyState
A placeholder component for empty screens or lists. Displays a title, optional message, icon, and call-to-action button.
Basic Usage
<EmptyState title="No Results" message="Try adjusting your search filters." />With Icon and Action
import { Icon } from '@/common/components';
<EmptyState
title="No Notifications"
message="You're all caught up! Check back later."
icon={<Icon name="notifications-off-outline" size={48} variant="muted" />}
actionLabel="Refresh"
onAction={handleRefresh}
/>Sizes
<EmptyState title="Empty" size="sm" />
<EmptyState title="Empty" size="md" />
<EmptyState title="Empty" size="lg" />Props
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | required | Primary heading text |
message | string | — | Descriptive text below the title |
icon | ReactNode | — | Icon element rendered above the title |
actionLabel | string | — | Label for the call-to-action button |
onAction | () => void | — | Callback when the action button is pressed |
size | 'sm' | 'md' | 'lg' | 'md' | Size variant controlling spacing and typography |
ErrorBoundary
A React error boundary (class component) that catches render errors in its subtree and displays a fallback UI with a retry button. Essential for crash recovery at the app and feature level.
Basic Usage
<ErrorBoundary>
<MyFeatureScreen />
</ErrorBoundary>With Error Logging
<ErrorBoundary onError={(error, errorInfo) => crashReporter.log(error, errorInfo)}>
<App />
</ErrorBoundary>Custom Fallback
<ErrorBoundary
fallback={
<View>
<Text>Custom error UI</Text>
<Button title="Go Home" onPress={navigateHome} />
</View>
}
>
<RiskyComponent />
</ErrorBoundary>Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | required | Child components to render when no error is present |
fallback | ReactNode | — | Custom fallback UI (replaces the default error screen) |
onError | (error: Error, errorInfo: ErrorInfo) => void | — | Callback for external error logging |
ErrorBoundary is a class component because React’s getDerivedStateFromError and componentDidCatch lifecycle methods are only available in class components. The default fallback displays a “Something went wrong” message with a “Try Again” button that resets the error state. In development mode, the actual error message is also shown.