From 2a6291a547aa4b9a16910f8d826bc4fbf751553b Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Mon, 2 Jun 2025 08:37:01 -0700 Subject: [PATCH] Clicking outside popover dismisses it --- .../admin/AlbumMetadataPopover.svelte | 5 ++++- .../admin/GenericMetadataPopover.svelte | 21 ++++++++++++++++++- .../admin/PostMetadataPopover.svelte | 5 ++++- .../admin/albums/[id]/edit/+page.svelte | 1 + src/routes/admin/albums/new/+page.svelte | 18 ++++++++++++++++ src/routes/admin/posts/[id]/edit/+page.svelte | 1 + src/routes/admin/posts/new/+page.svelte | 20 +----------------- 7 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/lib/components/admin/AlbumMetadataPopover.svelte b/src/lib/components/admin/AlbumMetadataPopover.svelte index 772edcc..5cb8921 100644 --- a/src/lib/components/admin/AlbumMetadataPopover.svelte +++ b/src/lib/components/admin/AlbumMetadataPopover.svelte @@ -6,13 +6,15 @@ triggerElement: HTMLElement onUpdate: (key: string, value: any) => void onDelete: () => void + onClose?: () => void } let { album = $bindable(), triggerElement, onUpdate, - onDelete + onDelete, + onClose = () => {} }: Props = $props() // Convert album date to YYYY-MM-DD format for date input @@ -98,4 +100,5 @@ bind:data={popoverData} {triggerElement} onUpdate={handleDateChange} + {onClose} /> \ No newline at end of file diff --git a/src/lib/components/admin/GenericMetadataPopover.svelte b/src/lib/components/admin/GenericMetadataPopover.svelte index 8e94ec7..dee594f 100644 --- a/src/lib/components/admin/GenericMetadataPopover.svelte +++ b/src/lib/components/admin/GenericMetadataPopover.svelte @@ -31,6 +31,7 @@ onUpdate?: (key: string, value: any) => void onAddTag?: () => void onRemoveTag?: (tag: string) => void + onClose?: () => void } let { @@ -39,7 +40,8 @@ triggerElement, onUpdate = () => {}, onAddTag = () => {}, - onRemoveTag = () => {} + onRemoveTag = () => {}, + onClose = () => {} }: Props = $props() let popoverElement: HTMLDivElement @@ -129,9 +131,26 @@ window.addEventListener('scroll', handleUpdate, true) window.addEventListener('resize', handleUpdate) + // Click outside handler + const handleClickOutside = (event: MouseEvent) => { + const target = event.target as Node + // Don't close if clicking inside the trigger button or the popover itself + if ( + triggerElement?.contains(target) || + popoverElement?.contains(target) + ) { + return + } + onClose() + } + + // Add click outside listener + document.addEventListener('click', handleClickOutside) + return () => { window.removeEventListener('scroll', handleUpdate, true) window.removeEventListener('resize', handleUpdate) + document.removeEventListener('click', handleClickOutside) if (portalTarget) { document.body.removeChild(portalTarget) } diff --git a/src/lib/components/admin/PostMetadataPopover.svelte b/src/lib/components/admin/PostMetadataPopover.svelte index 55c12e8..b06822a 100644 --- a/src/lib/components/admin/PostMetadataPopover.svelte +++ b/src/lib/components/admin/PostMetadataPopover.svelte @@ -12,6 +12,7 @@ onAddTag: () => void onRemoveTag: (tag: string) => void onDelete: () => void + onClose?: () => void } let { @@ -24,7 +25,8 @@ triggerElement, onAddTag, onRemoveTag, - onDelete + onDelete, + onClose = () => {} }: Props = $props() function handleFieldUpdate(key: string, value: any) { @@ -102,4 +104,5 @@ onUpdate={handleFieldUpdate} {onAddTag} {onRemoveTag} + {onClose} /> \ No newline at end of file diff --git a/src/routes/admin/albums/[id]/edit/+page.svelte b/src/routes/admin/albums/[id]/edit/+page.svelte index 0e76306..709c3d8 100644 --- a/src/routes/admin/albums/[id]/edit/+page.svelte +++ b/src/routes/admin/albums/[id]/edit/+page.svelte @@ -577,6 +577,7 @@ triggerElement={metadataButtonElement} onUpdate={handleMetadataUpdate} onDelete={handleMetadataDelete} + onClose={() => isMetadataOpen = false} /> {/if} diff --git a/src/routes/admin/albums/new/+page.svelte b/src/routes/admin/albums/new/+page.svelte index 0797bcd..ee7f371 100644 --- a/src/routes/admin/albums/new/+page.svelte +++ b/src/routes/admin/albums/new/+page.svelte @@ -258,6 +258,7 @@ triggerElement={metadataButtonElement} onUpdate={handleMetadataUpdate} onDelete={() => {}} + onClose={() => isMetadataOpen = false} /> {/if} @@ -394,6 +395,23 @@ } } + .btn { + padding: $unit-2x $unit-3x; + border: none; + border-radius: 50px; + font-size: 0.925rem; + cursor: pointer; + transition: all 0.2s ease; + display: flex; + align-items: center; + gap: $unit; + + &:disabled { + opacity: 0.6; + cursor: not-allowed; + } + } + .metadata-popover-container { position: relative; } diff --git a/src/routes/admin/posts/[id]/edit/+page.svelte b/src/routes/admin/posts/[id]/edit/+page.svelte index cb6e93f..17d4ee8 100644 --- a/src/routes/admin/posts/[id]/edit/+page.svelte +++ b/src/routes/admin/posts/[id]/edit/+page.svelte @@ -240,6 +240,7 @@ onAddTag={addTag} onRemoveTag={removeTag} onDelete={openDeleteConfirmation} + onClose={() => showMetadata = false} /> {/if} diff --git a/src/routes/admin/posts/new/+page.svelte b/src/routes/admin/posts/new/+page.svelte index f2210da..2feb618 100644 --- a/src/routes/admin/posts/new/+page.svelte +++ b/src/routes/admin/posts/new/+page.svelte @@ -115,25 +115,6 @@ } - function handleMetadataPopover(event: MouseEvent) { - const target = event.target as Node - // Don't close if clicking inside the metadata button or anywhere in a metadata popover - if ( - metadataButtonRef?.contains(target) || - document.querySelector('.metadata-popover')?.contains(target) - ) { - return - } - showMetadata = false - } - - - $effect(() => { - if (showMetadata) { - document.addEventListener('click', handleMetadataPopover) - return () => document.removeEventListener('click', handleMetadataPopover) - } - }) // Mock post object for metadata popover const mockPost = $derived({ @@ -190,6 +171,7 @@ onAddTag={addTag} onRemoveTag={removeTag} onDelete={() => {}} + onClose={() => showMetadata = false} /> {/if}