chore(medications): tighten titration ladder, cadence grid, and phase-config layout on mobile

v1.4.27 MB7 — four medications-surface polish items in one commit:

- CF-48: the titration ladder keeps its vertical (`flex-col`) layout
  until `md:` instead of breaking horizontal at `sm:`. The German
  dose + typical-weeks labels wrapped to 3 lines per step on Pixel 5,
  which read denser than the vertical layout below.
- CF-49: the 30-day cadence grid tightens from `gap-1` to `gap-0.5`
  on `<sm` so more cells fit per row without sacrificing the 44 px
  tap target per cell. The original 4 px gap returns at `sm:`.
- CF-50: the PhaseConfig dialog rows stack on `<sm` so the input +
  mode toggle + suffix caption fit inside the 280-300 px dialog
  inner width on Galaxy Fold. The suffix wraps below at `<sm` via
  `basis-full`; `sm:` keeps the single-line layout.
- CF-66: the DrugLevelChart wrapper drops the `md:p-6` lift so its
  padding matches the surrounding trend cards (`p-4` everywhere).
This commit is contained in:
Marc-André Bombeck committed 2026-05-15 19:16:45 +02:00
1 parent 7bfd5beeb2
commit e1451f840f
4 files changed
+37 -6

No files matched your search

@@ -229,9 +229,14 @@ export function DrugLevelChart({
// and skips the outer `<section>` wrapper so the user doesn't see a
// card painted inside a card. The disclaimer also collapses to a
// single muted line to keep the tile's vertical footprint tight.
// v1.4.27 MB7 / CF-66 — drop the `md:p-6` lift so the wrapper
// stays at the `p-4` density across viewports. The 6 unit padding
// on `md+` made the GLP-1 tile feel oversized relative to the
// neighbouring trend cards, which all use `p-4`. Compact mode
// retains the `space-y-2` layout without an outer card wrapper.
const wrapperClass = compact
? "space-y-2"
: "bg-card border-border rounded-xl border p-4 md:p-6";
: "bg-card border-border rounded-xl border p-4";
const wrapperProps = {
"aria-labelledby": "drug-level-chart-title",
className: wrapperClass,
@@ -192,7 +192,14 @@ export function SchedulingSection({
) : (
<>
<div
className="flex flex-wrap gap-1"
// v1.4.27 MB7 / CF-49 — tighten the gap from
// `gap-1` (4 px) to `gap-0.5` (2 px) on `<sm` so
// the 30-day cadence grid fits in fewer rows on
// Pixel 5 (375 px) without sacrificing the 44 px
// tap target per cell. At `sm:` and above the
// original 4 px gap returns; the wider container
// there already absorbs the timeline in 1-2 rows.
className="flex flex-wrap gap-0.5 sm:gap-1"
role="img"
aria-label={t(
"medications.scheduling.cadenceViz.ariaTimeline",
@@ -138,7 +138,15 @@ export function TitrationSection({ medicationId }: TitrationSectionProps) {
{hasLadder ? (
<ol
className="flex flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-stretch"
// v1.4.27 MB7 / CF-48 — keep the vertical (`flex-col`)
// layout until `md:` instead of breaking to horizontal
// at `sm:`. On Pixel 5 (375 px) the horizontal ladder
// had 4-5 visible steps but each step's "Standard 0.5
// mg" + "typical 4 weeks" label combo wrapped to 3
// lines per step, which read as a denser block than
// the vertical layout below. From `md:` upwards the
// wider container can absorb the horizontal stride.
className="flex flex-col gap-2 md:flex-row md:flex-wrap md:items-stretch"
aria-label={t("medications.titration.drugLadderHeader")}
>
{data.ladder.map((step) => {
@@ -149,7 +157,7 @@ export function TitrationSection({ medicationId }: TitrationSectionProps) {
<li
key={step.stepIndex}
className={[
"border-border/70 flex flex-1 flex-col rounded-md border px-2.5 py-2 sm:min-w-[7rem]",
"border-border/70 flex flex-1 flex-col rounded-md border px-2.5 py-2 md:min-w-[7rem]",
isCurrent
? "border-primary ring-primary/40 ring-2"
: "",
@@ -182,7 +182,18 @@ export function PhaseConfigDialog({
const mode = form[modeKey] as "MINUTES" | "PERCENT";
return (
<div key={key} className="flex items-center gap-2">
// v1.4.27 MB7 / CF-50 — stack the row on `<sm` so
// the input + mode toggle + suffix caption don't
// overflow the 280-300 px dialog inner width on
// Galaxy Fold. The dot + phase label stay on the
// first line; the input / toggle / suffix wrap
// beneath. At `sm:` the original single-line layout
// returns because the wider dialog can absorb the
// five horizontal slots.
<div
key={key}
className="flex flex-wrap items-center gap-2 sm:flex-nowrap"
>
<div
className={`h-3 w-3 rounded-full ${dotClass} shrink-0`}
aria-hidden="true"
@@ -211,7 +222,7 @@ export function PhaseConfigDialog({
? t("medications.phaseMinutes")
: t("medications.phasePercent")}
</Button>
<span className="text-muted-foreground shrink-0 text-xs">
<span className="text-muted-foreground basis-full text-xs sm:basis-auto sm:shrink-0">
{direction === "before"
? t("medications.phaseBeforeEnd")
: t("medications.phaseAfterEnd")}