fix: show pwa refresh menu options

This commit is contained in:
Federico Jaramillo Martinez
2026-06-01 22:07:03 +02:00
parent 09225a4cea
commit 8cd2bbaf1d
4 changed files with 43 additions and 3 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@jmfederico/pi-web": patch
---
Fix the PWA refresh control menu so its reload options are visible when opened from the compact header button.
@@ -0,0 +1,27 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { actionMenuPanelStyle } from "./actionMenu";
describe("actionMenuPanelStyle", () => {
afterEach(() => {
vi.unstubAllGlobals();
});
it("can constrain menus to the viewport for compact shadow-root controls", () => {
vi.stubGlobal("window", { innerWidth: 400, innerHeight: 800 });
vi.stubGlobal("HTMLElement", FakeHTMLElement);
const target = new FakeHTMLElement({ top: 10, right: 390, bottom: 46, left: 354 });
expect(actionMenuPanelStyle(target, { constrainTo: "viewport" })).toBe("top: 46px; max-height: 754px; right: 10px; max-width: 390px;");
});
});
class FakeHTMLElement extends EventTarget {
constructor(private readonly rect: { top: number; right: number; bottom: number; left: number }) {
super();
}
getBoundingClientRect(): { top: number; right: number; bottom: number; left: number } {
return this.rect;
}
}
+10 -2
View File
@@ -8,10 +8,14 @@ interface ActionMenuRect {
left: number;
}
export function actionMenuPanelStyle(target: EventTarget | null): string {
interface ActionMenuPanelStyleOptions {
constrainTo?: "host" | "viewport";
}
export function actionMenuPanelStyle(target: EventTarget | null, options: ActionMenuPanelStyleOptions = {}): string {
if (typeof HTMLElement === "undefined" || typeof window === "undefined" || !(target instanceof HTMLElement)) return "";
const trigger = target.getBoundingClientRect();
const bounds = actionMenuBounds(target);
const bounds = options.constrainTo === "viewport" ? viewportBounds() : actionMenuBounds(target);
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight;
const leftBound = Math.max(0, bounds.left);
@@ -35,6 +39,10 @@ export function actionMenuPanelStyle(target: EventTarget | null): string {
function actionMenuBounds(target: HTMLElement): ActionMenuRect {
const root = target.getRootNode();
if (typeof ShadowRoot !== "undefined" && root instanceof ShadowRoot && root.host instanceof HTMLElement) return root.host.getBoundingClientRect();
return viewportBounds();
}
function viewportBounds(): ActionMenuRect {
return { top: 0, right: window.innerWidth, bottom: window.innerHeight, left: 0 };
}
@@ -112,7 +112,7 @@ export class AppRefreshControl extends LitElement {
};
private openMenu(target: EventTarget | null): void {
this.menuStyle = actionMenuPanelStyle(target);
this.menuStyle = actionMenuPanelStyle(target, { constrainTo: "viewport" });
this.menuOpen = true;
}