From b121554918a9d961acf41531bb214a6d8d79dd80 Mon Sep 17 00:00:00 2001 From: dev Date: Thu, 14 May 2026 02:28:35 +0200 Subject: [PATCH] Fix UIX docs theme and popover dismiss --- .../popover/popover-provider.svelte.ts | 32 ++++++++++++----- web/routes/uix/+layout@.svelte | 36 +++++++++++++++---- 2 files changed, 54 insertions(+), 14 deletions(-) diff --git a/src/uix/soma/components/popover/popover-provider.svelte.ts b/src/uix/soma/components/popover/popover-provider.svelte.ts index 572598c55..322481243 100644 --- a/src/uix/soma/components/popover/popover-provider.svelte.ts +++ b/src/uix/soma/components/popover/popover-provider.svelte.ts @@ -82,6 +82,7 @@ export class PopoverProvider { readonly overlayPresence: Presence; private contentRef = state(null); private overlayRef = state(null); + private triggerRef = state(null); // tracked IDs contentId = state(''); @@ -157,6 +158,10 @@ export class PopoverProvider { this.contentRef.current = el; } + setTriggerRef(el: HTMLElement | null) { + this.triggerRef.current = el; + } + setOverlayRef(el: HTMLElement | null) { this.overlayRef.current = el; } @@ -166,7 +171,13 @@ export class PopoverProvider { */ dismissWith(action: 'save' | 'cancel' | 'dismiss' | 'dismiss-outside' | 'fail'): Promise { const eventName = action === 'fail' ? 'close-after-fail' : `close-${action}`; - return this.runtime.trigger(eventName); + return this.triggerClose(eventName); + } + + triggerClose(eventName: string, fallbackTarget?: HTMLElement): Promise { + const target = this.contentRef.current ?? fallbackTarget ?? this.triggerRef.current; + if (!target) return this.runtime.trigger(eventName); + return this.runtime.trigger(eventName, { fallbackTarget: target }); } scheduleHoverOpen(delay: number, fallbackTarget: HTMLElement) { @@ -189,7 +200,7 @@ export class PopoverProvider { delay, () => { this.hoverTimer = null; - void this.runtime.trigger('close-dismiss'); + void this.triggerClose('close-dismiss'); }, { replace: true, meta: { component: 'popover', action: 'hover-close' } } ); @@ -246,6 +257,7 @@ export class PopoverTriggerProvider { id: opts.id, ref: opts.ref, owner: this, + onRefChange: (el) => this.provider.setTriggerRef(el), syncAttrs: true }); @@ -267,7 +279,7 @@ export class PopoverTriggerProvider { // pass the trigger as fallbackTarget so the visual channel still has // somewhere to write `data-event*`. if (this.provider.opts.open.current) { - void this.provider.runtime.trigger('close-dismiss'); + void this.provider.triggerClose('close-dismiss', e.currentTarget as HTMLElement); } else { void this.provider.runtime.trigger('present', { fallbackTarget: e.currentTarget as HTMLElement @@ -279,7 +291,7 @@ export class PopoverTriggerProvider { if (e.key === KEYS.ENTER || e.key === KEYS.SPACE) { e.preventDefault(); if (this.provider.opts.open.current) { - void this.provider.runtime.trigger('close-dismiss'); + void this.provider.triggerClose('close-dismiss', e.currentTarget as HTMLElement); } else { void this.provider.runtime.trigger('present', { fallbackTarget: e.currentTarget as HTMLElement @@ -443,12 +455,16 @@ export class PopoverContentProvider { enabled: readableActive(() => this.provider.opts.open.current), onEscapeKeydown: readableActive(() => (e: KeyboardEvent) => { opts.onEscapeKeydown.current(e); - if (!e.defaultPrevented) void this.provider.runtime.trigger('close-dismiss'); + if (!e.defaultPrevented) { + void this.provider.triggerClose('close-dismiss', opts.ref.current ?? undefined); + } }), escapeKeydownBehavior: resolvedEscapeBehavior, onInteractOutside: readableActive(() => (e: PointerEvent) => { opts.onInteractOutside.current(e); - if (!e.defaultPrevented) void this.provider.runtime.trigger('close-dismiss-outside'); + if (!e.defaultPrevented) { + void this.provider.triggerClose('close-dismiss-outside', opts.ref.current ?? undefined); + } }), interactOutsideBehavior: resolvedInteractBehavior, onFocusOutside: opts.onFocusOutside, @@ -563,8 +579,8 @@ export class PopoverCloseProvider { }); } - readonly onclick = (_e: SomaMouseEvent) => { - void this.provider.runtime.trigger('close-cancel'); + readonly onclick = (e: SomaMouseEvent) => { + void this.provider.triggerClose('close-cancel', e.currentTarget as HTMLElement); }; readonly props = $derived.by(() => ({ diff --git a/web/routes/uix/+layout@.svelte b/web/routes/uix/+layout@.svelte index de272e8c9..60d3d8668 100644 --- a/web/routes/uix/+layout@.svelte +++ b/web/routes/uix/+layout@.svelte @@ -1,6 +1,7 @@