fix(a11y): distinguish errors from empty states and close naming gaps

Add isError branches with a retry affordance to the mood, illness, and
vorsorge lists so a failed read no longer renders as "no entries yet"
and invites duplicate re-entry, matching the labs and cycle pattern.

Make the admin backups table reachable on a phone with a card fallback,
name the admin language and timezone selects and the AI raw-data switch
for screen readers, and replace the touch-unreachable title= help on the
glucose clinical panels with a tap-capable info popover.

Route the password-strength label through the AA-tuned semantic tokens,
underline the register login link so it is not distinguished by colour
alone, give the labs load error alert semantics, and explain why the
target editor Save button is disabled with aria-invalid and a live
alert.
This commit is contained in:
Marc-André Bombeck committed 2026-06-28 02:53:14 +02:00
1 parent b02e3e4072
commit c38271bc44
13 files changed
+350 -88

No files matched your search

@@ -3,6 +3,7 @@
import { useId, useState } from "react";
import { ChevronDown } from "lucide-react";
import { InfoHint } from "@/components/ui/info-hint";
import { useTranslations } from "@/lib/i18n/context";
import { cn } from "@/lib/utils";
import type { GlucoseClinicalMetrics } from "@/lib/analytics/glucose-metrics";
@@ -146,8 +147,9 @@ function AdvancedStat({
}) {
return (
<div className="space-y-0.5">
<dt className="text-muted-foreground text-xs" title={help}>
<dt className="text-muted-foreground flex items-center gap-1 text-xs">
{label}
<InfoHint label={help} />
</dt>
<dd className="text-foreground text-base font-semibold tabular-nums">
{value}
@@ -5,6 +5,7 @@ import { Activity, Droplet, FlaskConical, TrendingUp } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { InfoHint } from "@/components/ui/info-hint";
import { LearningGate } from "@/components/ui/learning-gate";
import { LearnMoreLink } from "@/components/ui/learn-more-link";
import { Skeleton } from "@/components/ui/skeleton";
@@ -195,11 +196,9 @@ export function GlucoseClinicalPanel() {
) : null}
{cv ? (
<div className="space-y-0.5" data-slot="glucose-cv">
<span
className="text-muted-foreground flex items-center gap-1 text-xs"
title={t("insights.bloodGlucose.clinical.cv.help")}
>
<span className="text-muted-foreground flex items-center gap-1 text-xs">
{t("insights.bloodGlucose.clinical.cv.label")}
<InfoHint label={t("insights.bloodGlucose.clinical.cv.help")} />
</span>
<div className="flex items-center gap-1.5">
<span className="text-foreground text-lg font-semibold tabular-nums">
@@ -283,12 +282,10 @@ function Metric({
}) {
return (
<div className="space-y-0.5">
<span
className="text-muted-foreground flex items-center gap-1 text-xs"
title={help}
>
<span className="text-muted-foreground flex items-center gap-1 text-xs">
{icon}
{label}
{help ? <InfoHint label={help} /> : null}
</span>
<span className="text-foreground flex items-baseline gap-1">
<span className="text-lg font-semibold tabular-nums">{value}</span>