mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 04:32:42 +00:00
fix(a11y): 44px tap targets + focus-visible on rec-feedback, chart range tabs, export switch (H1/H2/H6/H7)
WCAG 2.5.5 minimum hit-area is 44×44 CSS px and the Wave-C polish set that as the project floor. Several v1.4.16 surfaces missed it: - Recommendation thumbs (h-7 = 28 px) — `<RecommendationFeedback>` up + down both bumped to `min-h-11 min-w-11` with focus-visible ring. - Recommendation chevron expand toggle (~24 px, no focus state) — `<RecommendationCard>` rec-expand-toggle bumped to `min-h-11 min-w-11` with focus-visible ring. - Chart range tabs (7d/30d/90d/All) — `min-h-9 px-2.5` ≈ 36×28 px on Pixel 5; bumped to `min-h-11 px-3` across HealthChart, MoodChart, MedicationComplianceChart, ComplianceCharts, ComplianceLineChart. - Medication CSV "include intake history" raw `<input type="checkbox">` (16×16, system-blue on iOS Safari) — replaced with shadcn `<Switch>` inside a `min-h-11` label so the row is properly tappable and visually consistent with every other settings toggle. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
6e74d38213
commit
c3451a4c06
8 files changed
+18
-15
No files matched your search
@@ -103,7 +103,7 @@ export function ComplianceCharts({ medications }: ComplianceChartsProps) {
|
||||
type="button"
|
||||
variant={rangePoints === 30 ? "default" : "ghost"}
|
||||
size="sm"
|
||||
className="min-h-9 px-2.5 text-xs"
|
||||
className="min-h-11 px-3 text-xs"
|
||||
onClick={() => setRangePoints(30)}
|
||||
title={t("charts.points30Title")}
|
||||
>
|
||||
@@ -113,7 +113,7 @@ export function ComplianceCharts({ medications }: ComplianceChartsProps) {
|
||||
type="button"
|
||||
variant={rangePoints === 90 ? "default" : "ghost"}
|
||||
size="sm"
|
||||
className="min-h-9 px-2.5 text-xs"
|
||||
className="min-h-11 px-3 text-xs"
|
||||
onClick={() => setRangePoints(90)}
|
||||
title={t("charts.points90Title")}
|
||||
>
|
||||
@@ -123,7 +123,7 @@ export function ComplianceCharts({ medications }: ComplianceChartsProps) {
|
||||
type="button"
|
||||
variant={rangePoints === 0 ? "default" : "ghost"}
|
||||
size="sm"
|
||||
className="min-h-9 px-2.5 text-xs"
|
||||
className="min-h-11 px-3 text-xs"
|
||||
onClick={() => setRangePoints(0)}
|
||||
title={t("charts.pointsAllTitle")}
|
||||
>
|
||||
|
||||
@@ -73,7 +73,7 @@ export function ComplianceLineChart({
|
||||
key={r.label}
|
||||
variant={activeRangePoints === r.points ? "default" : "ghost"}
|
||||
size="sm"
|
||||
className="min-h-9 px-2.5 text-xs"
|
||||
className="min-h-11 px-3 text-xs"
|
||||
onClick={() => setActiveRangePoints(r.points)}
|
||||
title={r.title}
|
||||
>
|
||||
|
||||
@@ -879,7 +879,7 @@ export function HealthChart({
|
||||
key={r.labelKey}
|
||||
variant={rangePoints === r.points ? "default" : "ghost"}
|
||||
size="sm"
|
||||
className="min-h-9 px-2.5 text-xs"
|
||||
className="min-h-11 px-3 text-xs"
|
||||
onClick={() => setRangePoints(r.points)}
|
||||
title={t(r.titleKey)}
|
||||
data-slot="chart-range-tab"
|
||||
|
||||
@@ -257,7 +257,7 @@ export function MedicationComplianceChart({
|
||||
key={r}
|
||||
variant={days === r ? "default" : "ghost"}
|
||||
size="sm"
|
||||
className="min-h-9 px-2.5 text-xs"
|
||||
className="min-h-11 px-3 text-xs"
|
||||
onClick={() => setDays(r)}
|
||||
>
|
||||
{r}T
|
||||
|
||||
@@ -550,7 +550,7 @@ export function MoodChart({
|
||||
key={r.labelKey}
|
||||
variant={rangePoints === r.points ? "default" : "ghost"}
|
||||
size="sm"
|
||||
className="min-h-9 px-2.5 text-xs"
|
||||
className="min-h-11 px-3 text-xs"
|
||||
onClick={() => setRangePoints(r.points)}
|
||||
title={t(r.titleKey)}
|
||||
data-slot="chart-range-tab"
|
||||
|
||||
@@ -369,7 +369,7 @@ export function RecommendationCard({
|
||||
type="button"
|
||||
onClick={() => setExpanded((v) => !v)}
|
||||
aria-expanded={expanded}
|
||||
className="text-muted-foreground hover:text-foreground rounded-md p-1 transition-colors"
|
||||
className="text-muted-foreground hover:text-foreground focus-visible:ring-ring/50 inline-flex min-h-11 min-w-11 items-center justify-center rounded-md transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none"
|
||||
title={
|
||||
expanded
|
||||
? t("insights.recommendation.rationaleCollapse")
|
||||
|
||||
@@ -265,7 +265,7 @@ export function RecommendationFeedback({
|
||||
title={t("insights.recommendation.feedbackHelpful")}
|
||||
disabled={disabled}
|
||||
onClick={() => submit(true)}
|
||||
className="text-muted-foreground hover:text-dracula-green disabled:hover:text-muted-foreground inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors disabled:opacity-60"
|
||||
className="text-muted-foreground hover:text-dracula-green disabled:hover:text-muted-foreground focus-visible:ring-ring/50 inline-flex min-h-11 min-w-11 items-center justify-center rounded-md transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:opacity-60"
|
||||
>
|
||||
{submittingUp ? (
|
||||
<Loader2 className="h-3.5 w-3.5 animate-spin" aria-hidden="true" />
|
||||
@@ -280,7 +280,7 @@ export function RecommendationFeedback({
|
||||
title={t("insights.recommendation.feedbackNotHelpful")}
|
||||
disabled={disabled}
|
||||
onClick={() => submit(false)}
|
||||
className="text-muted-foreground hover:text-dracula-orange disabled:hover:text-muted-foreground inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors disabled:opacity-60"
|
||||
className="text-muted-foreground hover:text-dracula-orange disabled:hover:text-muted-foreground focus-visible:ring-ring/50 inline-flex min-h-11 min-w-11 items-center justify-center rounded-md transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:opacity-60"
|
||||
>
|
||||
{submittingDown ? (
|
||||
<Loader2 className="h-3.5 w-3.5 animate-spin" aria-hidden="true" />
|
||||
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import {
|
||||
DoctorReportDialog,
|
||||
type DoctorReportSubmitPayload,
|
||||
@@ -453,13 +454,15 @@ function MedicationsCsvCard() {
|
||||
setSince={setSince}
|
||||
setUntil={setUntil}
|
||||
/>
|
||||
<label className="flex cursor-pointer items-center gap-2 text-xs">
|
||||
<input
|
||||
<label
|
||||
htmlFor="export-medications-include-intake"
|
||||
className="flex min-h-11 cursor-pointer items-center gap-3 text-xs"
|
||||
>
|
||||
<Switch
|
||||
id="export-medications-include-intake"
|
||||
data-testid="export-medications-include-intake"
|
||||
type="checkbox"
|
||||
checked={includeIntake}
|
||||
onChange={(e) => setIncludeIntake(e.target.checked)}
|
||||
className="border-border h-4 w-4 cursor-pointer rounded border"
|
||||
onCheckedChange={setIncludeIntake}
|
||||
/>
|
||||
<span className="text-muted-foreground">
|
||||
{t("settings.sections.export.cards.medicationsCsv.includeIntake")}
|
||||
|
||||
Reference in new issue
Block a user