feat(common): generic Promise-based ConfirmDialog primitive (#640 part C)
Ports 8digit/picpeak@88bfde1 — replaces `window.confirm()` with a styled, themed, accessible in-app modal. Usage: const confirm = useConfirm(); const ok = await confirm({ title: 'Delete event?', message: 'This will permanently remove the gallery and all photos.', variant: 'danger', confirmLabel: 'Delete', }); if (ok) doDelete(); Three variants: 'primary' (default, no icon), 'danger' (red AlertCircle + red confirm button), 'warning' (amber AlertTriangle). Keyboard support: Escape cancels, Enter confirms (unless focus is in an input/textarea/select so an open form doesn't get hijacked), backdrop click cancels. Cancel button is focused by default — a stray Enter cannot accidentally confirm a destructive action. Wraps at App.tsx level, inside GlobalThemeProvider so the modal respects the theme tokens, above the toast container so a confirm appearing under a toast still gets the click. Provider exports through components/common alongside the rest of the shared primitives. This PR only lands the primitive. Existing window.confirm() call-sites are left untouched — sweeping them is follow-up work that can land in any cadence (each sweep is one component, no architectural risk). Existing structured-input flows (PublishGalleryDialog, DuplicateEventDialog, PasswordResetModal, etc.) stay as-is — they collect data, not yes/no. No new i18n entries — uses common.cancel / common.confirm / common.close which already exist in EN + DE. ### Test plan - [x] tsc --noEmit clean - [x] eslint clean on changed files - [ ] Manual: pick any existing window.confirm() site (e.g. EventDetailsPage delete button), swap to useConfirm(), verify the modal renders with theme tokens, Escape cancels, Enter confirms, backdrop click cancels, focus lands on Cancel - [ ] Manual: variant='danger' renders red confirm button + AlertCircle icon - [ ] Manual: open the dialog from inside another modal (e.g. a settings panel) — z-[9999] keeps the confirm on top of any other overlay
This commit is contained in:
@@ -73,6 +73,7 @@ import { RequireFeature } from './components/admin/RequireFeature';
|
||||
import { PageErrorBoundary, OfflineIndicator, SkipLink, DynamicFavicon, RobotsMetaTags, CMSContentBlock, Loading } from './components/common';
|
||||
import { MaintenanceWrapper } from './components/MaintenanceWrapper';
|
||||
import { GlobalThemeProvider } from './components/GlobalThemeProvider';
|
||||
import { ConfirmDialogProvider } from './components/common';
|
||||
import { usePublicSettings } from './hooks/usePublicSettings';
|
||||
|
||||
// Create a client
|
||||
@@ -149,6 +150,7 @@ function App() {
|
||||
<MaintenanceProvider>
|
||||
<ThemeProvider>
|
||||
<GlobalThemeProvider>
|
||||
<ConfirmDialogProvider>
|
||||
<DynamicFavicon />
|
||||
<RobotsMetaTags />
|
||||
<Router>
|
||||
@@ -406,6 +408,7 @@ function App() {
|
||||
pauseOnHover
|
||||
theme={toastTheme}
|
||||
/>
|
||||
</ConfirmDialogProvider>
|
||||
</GlobalThemeProvider>
|
||||
</ThemeProvider>
|
||||
</MaintenanceProvider>
|
||||
|
||||
Reference in New Issue
Block a user