feat(ux): toast system, accessible modal wrapper, safer dialogs

- Global toast stack (success/error/info) replacing hidden notice/syncError
- Shared Modal: focus trap, Escape, focus restore, scroll lock; all dialogs migrated
- ConfirmDialog tone prop; limit-override now warning-styled
- Single-entry delete now requires confirmation, per-row busy spinner
- Onboarding no longer closes on failed save; inline error + skip option
This commit is contained in:
nh9961
2026-07-19 20:08:14 +00:00
parent f8d06cbafb
commit 733c6cbae8
16 changed files with 857 additions and 520 deletions
+3 -1
View File
@@ -8,6 +8,7 @@ type LogbookViewProps = {
totalEntries: number;
filters: Filters;
flavours: Flavour[];
deletingId: string | null;
onFilterChange: (filters: Filters) => void;
onAdd: () => void;
onEdit: (entry: RedBullEntry) => void;
@@ -19,6 +20,7 @@ export function LogbookView({
totalEntries,
filters,
flavours,
deletingId,
onFilterChange,
onAdd,
onEdit,
@@ -28,7 +30,7 @@ export function LogbookView({
<section className="grid gap-4">
<div className="logbook-layout grid gap-4">
<FiltersPanel filters={filters} flavours={flavours} onChange={onFilterChange} />
<EntryLedger entries={entries} totalEntries={totalEntries} onAdd={onAdd} onEdit={onEdit} onDelete={onDelete} />
<EntryLedger entries={entries} totalEntries={totalEntries} deletingId={deletingId} onAdd={onAdd} onEdit={onEdit} onDelete={onDelete} />
</div>
<LegalFootnote />
</section>
+1 -4
View File
@@ -16,7 +16,6 @@ type SettingsViewProps = {
summary: Dashboard;
dataLoading: boolean;
entries: RedBullEntry[];
notice: string;
setupStatus: SetupStatus;
themeId: string;
themeMode: ThemeMode;
@@ -41,7 +40,6 @@ export function SettingsView({
summary,
dataLoading,
entries,
notice,
setupStatus,
themeId,
themeMode,
@@ -145,9 +143,8 @@ export function SettingsView({
<div className="mt-5 rounded-2xl border border-white/10 bg-white/[0.05] p-4">
<div className="flex items-center gap-2 text-sm text-slate-700">
{dataLoading ? <Loader2 className="animate-spin" size={16} aria-hidden="true" /> : <Cloud size={16} aria-hidden="true" />}
{notice}
{setupStatus.message}
</div>
<p className={`mt-2 text-xs ${setupStatus.state === "ok" ? "text-emerald-700" : "text-amber-700"}`}>{setupStatus.message}</p>
</div>
<button className="secondary-button mt-4 justify-center" type="button" onClick={onLogout}>
<LogOut size={17} aria-hidden="true" />