From 0a2a38942f2b99a60e525ba126e248233aee1e8a Mon Sep 17 00:00:00 2001 From: Pengusto <106893073+pengusto@users.noreply.github.com> Date: Thu, 1 Oct 2026 14:12:38 +0200 Subject: [PATCH] fix(gui): stack native login confirmation and wrap actions --- .../components/native-main-profiles-view.tsx | 8 ++-- .../native-main-confirmation-layout.test.tsx | 45 +++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 gui/tests/native-main-confirmation-layout.test.tsx diff --git a/gui/src/components/native-main-profiles-view.tsx b/gui/src/components/native-main-profiles-view.tsx index 1ab3efc1441..0e773ee60a2 100644 --- a/gui/src/components/native-main-profiles-view.tsx +++ b/gui/src/components/native-main-profiles-view.tsx @@ -119,7 +119,7 @@ export function NativeMainProfilesView({ } {action && s &&
{ if (event.key === "Escape" && !busy) { event.preventDefault(); onSelect(null); } }}> @@ -131,9 +131,9 @@ export function NativeMainProfilesView({ onStopped(event.target.checked)} /> {t("nativeMain.stopped")}

-
- - +
} diff --git a/gui/tests/native-main-confirmation-layout.test.tsx b/gui/tests/native-main-confirmation-layout.test.tsx new file mode 100644 index 00000000000..27d01ad9cca --- /dev/null +++ b/gui/tests/native-main-confirmation-layout.test.tsx @@ -0,0 +1,45 @@ +import { expect, test } from "bun:test"; +import { Window } from "happy-dom"; +import { renderToStaticMarkup } from "react-dom/server"; +import { NativeMainProfilesView, type NativeMainProfilesViewProps } from "../src/components/native-main-profiles-view"; +import { nativeMainTranslator } from "../src/i18n/native-main-copy"; + +const home = `/srv/${"long-home-segment/".repeat(12)}.codex`; +const profile = { id: "00000000-0000-4000-8000-000000000001", label: "example-profile", identityHint: "native:11111111", state: "inactive" as const }; +const noop = () => {}; +const props: NativeMainProfilesViewProps = { + t: nativeMainTranslator("de"), id: "fixture", open: true, busy: false, blocked: false, + snapshot: { + list: { effectiveCodexHome: home, activeProfileId: null, profiles: [profile] }, + doctor: { effectiveCodexHome: home, activeProfileId: null, supported: true, + authStatus: "ok", keyStore: "available", vaultStatus: "ok", recoveryPending: false }, + }, + label: "", action: { kind: "switch", target: profile.id, label: profile.label }, + confirmedStopped: false, previousId: null, error: null, result: null, refreshFailed: false, + onToggle: noop, onRefresh: noop, onLabel: noop, onRegister: noop, onSelect: noop, + onStopped: noop, onConfirm: noop, +}; +const css = (await Bun.file(new URL("../src/styles.css", import.meta.url)).text()).replace(/^@import .*;$/gm, ""); + +test("native confirmation overrides the shared horizontal notice and permits wrapped actions", async () => { + const window = new Window(); + try { + window.document.head.innerHTML = ``; + window.document.body.innerHTML = renderToStaticMarkup(); + const panel = window.document.querySelector('[role="group"]')!; + // happy-dom checks the cascade, not browser geometry. Inherited notice flex + // previously put heading, prose, path, consent and actions in one narrow row. + expect(window.getComputedStyle(panel).display).toBe("block"); + expect(panel.querySelector("code")?.textContent).toBe(home); + expect(window.getComputedStyle(panel.querySelector(".row")!).flexWrap).toBe("wrap"); + for (const button of panel.querySelectorAll("button")) { + const style = window.getComputedStyle(button); + expect(style.whiteSpace).toBe("normal"); + expect(style.maxWidth).toBe("100%"); + expect(style.overflowWrap).toBe("anywhere"); + } + expect(panel.querySelector(".btn-primary")!.disabled).toBe(true); + } finally { + await window.happyDOM.close(); + } +});