Rebounce navigation events

This commit is contained in:
2026-01-30 12:26:36 +01:00
parent 5ce6b0c417
commit d3d26c6ae1
8 changed files with 56 additions and 26 deletions

View File

@@ -4,7 +4,7 @@ let { children }: {
} = $props();
let dialog: HTMLDialogElement = $state()
export const open = (button_rect: DOMRect) => {
export const open = (origin: DOMRect|MouseEvent) => {
// Show the window so we can get the location
dialog.showModal()
@@ -15,10 +15,18 @@ export const open = (button_rect: DOMRect) => {
const max_left = window.innerWidth - dialog_rect.width - edge_offset
const max_top = window.innerHeight - dialog_rect.height - edge_offset
// Position the dialog in horizontally in the center of the button and
// verticially below it
const min_left = Math.max((button_rect.left + (button_rect.width/2)) - (dialog_rect.width/2), edge_offset)
const min_top = Math.max(button_rect.bottom, edge_offset)
let min_left: number, min_top: number
if (origin instanceof DOMRect) {
// Position the dialog in horizontally in the center of the button and
// verticially below it
min_left = Math.max((origin.left + (origin.width/2)) - (dialog_rect.width/2), edge_offset)
min_top = Math.max(origin.bottom, edge_offset)
} else if (origin instanceof MouseEvent) {
// Place the dialog at the bottom right of the mouse pointer, like
// regular context menus
min_left = Math.max(origin.clientX, edge_offset)
min_top = Math.max(origin.clientY, edge_offset)
}
// Place the window
dialog.style.left = Math.round(Math.min(min_left, max_left)) + "px"
@@ -35,6 +43,7 @@ export const close = () => {
// the dialog itself then the click was on the dialog background
const click = (e: MouseEvent) => {
if (e.target === dialog) {
e.preventDefault()
dialog.close()
}
}
@@ -42,7 +51,7 @@ const click = (e: MouseEvent) => {
<!-- svelte-ignore a11y_click_events_have_key_events -->
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
<dialog bind:this={dialog} onclick={click}>
<dialog bind:this={dialog} onclick={click} oncontextmenu={click}>
{@render children?.()}
</dialog>