From a3b274171ceea7d07e865442a58fbe3f08202c8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Fri, 19 Jun 2026 20:31:58 +0200 Subject: [PATCH] fix(a11y): announce coach history state and Vorsorge trend Add aria-expanded to the coach drawer's history-collapse control so its expanded state is exposed, matching the expand toggle. Give the Vorsorge trend strip an sr-only summary of the latest value and seven-day direction, and key the bars on measuredAt rather than the array index. --- .../coach-panel/coach-drawer-body.tsx | 1 + .../vorsorge-trend-strip.tsx | 36 ++++++++++++++----- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/components/insights/coach-panel/coach-drawer-body.tsx b/src/components/insights/coach-panel/coach-drawer-body.tsx index 6842439fe..6076a2b4b 100644 --- a/src/components/insights/coach-panel/coach-drawer-body.tsx +++ b/src/components/insights/coach-panel/coach-drawer-body.tsx @@ -126,6 +126,7 @@ export function CoachDrawerBody({ onClick={onToggleHistory} data-slot="coach-history-collapse" aria-label={t("insights.coach.hideConversations")} + aria-expanded={historyOpen} title={t("insights.coach.hideConversations")} className="text-muted-foreground hover:text-foreground -mr-1 size-9 shrink-0" > diff --git a/src/components/measurement-reminders/vorsorge-trend-strip.tsx b/src/components/measurement-reminders/vorsorge-trend-strip.tsx index 5d476c702..8250e273d 100644 --- a/src/components/measurement-reminders/vorsorge-trend-strip.tsx +++ b/src/components/measurement-reminders/vorsorge-trend-strip.tsx @@ -43,10 +43,7 @@ function useRecentValues(measurementType: string | null, enabled: boolean) { const res = await apiGet<{ measurements: RecentMeasurement[] }>( `/api/measurements?${params}`, ); - return res.measurements - .slice() - .reverse() - .map((m) => m.value); + return res.measurements.slice().reverse(); }, enabled: enabled && measurementType != null, }); @@ -64,27 +61,48 @@ export function VorsorgeTrendStrip({ // Nothing to show for a free-text reminder or a too-thin window. if (measurementType == null) return null; - const values = data ?? []; - if (values.length < 2) return null; + const readings = data ?? []; + if (readings.length < 2) return null; + const values = readings.map((r) => r.value); const min = Math.min(...values); const max = Math.max(...values); const span = max - min || 1; + // 7-day direction from first → last reading in the window. Latest value + // and direction feed the sr-only summary so a screen reader gets the + // trend, not just the generic "Last 7 days" label. + const latest = values[values.length - 1]; + const delta = latest - values[0]; + const direction = + delta > 0 + ? t("measurementReminders.trendStrip.rising") + : delta < 0 + ? t("measurementReminders.trendStrip.falling") + : t("measurementReminders.trendStrip.steady"); + return (
- {values.map((v, i) => { + + {t("measurementReminders.trendStrip.summary", { + value: latest, + direction, + })} + + {readings.map((r, i) => { // Floor at ~18% so a flat series still reads as bars, not a line. - const pct = 0.18 + ((v - min) / span) * 0.82; + const pct = 0.18 + ((r.value - min) / span) * 0.82; return (