mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 14:40:52 +00:00
fix(a11y): name every control by the text it shows
axe 4.14 checks WCAG 2.5.3 (label in name), and the app frame failed it on every page: the account link, the user menu and the day strip carried an aria-label that left out their visible text. The same class sat in the coverage meter, the score ring, medication links, instrument cards, filter pills with a value set, cycle calendar days (named by an ISO key), admin user and login rows, a few sort and action buttons, and the French, Spanish, Italian and Polish weekday chips, whose abbreviations were not part of the day names. Controls with visible text are now named by it, with any extra purpose added as screen-reader text; the select pill and calendar days spell out a name that contains what they show. The day and conversation strips keep their action as the tooltip.
This commit is contained in:
1 parent
038f8b10cd
commit
562ff8a277
36 files changed
+134
-97
No files matched your search
@@ -288,7 +288,9 @@ describe("the axis override reaches the markup", () => {
|
||||
|
||||
expect(html).toContain("Covers the three areas the score needs");
|
||||
expect(html).not.toContain(">3/3<");
|
||||
expect(html).toMatch(/aria-label="Covers the three areas the score needs/);
|
||||
expect(html).toMatch(
|
||||
/class="sr-only">Covers the three areas the score needs/,
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps the fraction for every caller that does not override it", () => {
|
||||
|
||||
@@ -189,10 +189,12 @@ export function CorrelationCard({ result }: CorrelationCardProps) {
|
||||
data-slot="correlation-card-cta"
|
||||
className="gap-1.5"
|
||||
title={t("insights.correlationRow.experimentTooltip")}
|
||||
aria-label={t("insights.correlationRow.experimentTooltip")}
|
||||
>
|
||||
<Sparkles className="h-3.5 w-3.5" aria-hidden="true" />
|
||||
<span>{t("insights.correlationRow.experimentCta")}</span>
|
||||
<span className="sr-only">
|
||||
, {t("insights.correlationRow.experimentTooltip")}
|
||||
</span>
|
||||
</Button>
|
||||
{/* v1.21.0 — the live Coach hand-off sits beside the
|
||||
roadmap CTA: it scopes to both sources in the pair. */}
|
||||
|
||||
@@ -79,7 +79,10 @@ describe("<CoverageMeter>", () => {
|
||||
|
||||
it("carries an accessible summary label", () => {
|
||||
const html = render(<CoverageMeter coverage={PARTIAL} confidence={LOW} />);
|
||||
expect(html).toContain("aria-label");
|
||||
// The visible ratio plus the sentence, never an aria-label that drops
|
||||
// the ratio (WCAG 2.5.3).
|
||||
expect(html).not.toContain("aria-label");
|
||||
expect(html).toContain('class="sr-only">3 of 5 inputs (35%)</span>');
|
||||
expect(html).toContain("3");
|
||||
expect(html).toContain("5");
|
||||
});
|
||||
|
||||
@@ -138,7 +138,6 @@ export function CoverageMeter({
|
||||
data-present={present}
|
||||
data-required={required}
|
||||
data-percent={percent}
|
||||
aria-label={summaryLabel}
|
||||
aria-describedby={tooltipId}
|
||||
className={cn(
|
||||
// 44px hit target via padding while the dots stay optically
|
||||
@@ -183,6 +182,9 @@ export function CoverageMeter({
|
||||
required,
|
||||
})}
|
||||
</span>
|
||||
{/* The visible ratio names the button; the sentence adds what it
|
||||
counts (WCAG 2.5.3: the name contains what is shown). */}
|
||||
<span className="sr-only">{summaryLabel}</span>
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
|
||||
Reference in new issue
Block a user