fix(a11y): names that carry what they show; the unused-key check stops covering whole files

- The palette launcher's name replaced its visible "Jump to…" (and the key cap's its "Ctrl K"):
  a voice-control "click Jump to" matched nothing (WCAG 2.5.3). Each name contains its text now.
- SegmentedToggle's `title` was only a tooltip on a non-focusable box — the live search's "how
  many per batch" hint reached no keyboard or screen-reader user. It is the group's accessible
  description, standalone and captioned alike.
- The unused-key contract let a template like `card.${status}` cover its whole namespace, which hid
  five dead keys (deleted). Dynamic keys are matched by shape (`editor.*.hint`); a bare namespace
  shape covers nothing, and the audit/quota namespaces are now held both ways by backendIds.
- CLAUDE.md's "FE control" row matches the lint rule it cites; each no-restricted-syntax entry has
  its reason directly above it.
This commit is contained in:
2026-09-19 19:19:43 +02:00
parent fa4f823fc8
commit cf0c55ba80
13 changed files with 128 additions and 39 deletions
+3 -5
View File
@@ -446,14 +446,12 @@ export default function Feed({
{zeroQuota ? t("feed.yt.freeNote") : t("feed.yt.quotaNote")}
</span>
{/* Four fixed counts: the house's segmented control, not a native <select> (owner's
pick, 2026-09-19). The caption is the group's name; the hint rides on the row. */}
<div
className="ml-auto flex items-center gap-1.5 text-xs text-muted shrink-0"
title={t("feed.yt.showHint")}
>
pick, 2026-09-19). The caption is the group's name, the hint its description. */}
<div className="ml-auto flex items-center gap-1.5 text-xs text-muted shrink-0">
<span aria-hidden="true">{t("feed.yt.show")}</span>
<SegmentedToggle
ariaLabel={t("feed.yt.show")}
title={t("feed.yt.showHint")}
value={String(ytCount)}
onChange={(v) => setYtCount(Number(v))}
options={YT_COUNTS.map((n) => ({ value: String(n), label: String(n) }))}