From f953f3871690cf6409fe2c8b385efe7918cede14 Mon Sep 17 00:00:00 2001 From: Michael Mainguy Date: Sun, 20 Sep 2026 07:28:43 -0500 Subject: [PATCH] Fit the login form to the picture's box The form now sits in the same 16:9 box as the snapshot, so a card keeps its height whichever it shows. A compact variant drops the aside about which user to create and tightens the spacing, since that space is fixed; the camera page keeps the full form, where there is room. Anything that still doesn't fit scrolls inside the box rather than stretching the card. Co-Authored-By: Claude Opus 5 (1M context) --- src/app/camera-card.test.tsx | 4 ++++ src/app/camera-card.tsx | 17 ++++++++++------- src/app/camera-login.tsx | 19 ++++++++++++++----- .../[id]/camera-login-controls.test.tsx | 2 ++ 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/app/camera-card.test.tsx b/src/app/camera-card.test.tsx index e24896d..88b6474 100644 --- a/src/app/camera-card.test.tsx +++ b/src/app/camera-card.test.tsx @@ -270,6 +270,10 @@ describe("CameraCard", () => { expect(screen.queryByRole("link", { name: "Pop out Porch" })).toBeNull(); // The status still says what is wrong, where the picture would have been. expect(container.querySelector("[data-status='auth']")).toBeTruthy(); + + // Same box as the picture, and the aside that wouldn't fit is left out. + expect(container.querySelector(".aspect-video")).toBeTruthy(); + expect(container.textContent).not.toContain("Use the ONVIF user you created"); }); it("keeps a username the user typed over the saved one", async () => { diff --git a/src/app/camera-card.tsx b/src/app/camera-card.tsx index 5420956..5689bbd 100644 --- a/src/app/camera-card.tsx +++ b/src/app/camera-card.tsx @@ -178,14 +178,17 @@ export default function CameraCard({
  • {/* A camera that can't log in has no picture to show, so the form takes its place. */} {showLogin ? ( -
    +
    - setEditingLogin(false)} - onCancel={problem?.kind === "auth" ? undefined : () => setEditingLogin(false)} - /> +
    + setEditingLogin(false)} + onCancel={problem?.kind === "auth" ? undefined : () => setEditingLogin(false)} + compact + /> +
    ) : ( void; onCancel?: () => void; + /** For the dashboard card, where the form stands in for the picture. */ + compact?: boolean; }) { const status = useCredentialStatus(cam.id); const save = useSaveCredentials(cam.id); @@ -63,16 +66,22 @@ export function CredentialsForm({ const busy = save.isPending || clear.isPending; return ( -
    +
    Camera login
    {reason &&
    {reason}
    } -
    - Use the ONVIF user you created on the camera ( - camera web page). -
    + {/* On a card this has to fit where the picture would be, so the aside goes. */} + {!compact && ( +
    + Use the ONVIF user you created on the camera ( + camera web page). +
    + )} setTypedUsername(e.target.value)} diff --git a/src/app/cameras/[id]/camera-login-controls.test.tsx b/src/app/cameras/[id]/camera-login-controls.test.tsx index 9915d30..b09b350 100644 --- a/src/app/cameras/[id]/camera-login-controls.test.tsx +++ b/src/app/cameras/[id]/camera-login-controls.test.tsx @@ -59,6 +59,8 @@ describe("CameraLoginControls", () => { expect(screen.queryByText("Camera login")).toBeNull(); fireEvent.click(screen.getByRole("button", { name: "Change login" })); expect(await screen.findByText("Camera login")).toBeTruthy(); + // With room to spare here, the form keeps its aside about which user to use. + expect(screen.getByText(/Use the ONVIF user you created/)).toBeTruthy(); fireEvent.click(screen.getByRole("button", { name: "Cancel" })); expect(screen.queryByText("Camera login")).toBeNull();