From 9664cd6ee507be2bac1b9920bbb7415fda2976ab Mon Sep 17 00:00:00 2001 From: xarmian Date: Thu, 9 Jul 2026 15:33:37 -0400 Subject: [PATCH] feat(web): shared native-dialog Modal primitive + migrate form modals (TASK-2023) (#881) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(web): shared native-dialog Modal primitive + migrate form modals (TASK-2023) * fix(web): hide closed native-dialog Modal (specificity vs UA rule) — Codex P1 --- web/src/app.css | 7 +- .../components/ConnectWorkspaceModal.svelte | 53 +---- .../lib/components/OpenChildrenDialog.svelte | 143 ++--------- web/src/lib/components/ShareDialog.svelte | 53 +---- web/src/lib/components/admin/UserModal.svelte | 122 ++-------- .../collections/CreateCollectionModal.svelte | 100 ++------ .../collections/EditCollectionModal.svelte | 74 +----- web/src/lib/components/common/Modal.svelte | 222 ++++++++++++++++++ .../editor/ImportFromUrlModal.svelte | 56 ++--- .../layout/CreateWorkspaceModal.svelte | 52 +--- 10 files changed, 350 insertions(+), 532 deletions(-) create mode 100644 web/src/lib/components/common/Modal.svelte diff --git a/web/src/app.css b/web/src/app.css index 5f0e7307..aefa83a4 100644 --- a/web/src/app.css +++ b/web/src/app.css @@ -714,12 +714,15 @@ dialog.attachment-image-lightbox .attachment-image-lightbox-close:hover { .overlay, .palette, .modal, - .modal-backdrop { + .modal-backdrop, + dialog[open] { display: none !important; } /* Modals / dialogs / tooltips. Most KeyboardShortcuts-style overlays - carry role="dialog" on the backdrop. */ + carry role="dialog" on the backdrop. The shared Modal primitive uses a + native (implicit dialog role, no literal role attribute), so it + is covered by the `dialog[open]` selector above. */ [role="dialog"], [role="tooltip"], [role="menu"] { diff --git a/web/src/lib/components/ConnectWorkspaceModal.svelte b/web/src/lib/components/ConnectWorkspaceModal.svelte index 4b8df215..ca0585bf 100644 --- a/web/src/lib/components/ConnectWorkspaceModal.svelte +++ b/web/src/lib/components/ConnectWorkspaceModal.svelte @@ -3,6 +3,7 @@ import { copyToClipboard } from '$lib/utils/clipboard'; import { defaultInstallTab, type InstallTab } from '$lib/utils/platform'; import { api, PadApiError } from '$lib/api/client'; + import Modal from '$lib/components/common/Modal.svelte'; import type { ClaimCodeResponse } from '$lib/types'; interface Props { @@ -297,12 +298,6 @@ toastStore.show(success ? label : 'Failed to copy', success ? 'success' : 'error'); } - function handleKeydown(e: KeyboardEvent) { - if (e.key === 'Escape' && open) { - open = false; - } - } - // --- Display helpers ----------------------------------------------------- let title = $derived( @@ -325,19 +320,13 @@ const CONNECTED_APPS_HREF = '/console/connected-apps'; - + (open = false)} labelledby="connect-ws-title" maxWidth="560px"> + -{#if open} - - -
(open = false)}> - -{/if} + diff --git a/web/src/lib/components/editor/ImportFromUrlModal.svelte b/web/src/lib/components/editor/ImportFromUrlModal.svelte index 3711d573..ddbf40dc 100644 --- a/web/src/lib/components/editor/ImportFromUrlModal.svelte +++ b/web/src/lib/components/editor/ImportFromUrlModal.svelte @@ -3,6 +3,7 @@ import { marked } from 'marked'; import { api, type ImportURLResponse } from '$lib/api/client'; import { toastStore } from '$lib/stores/toast.svelte'; + import Modal from '$lib/components/common/Modal.svelte'; // Context the modal observes about the editor at the moment of // insert. `wasEmpty` mirrors editor.isEmpty BEFORE we splice in @@ -48,12 +49,6 @@ } }); - function handleKeydown(e: KeyboardEvent) { - if (open && e.key === 'Escape') { - open = false; - } - } - async function handleFetch() { errorMessage = ''; result = null; @@ -123,19 +118,22 @@ } - + + -{#if open} - - -
- -{/if} +