fix(a11y): repair non-sequential heading order on three surfaces

Lighthouse v1.4.33 a11y pass flagged "heading elements not in
sequentially descending order" (score 91/94). Three offenders:

- `<TherapyTimeline>` (insights/medikamente sub-page): sr-only
  drug-name heading was an h4, but the parent SubPageShell ships
  the only h1 and CardTitle is a <div>. Promoted to h2 so the
  outline stays h1 -> h2 without skipping levels.
- `<FeedbackInboxDetailSheet>`: metadata + screenshot section
  headings rendered as h4 inside a ResponsiveSheet whose dialog
  title is h2 (Radix default). Demoted to h3 to stay sequential
  beneath the sheet title.
- `<RemindersSection>`: results heading was h4 inside the admin
  SectionFrame's h1. Promoted to h2.

Coach panel headings (IW5 surface) audited but not changed.
This commit is contained in:
Marc-André Bombeck committed 2026-05-16 17:57:28 +02:00
1 parent 972c8a56dd
commit 2620064ef1
3 files changed
+17 -8

No files matched your search

@@ -434,9 +434,11 @@ function FeedbackDetailDialog({
{(url || locale || userAgent || appVersion) && (
<div>
<h4 className="text-muted-foreground text-xs font-semibold tracking-wider uppercase">
{/* v1.4.33 IW9 — h4 -> h3 so the sheet outline stays
sequential beneath the ResponsiveSheet's h2 title. */}
<h3 className="text-muted-foreground text-xs font-semibold tracking-wider uppercase">
{t("admin.feedback.metadataHeading")}
</h4>
</h3>
<dl className="mt-2 grid grid-cols-[max-content_1fr] gap-x-3 gap-y-1 text-xs">
{url && (
<>
@@ -476,9 +478,9 @@ function FeedbackDetailDialog({
{item.screenshotBase64 && (
<div>
<h4 className="text-muted-foreground mb-2 text-xs font-semibold tracking-wider uppercase">
<h3 className="text-muted-foreground mb-2 text-xs font-semibold tracking-wider uppercase">
{t("admin.feedback.screenshotHeading")}
</h4>
</h3>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={item.screenshotBase64}
+4 -2
View File
@@ -252,9 +252,11 @@ export function RemindersSection() {
{reminderCheck.data?.medications &&
reminderCheck.data.medications.length > 0 && (
<div className="mt-4 space-y-2">
<h4 className="text-sm font-medium">
{/* v1.4.33 IW9 — h4 -> h2 so the page outline stays
sequential (parent admin SectionFrame ships <h1>). */}
<h2 className="text-sm font-medium">
{t("admin.reminderCheckResults")}
</h4>
</h2>
<div className="space-y-2">
{reminderCheck.data.medications.map((med, i) => (
<div key={i} className="bg-muted/50 space-y-1.5 rounded-lg p-3">
+7 -2
View File
@@ -111,9 +111,14 @@ export function TherapyTimeline({ limit }: TherapyTimelineProps) {
{/* v1.4.27 B7 / L4 — sr-only drug-name heading per
entry so screen-reader users can jump between
medication blocks; the visible row keeps the
inline <strong> rendering. */}
inline <strong> rendering.
v1.4.33 IW9 — promoted from h4 -> h2 so the page
outline stays sequential. The parent SubPageShell
ships an <h1>; CardTitle is a <div>, so the timeline
is the only heading-bearing surface here and h2
nests directly under h1 without skipping levels. */}
{entry.medicationName && (
<h4 className="sr-only">{entry.medicationName}</h4>
<h2 className="sr-only">{entry.medicationName}</h2>
)}
<p className="text-muted-foreground text-xs">
{fmt.dateWithWeekday(new Date(entry.date))}