diff --git a/messages/de.json b/messages/de.json index e4cc18cde..1b2965760 100644 --- a/messages/de.json +++ b/messages/de.json @@ -1281,8 +1281,7 @@ "group": { "data": "Daten", "reminders": "Erinnerungen", - "lifecycle": "Lebenszyklus", - "danger": "Gefahrenzone" + "lifecycle": "Lebenszyklus" }, "dataPortability": { "import": { diff --git a/messages/en.json b/messages/en.json index 37ad2fcff..66dd819e2 100644 --- a/messages/en.json +++ b/messages/en.json @@ -1281,8 +1281,7 @@ "group": { "data": "Data", "reminders": "Reminders", - "lifecycle": "Lifecycle", - "danger": "Danger zone" + "lifecycle": "Lifecycle" }, "dataPortability": { "import": { diff --git a/messages/es.json b/messages/es.json index 0d88c307a..6a3b5b635 100644 --- a/messages/es.json +++ b/messages/es.json @@ -1281,8 +1281,7 @@ "group": { "data": "Datos", "reminders": "Recordatorios", - "lifecycle": "Ciclo de vida", - "danger": "Zona de peligro" + "lifecycle": "Ciclo de vida" }, "dataPortability": { "import": { diff --git a/messages/fr.json b/messages/fr.json index f2a73b2cb..945c3232d 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -1281,8 +1281,7 @@ "group": { "data": "Données", "reminders": "Rappels", - "lifecycle": "Cycle de vie", - "danger": "Zone de danger" + "lifecycle": "Cycle de vie" }, "dataPortability": { "import": { diff --git a/messages/it.json b/messages/it.json index 55bb92650..824be31d4 100644 --- a/messages/it.json +++ b/messages/it.json @@ -1281,8 +1281,7 @@ "group": { "data": "Dati", "reminders": "Promemoria", - "lifecycle": "Ciclo di vita", - "danger": "Zona pericolosa" + "lifecycle": "Ciclo di vita" }, "dataPortability": { "import": { diff --git a/messages/pl.json b/messages/pl.json index 8f2ebfa8d..3d917ebd5 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -1281,8 +1281,7 @@ "group": { "data": "Dane", "reminders": "Przypomnienia", - "lifecycle": "Cykl życia", - "danger": "Strefa zagrożenia" + "lifecycle": "Cykl życia" }, "dataPortability": { "import": { diff --git a/src/components/medications/__tests__/advanced-settings-sheet.test.tsx b/src/components/medications/__tests__/advanced-settings-sheet.test.tsx index 1a83c95d6..60931d50b 100644 --- a/src/components/medications/__tests__/advanced-settings-sheet.test.tsx +++ b/src/components/medications/__tests__/advanced-settings-sheet.test.tsx @@ -1,14 +1,14 @@ /** * v1.7.0 — AdvancedSettingsSheet composition contract. * - * The sheet hosts four labelled groups — Data → Reminders → Lifecycle → - * Danger zone — composed from bare section bodies. `` + * The sheet hosts four blocks — Reminders → Lifecycle → Data → Danger + * zone — composed from bare section bodies. `` * wraps Radix portals that `renderToStaticMarkup` does not materialise, * so we mock it to a passthrough that renders children only when `open` * and echoes `contentWidth`. The bodies are mocked to ordered markers. * The test pins: - * - the four groups render in the documented order; - * - the sheet opens at the `4xl` width token; + * - the four blocks render in the documented order; + * - the sheet opens at the `2xl` width token; * - `onRequestPhaseSheet` threads through to the phases row; * - `onOpenImport` wires the import button (co-located with export); * - the export control sits beside the import control; @@ -107,27 +107,27 @@ function baseProps( } describe("AdvancedSettingsSheet (v1.7.0)", () => { - it("renders the four groups in Data → Reminders → Lifecycle → Danger order", () => { + it("renders the four blocks in Reminders → Lifecycle → Data → Danger order", () => { const html = renderToStaticMarkup( {} })} />, ); - const data = html.indexOf("advanced-group-data"); const reminders = html.indexOf("advanced-group-reminders"); const lifecycle = html.indexOf("advanced-group-lifecycle"); - const danger = html.indexOf("advanced-group-danger"); - expect(data).toBeGreaterThan(-1); - expect(reminders).toBeGreaterThan(data); + const data = html.indexOf("advanced-group-data"); + const danger = html.indexOf("mock-danger"); + expect(reminders).toBeGreaterThan(-1); expect(lifecycle).toBeGreaterThan(reminders); - expect(danger).toBeGreaterThan(lifecycle); + expect(data).toBeGreaterThan(lifecycle); + expect(danger).toBeGreaterThan(data); }); - it("opens at the 4xl width token", () => { + it("opens at the 2xl width token", () => { const html = renderToStaticMarkup( , ); - expect(html).toContain('data-content-width="4xl"'); + expect(html).toContain('data-content-width="2xl"'); }); it("threads onRequestPhaseSheet through to the phases row", () => { diff --git a/src/components/medications/advanced-settings-sheet.tsx b/src/components/medications/advanced-settings-sheet.tsx index d80ed5924..7d8974b20 100644 --- a/src/components/medications/advanced-settings-sheet.tsx +++ b/src/components/medications/advanced-settings-sheet.tsx @@ -3,24 +3,21 @@ /** * v1.7.0 — Advanced settings sheet. * v1.7.2 — widened to `4xl` and re-laid into a responsive two-column - * grid so a normal desktop viewport shows every group without forcing - * a long single-column scroll. + * grid. + * v1.8.6 — rebuilt as a single column. The two-column data|reminders + * grid read as overloaded; the sheet now narrows to `2xl` (~672px) and + * stacks four bordered section cards in most-used-first order: + * Reminders → Lifecycle → Data → Danger. One spacing rule throughout — + * `space-y-4` between cards, `divide-y` + `py-3` rows inside each card + * (the `` card owns the dividers). * - * Four labelled groups under one consistent visual system (R-medui §5): - * - * - Data: intake Import + medications CSV Export (co-located) + - * external-API endpoint / token. * - Reminders: notifications switch + reminder window (grace). * - Lifecycle: pause/resume + end course + phases. - * - Danger zone: purge intake history + delete medication. - * - * Layout: on `lg+` the first three groups flow into a two-column grid — - * the Data group (tallest, with the export toggle + token snippets) - * holds the left column; Reminders + Lifecycle stack down the right. - * The Danger zone always spans the full width at the bottom, set off by - * its own destructive-tinted card, so an irreversible action never - * shares a column with a routine toggle. On ` -
- {/* Top region: Data + Reminders + Lifecycle in a two-column grid - on lg+, single column below. `items-start` keeps each group - top-aligned so the shorter right column never stretches. */} -
- {/* DATA — import + export + external API. Tallest group → left - column on lg+ so the right column's two shorter groups - balance against it. */} - +
+ {/* REMINDERS — notifications + reminder window. Most-used group + first; each row is a padded `
` so the group card's + `divide-y` draws the hairline between them. */} + +
+ +
+
+ +
+
+ + {/* LIFECYCLE — pause/resume + end course + phases */} + +
+ onOpenChange(false)} + /> +
+ {isGlp1 && ( +
+ +
+ )} +
+ + {/* DATA — import + export + external API */} + +
- - - +
+
- - - {/* Right column: Reminders + Lifecycle stacked. */} -
- {/* REMINDERS — notifications + reminder window */} - - - - - - - - - {/* LIFECYCLE — pause/resume + end course + phases */} - - onOpenChange(false)} - /> - - {isGlp1 && ( - <> - - - - )} -
-
- - {/* DANGER ZONE — purge + delete. Full-width at the bottom, set - off by the destructive-tinted card inside the body so an - irreversible action never shares a column with a toggle. */} - - onOpenChange(false)} - /> + + {/* DANGER ZONE — purge + delete. Set off by the destructive- + tinted card so an irreversible action never sits next to a + routine toggle. The body supplies its own matched-pair card, + so it slots in without the neutral group frame. */} + onOpenChange(false)} + />
); diff --git a/src/components/medications/settings-group.tsx b/src/components/medications/settings-group.tsx index 769682184..f304b2d58 100644 --- a/src/components/medications/settings-group.tsx +++ b/src/components/medications/settings-group.tsx @@ -2,11 +2,13 @@ /** * v1.7.0 — advanced-settings group header. - * - * Lightweight presentational grouping for the redesigned - * ``: an uppercase micro-label over a hairline - * rule, then the group body. Reads as "one settings document, four - * parts" rather than three bordered section cards. + * v1.8.6 — rebuilt as a bordered section card. The sheet now stacks + * every group in a single column (Reminders → Lifecycle → Data → + * Danger), so each group needs its own frame to read as a distinct + * block rather than a hairline-separated run. The card owns one spacing + * rule: an uppercase micro-label header, then a `divide-y` body where + * each row carries `py-3`. Callers pass one `
` per row; the card + * supplies the dividers so no row interleaves its own ``. * * The label is a plain `

` (not a heading with an id) so it stays out * of the `aria-labelledby` graph — the sheet already owns the dialog @@ -17,26 +19,30 @@ import { type ReactNode } from "react"; +import { cn } from "@/lib/utils"; + export interface SettingsGroupProps { label: ReactNode; children: ReactNode; dataSlot?: string; + className?: string; } export function SettingsGroup({ label, children, dataSlot, + className, }: SettingsGroupProps) { return (

-

+

{label}

- {children} +
{children}
); }