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.
This commit is contained in:
Marc-André Bombeck committed 2026-06-19 20:31:58 +02:00
1 parent 1f8420a6d0
commit a3b274171c
2 files changed
+28 -9

No files matched your search

@@ -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"
>
@@ -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 (
<div
className="flex h-6 items-end gap-0.5"
role="img"
aria-label={t("measurementReminders.trendStrip.label")}
>
{values.map((v, i) => {
<span className="sr-only">
{t("measurementReminders.trendStrip.summary", {
value: latest,
direction,
})}
</span>
{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 (
<span
key={i}
key={r.measuredAt}
data-index={i}
className="bg-muted-foreground/30 w-1.5 rounded-sm"
style={{ height: `${Math.round(pct * 100)}%` }}
aria-hidden="true"
/>
);
})}