Overview
SaveStatus displays a small colored dot that indicates save status without shifting layout. It shows a tooltip on hover for accessibility. The "saved" state auto-fades after 3 seconds by default.
Key Features
- Four states: idle (hidden), saving (pulse), saved (green), error (red)
- Tooltip on hover for accessibility
- Auto-fade after save (configurable delay)
- No layout shift - absolute positioned in parent
Interactive Examples
States
All four visual states
idle
No dot visible
saving
Pulsing dot
saved
Green dot
error
Red dot
Hover over each dot to see the tooltip. The saving state pulses, saved uses success green, and error uses destructive red.
Interactive Flow
Simulated auto-save flow
Current status: idle
Positioning
Common placement strategies
PageCard with SaveStatus
<PageCard className="relative">
<SaveStatus
status={saveStatus}
className="absolute right-6 top-6 sm:right-12 sm:top-12"
/>
<FormBlock mode="auto-save" showAutoSaveStatus={false}>
...
</FormBlock>
</PageCard>The parent container needs position: relative for absolute positioning. PageCard uses p-6 sm:p-12 padding, so match the offset values.
Props Reference
| Prop | Type | Default | Description |
|---|---|---|---|
status | 'idle' | 'saving' | 'saved' | 'error' | required | Current save status |
errorMessage | string | "Failed to save" | Custom error tooltip text |
fadeDelay | number | 3000 | Ms before 'saved' fades (0 to disable) |
className | string | - | Additional CSS classes for positioning |
Usage
import { SaveStatus, type SaveStatusState } from '@/ui/components';
const [saveStatus, setSaveStatus] = useState<SaveStatusState>('idle');
const handleAutoSave = async (data: FormData) => {
setSaveStatus('saving');
try {
await saveData(data);
setSaveStatus('saved');
} catch (error) {
setSaveStatus('error');
}
};
<PageCard className="relative">
<SaveStatus status={saveStatus} className="absolute right-4 top-4" />
<FormBlock
mode="auto-save"
showAutoSaveStatus={false}
onAutoSave={handleAutoSave}
>
...
</FormBlock>
</PageCard>