Clicking outside popover dismisses it

This commit is contained in:
Justin Edmund 2025-06-02 08:37:01 -07:00
parent 9a09dde557
commit 2a6291a547
7 changed files with 49 additions and 22 deletions

View file

@ -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}
/>

View file

@ -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)
}

View file

@ -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}
/>

View file

@ -577,6 +577,7 @@
triggerElement={metadataButtonElement}
onUpdate={handleMetadataUpdate}
onDelete={handleMetadataDelete}
onClose={() => isMetadataOpen = false}
/>
{/if}
</div>

View file

@ -258,6 +258,7 @@
triggerElement={metadataButtonElement}
onUpdate={handleMetadataUpdate}
onDelete={() => {}}
onClose={() => isMetadataOpen = false}
/>
{/if}
</div>
@ -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;
}

View file

@ -240,6 +240,7 @@
onAddTag={addTag}
onRemoveTag={removeTag}
onDelete={openDeleteConfirmation}
onClose={() => showMetadata = false}
/>
{/if}
</div>

View file

@ -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}
</div>