SaveIndicator
Keep the difference between saved, dirty, saving and failed visible.
Live — this one is real
Unsaved changes
Usage
import { useState } from "react";
import { SaveIndicator } from "mizu-ui";
export function Example() {
const [state, setState] = useState<"saved" | "unsaved" | "saving" | "error">(
"unsaved",
);
return (
<>
<SaveIndicator state={state} onRetry={() => setState("saving")} />
<select
aria-label="Demo save state"
value={state}
onChange={(e) => setState(e.target.value as typeof state)}
>
{["saved", "unsaved", "saving", "error"].map((v) => (
<option key={v}>{v}</option>
))}
</select>
</>
);
}
Source & setup
Import mizu-ui/styles.css once. Fonts are optional via mizu-ui/fonts.css. Override --mizu-* tokens or use className for local styling. Uses native React and CSS; install the package peers for root imports.
Inspect status/Feedback.tsx
Source is included in the npm package under src/status/Feedback.tsx.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| state | "saved" | "unsaved" | "saving" | "error" | — | Actual persistence state supplied by your app. |
| onRetry | () => void | — | Optional retry for a failed save. |
Accessibility
Changes are announced politely. The retry control appears only when it can recover a failure.
Motion
CSS transitions explain state changes. Reduced motion removes travel.