From b33008ddc9d2dbe688ff1b3c39bf68fa34590226 Mon Sep 17 00:00:00 2001 From: Mike Fortman Date: Wed, 10 Jun 2026 10:27:09 -0500 Subject: [PATCH] a11y fixes --- frontend/app/globals.css | 11 +++++++++++ .../app/onboarding/_components/model-selector.tsx | 5 ++++- frontend/components/ui/multi-select.tsx | 4 +++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/frontend/app/globals.css b/frontend/app/globals.css index 77a41a2ad..942dd1c6c 100644 --- a/frontend/app/globals.css +++ b/frontend/app/globals.css @@ -870,3 +870,14 @@ } } } + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} diff --git a/frontend/app/onboarding/_components/model-selector.tsx b/frontend/app/onboarding/_components/model-selector.tsx index ad6df7374..65937f811 100644 --- a/frontend/app/onboarding/_components/model-selector.tsx +++ b/frontend/app/onboarding/_components/model-selector.tsx @@ -1,7 +1,7 @@ "use client"; import { CheckIcon, ChevronsUpDownIcon } from "lucide-react"; -import { useEffect, useState } from "react"; +import { useEffect, useId, useState } from "react"; import { Badge } from "@/components/ui/badge"; import { Button, type ButtonProps } from "@/components/ui/button"; import { @@ -65,6 +65,7 @@ export function ModelSelector({ }: ModelSelectorProps) { const [open, setOpen] = useState(defaultOpen); const [searchValue, setSearchValue] = useState(""); + const listboxId = useId(); // Flatten grouped options or use regular options const allOptions = @@ -103,6 +104,7 @@ export function ModelSelector({ role="combobox" disabled={disabled || allOptions.length === 0} aria-expanded={open} + aria-controls={listboxId} className={cn( "w-full gap-2 justify-between font-normal text-sm", hasError && "!border-destructive", @@ -143,6 +145,7 @@ export function ModelSelector({ onValueChange={setSearchValue} /> e.stopPropagation()} > diff --git a/frontend/components/ui/multi-select.tsx b/frontend/components/ui/multi-select.tsx index e5e1a8ace..129fbcdbb 100644 --- a/frontend/components/ui/multi-select.tsx +++ b/frontend/components/ui/multi-select.tsx @@ -49,6 +49,7 @@ export function MultiSelect({ }: MultiSelectProps) { const [open, setOpen] = React.useState(false); const [searchValue, setSearchValue] = React.useState(""); + const listboxId = React.useId(); // Normalize value to empty array if undefined/null to prevent crashes const safeValue = value ?? []; @@ -109,6 +110,7 @@ export function MultiSelect({ variant="outline" role="combobox" aria-expanded={open} + aria-controls={listboxId} className={cn("w-full justify-between h-8 py-0 text-left", className)} > {getDisplayText()} @@ -123,7 +125,7 @@ export function MultiSelect({ onValueChange={setSearchValue} /> No items found. - + {showAllOption && (