From 6790b60182e345729ab1826c212de8b484157275 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 13:54:37 +0000 Subject: [PATCH] Symmetri i huvudet och i knapparna MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Navigationen trycktes ihop mot högerkanten med ett tomrum efter ordmärket. På smal skärm ligger den nu på egen rad och fördelas över hela måttet — samma fördelning som sidfoten redan använder. Raden får sin balans av marginalerna i stället för av att posterna klumpas ihop. Mätt: noll pixlar kvar på bägge sidor. Portalens sex länkar blir på 360 px en tvåkolumnsindex, vilket läser sig som avsikt och inte som spill. Knapparna var innehållsbreda, så REQUEST ACCOUNT blev dubbelt så bred som LOGIN. Två knappar bredvid varandra där den ena är dubbelt så bred läser sig som en huvudåtgärd och en eftertanke, oavsett vad de heter — och det är inte förhållandet mellan dem. Rutnätet ger dem samma bredd; vikten skiljs av fyllning mot kontur, som resten av systemet gör. Lika bredd räckte inte: REQUEST ACCOUNT bryts till två rader och knapparna blev då olika HÖGA, vilket är samma obalans en rad ned. Bägge fyller nu sin cell. Mätt: 163x57 mot 163x57. ---- Och ett test som slutade mäta ------------------------------------- Namntestet från förra ändringen matchade markup-formen, inte invarianten. När fick en className hittade mönstret noll knappar — testet slutade mäta i stället för att falla. Det enda som avslöjade det var kravet att det ska hitta NÅGOT, och det är därför kravet står där i stället för att tas för givet. Mutationstestat igen efter rättelsen: bägge testen faller när "Customer login" läggs tillbaka. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt --- felsokning/app/src/alva/komponenter.tsx | 16 +++++++++++- .../src/felsokning/__tests__/alva-yta.test.ts | 8 +++++- felsokning/app/src/pages/alva/Ram.tsx | 15 +++++++---- felsokning/app/src/pages/alva/Start.tsx | 25 +++++++++++-------- 4 files changed, 47 insertions(+), 17 deletions(-) diff --git a/felsokning/app/src/alva/komponenter.tsx b/felsokning/app/src/alva/komponenter.tsx index 1a367e0..85e2f0d 100644 --- a/felsokning/app/src/alva/komponenter.tsx +++ b/felsokning/app/src/alva/komponenter.tsx @@ -303,12 +303,21 @@ export function Knapp({ onClick, variant = "primar", disabled, + bred = false, type = "button", }: { children: ReactNode; onClick?: () => void; variant?: "primar" | "sekundar"; disabled?: boolean; + /** + * Fyller sin behållare i stället för att vara innehållsbred. + * + * För knappar som står bredvid varandra: två olika breda knappar läser + * sig som en huvudåtgärd och en eftertanke, oavsett vad de heter. Med + * lika bredd skiljs vikten av fyllning mot kontur i stället. + */ + bred?: boolean; type?: "button" | "submit"; }) { const primär = variant === "primar"; @@ -317,7 +326,12 @@ export function Knapp({ type={type} onClick={onClick} disabled={disabled} - className="border px-4 py-2 text-[13px] font-semibold uppercase tracking-[0.08em] disabled:opacity-40" + // `h-full` och inte bara `w-full`: lika breda knappar där den ena + // texten bryts till två rader blir olika HÖGA, vilket är samma + // obalans en rad ned. Bägge fyller sin cell. + className={`border px-4 py-2 text-[13px] font-semibold uppercase tracking-[0.08em] disabled:opacity-40${ + bred ? " h-full w-full" : "" + }`} style={{ background: primär ? FARG.graphite : FARG.white, color: primär ? FARG.white : FARG.graphite, diff --git a/felsokning/app/src/felsokning/__tests__/alva-yta.test.ts b/felsokning/app/src/felsokning/__tests__/alva-yta.test.ts index c65dacc..850aa1f 100644 --- a/felsokning/app/src/felsokning/__tests__/alva-yta.test.ts +++ b/felsokning/app/src/felsokning/__tests__/alva-yta.test.ts @@ -416,7 +416,13 @@ describe("inloggningen heter samma sak överallt", () => { const namn = ram.match(/\{ till: "\/alva\/logga-in", text: "([^"]+)" \}/)?.[1]; expect(namn).toBeTruthy(); // Varje länk till inloggningen på startsidan bär samma text. - const knappar = [...start.matchAll(/to="\/alva\/logga-in">\s*]*>([^<]+)<\/Knapp>/g)]; + // + // Mönstret tål attribut på länken. Första versionen gjorde inte det, + // och när fick en className matchade den noll knappar — testet + // slutade mäta i stället för att falla. Det enda som avslöjade det var + // kravet nedan på att den ska hitta NÅGOT, vilket är därför det står + // där och inte som en självklarhet. + const knappar = [...start.matchAll(/to="\/alva\/logga-in"[^>]*>\s*]*>([^<]+)<\/Knapp>/g)]; expect(knappar.length).toBeGreaterThan(0); for (const [, text] of knappar) expect(text.trim()).toBe(namn); }); diff --git a/felsokning/app/src/pages/alva/Ram.tsx b/felsokning/app/src/pages/alva/Ram.tsx index 2f86c88..f1d7e7d 100644 --- a/felsokning/app/src/pages/alva/Ram.tsx +++ b/felsokning/app/src/pages/alva/Ram.tsx @@ -49,11 +49,16 @@ export function Ram({ children, portal = false }: { children: ReactNode; portal? - {/* Portalens fem länkar fick inte plats på en telefon och sköt - ut dokumentet i sidled i stället för att brytas. Raden bryts - nu, med tätare mellanrum på smal skärm. */} -