From 41faf165eea4c827083508b68e12e30995d977dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Fri, 7 Aug 2026 16:45:17 +0200 Subject: [PATCH] refactor(anamnesis): give each lifestyle entry a proper action row MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The three entries stacked two full-width buttons under the value — a disabled grey Save above a red-outlined "Remove smoking status" — so each one read as a slab of controls with the same weight as the field it belonged to, and scanning them ran the two labels together. Each entry now ends in one right-aligned action row: the quiet destructive first, the primary Save last, both at the mobile tap-target floor. The remove control drops the field name from its visible label, which the Label directly above already carries, and keeps the full phrase as its accessible name and in the dialog it opens — so three of them side by side stay distinguishable to a screen reader. Six languages. Follows the card action-row convention: primary bottom right, secondary beside it, nothing after the row. --- messages/de.json | 1 + messages/en.json | 1 + messages/es.json | 1 + messages/fr.json | 1 + messages/it.json | 1 + messages/pl.json | 1 + .../health-profile-facts-manager.test.tsx | 21 ++++++-- .../records/health-profile-facts-manager.tsx | 49 ++++++++++++------- 8 files changed, 52 insertions(+), 24 deletions(-) diff --git a/messages/de.json b/messages/de.json index f6f5cad7d..722d99e3b 100644 --- a/messages/de.json +++ b/messages/de.json @@ -8844,6 +8844,7 @@ "saveError": "Lebensstil-Kontext konnte nicht gespeichert werden", "loadError": "Lebensstil-Kontext konnte nicht geladen werden", "remove": "{kind} entfernen", + "removeShort": "Entfernen", "removeConfirmTitle": "{kind} entfernen?", "removeConfirmDescription": "Der aktuelle Wert gilt danach als nicht erfasst. Der datierte Verlauf bleibt erhalten.", "removedToast": "{kind} aus dem aktuellen Lebensstil-Kontext entfernt", diff --git a/messages/en.json b/messages/en.json index c4ca0124b..7afbc0765 100644 --- a/messages/en.json +++ b/messages/en.json @@ -8844,6 +8844,7 @@ "saveError": "Could not save lifestyle context", "loadError": "Could not load lifestyle context", "remove": "Remove {kind}", + "removeShort": "Remove", "removeConfirmTitle": "Remove {kind}?", "removeConfirmDescription": "The current value will become not recorded. Its dated history will be retained.", "removedToast": "{kind} removed from current lifestyle context", diff --git a/messages/es.json b/messages/es.json index cae29080d..8f6a2f6b1 100644 --- a/messages/es.json +++ b/messages/es.json @@ -8844,6 +8844,7 @@ "saveError": "No se pudo guardar el contexto del estilo de vida", "loadError": "No se pudo cargar el contexto del estilo de vida", "remove": "Eliminar {kind}", + "removeShort": "Quitar", "removeConfirmTitle": "¿Eliminar {kind}?", "removeConfirmDescription": "El valor actual pasará a constar como no registrado. Se conservará su historial fechado.", "removedToast": "{kind} eliminado del contexto actual del estilo de vida", diff --git a/messages/fr.json b/messages/fr.json index f7904933b..f26b406aa 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -8844,6 +8844,7 @@ "saveError": "Impossible d'enregistrer le contexte du mode de vie", "loadError": "Impossible de charger le contexte du mode de vie", "remove": "Supprimer : {kind}", + "removeShort": "Supprimer", "removeConfirmTitle": "Supprimer : {kind} ?", "removeConfirmDescription": "La valeur actuelle sera considérée comme non renseignée. Son historique daté sera conservé.", "removedToast": "{kind} supprimé du contexte actuel du mode de vie", diff --git a/messages/it.json b/messages/it.json index a45b72862..7175278a8 100644 --- a/messages/it.json +++ b/messages/it.json @@ -8844,6 +8844,7 @@ "saveError": "Impossibile salvare il contesto dello stile di vita", "loadError": "Impossibile caricare il contesto dello stile di vita", "remove": "Rimuovi {kind}", + "removeShort": "Rimuovi", "removeConfirmTitle": "Rimuovere {kind}?", "removeConfirmDescription": "Il valore attuale risulterà non registrato. La cronologia datata verrà conservata.", "removedToast": "{kind} rimosso dal contesto attuale dello stile di vita", diff --git a/messages/pl.json b/messages/pl.json index d39b0a380..972357d82 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -8844,6 +8844,7 @@ "saveError": "Nie udało się zapisać kontekstu stylu życia", "loadError": "Nie udało się wczytać kontekstu stylu życia", "remove": "Usuń: {kind}", + "removeShort": "Usuń", "removeConfirmTitle": "Usunąć: {kind}?", "removeConfirmDescription": "Bieżąca wartość zmieni się na brak danych. Historia z datami zostanie zachowana.", "removedToast": "Usunięto {kind} z bieżącego kontekstu stylu życia", diff --git a/src/components/records/__tests__/health-profile-facts-manager.test.tsx b/src/components/records/__tests__/health-profile-facts-manager.test.tsx index 54641b031..47dff67c2 100644 --- a/src/components/records/__tests__/health-profile-facts-manager.test.tsx +++ b/src/components/records/__tests__/health-profile-facts-manager.test.tsx @@ -114,7 +114,12 @@ describe("health-profile fact removal control", () => { .filter( (props) => props.type === "button" && - props.variant === "outline" && + // The Save control is the entry's PRIMARY action, so it carries the + // default variant. Matching on `variant === "outline"` used to be the + // discriminator and silently stopped matching anything when the + // action row was rebuilt — the button was still there, the selector + // was not. + props.variant === undefined && typeof props.onClick === "function", ) .map((props) => { @@ -132,12 +137,18 @@ describe("health-profile fact removal control", () => { const { html } = render(); expect(confirmButtons).toHaveLength(1); + // The visible label is short — three entries side by side each carrying + // their own field name read as one run of words — but the ACCESSIBLE name + // still says which entry it removes, and so does the dialog it opens. expect(confirmButtons[0]).toMatchObject({ slot: "health-profile-fact-remove-SMOKING_STATUS", - label: "Remove Smoking status", + label: "Remove", + ariaLabel: "Remove Smoking status", + confirmLabel: "Remove Smoking status", + title: "Remove Smoking status?", body: "The current value will become not recorded. Its dated history will be retained.", }); - expect(html).toContain("Remove Smoking status"); + expect(html).toContain("Remove"); expect(apiDelete).not.toHaveBeenCalled(); }); @@ -173,7 +184,7 @@ describe("health-profile fact removal control", () => { const saveButton = renderedButtons.find( (props) => props.type === "button" && - props.variant === "outline" && + props.variant === undefined && typeof props.onClick === "function", ); @@ -207,7 +218,7 @@ describe("health-profile fact removal control", () => { const saveButton = renderedButtons.find( (props) => props.type === "button" && - props.variant === "outline" && + props.variant === undefined && typeof props.onClick === "function", ); diff --git a/src/components/records/health-profile-facts-manager.tsx b/src/components/records/health-profile-facts-manager.tsx index a5cc6e2b4..c08a3eada 100644 --- a/src/components/records/health-profile-facts-manager.tsx +++ b/src/components/records/health-profile-facts-manager.tsx @@ -228,26 +228,21 @@ export function HealthProfileFactsManager() { ))} -
- + {/* One action row per entry (UI-STANDARDS §11 + the action-row + rule): right-aligned, primary last, the quiet destructive + beside it. Two full-width stacked blocks — a grey disabled + slab over a red-outlined one — carried the same visual weight + as the field they belong to and ran into each other when + scanned, which is what "Save" directly above "Remove smoking + status" read as. */} +
{current ? ( } slot={`health-profile-fact-remove-${kind}`} /> ) : null} +
);