CentercodeDitto
DittoPorygonAPI

SaveStatus

Subtle persistent indicator for auto-save state

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

PropTypeDefaultDescription
status'idle' | 'saving' | 'saved' | 'error'requiredCurrent save status
errorMessagestring"Failed to save"Custom error tooltip text
fadeDelaynumber3000Ms before 'saved' fades (0 to disable)
classNamestring-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>