From 379a3e675a34b0a4d22d0ee54c50f8710d3fec29 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sat, 24 Oct 2026 05:45:21 +0000 Subject: [PATCH] feat: Add keyboard focus states to Button and Switch components Co-authored-by: bobdivx <6737167+bobdivx@users.noreply.github.com> --- .Jules/palette.md | 4 ++++ apps/web/src/components/ui/Button.tsx | 2 +- apps/web/src/components/ui/Switch.tsx | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.Jules/palette.md b/.Jules/palette.md index 811f24d7d5..ee34abeab4 100644 --- a/.Jules/palette.md +++ b/.Jules/palette.md @@ -3,3 +3,7 @@ ## 2024-06-25 - Sidebar list navigation accessibility **Learning:** Found that list-style navigation items (like the `ThreadSidebar`) used conditional background colors to indicate active states (`bg-[var(--color-accent-soft)]`), but completely lacked programmatic indicators for screen readers. This pattern is likely present in other custom sidebar lists. **Action:** Always add `aria-current="true"` (or `"page"` if it's a full page navigation) alongside visual "active" states in list selections to ensure state is announced to screen readers. + +## 2024-10-24 - Added Focus Styles to Button component +**Learning:** The main `Button` component in `apps/web/src/components/ui/Button.tsx` lacked keyboard focus styles (`focus-visible:`). This makes keyboard navigation difficult as users cannot tell which button is currently focused. +**Action:** Always ensure that base UI interactive components like Buttons have `focus-visible` styles using the app's accent color (`focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-accent)]`). diff --git a/apps/web/src/components/ui/Button.tsx b/apps/web/src/components/ui/Button.tsx index e5841d65d1..dc43b5f9bd 100644 --- a/apps/web/src/components/ui/Button.tsx +++ b/apps/web/src/components/ui/Button.tsx @@ -65,7 +65,7 @@ export function Button({ title, }: Props) { const cls = cn( - 'inline-flex cursor-pointer items-center justify-center gap-2 font-medium tracking-tight transition-[filter,background-color,color,opacity,box-shadow] duration-200 ease-out disabled:pointer-events-none disabled:opacity-50', + 'inline-flex cursor-pointer items-center justify-center gap-2 font-medium tracking-tight transition-[filter,background-color,color,opacity,box-shadow] duration-200 ease-out disabled:pointer-events-none disabled:opacity-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-accent)]', variants[variant], sizes[size], className, diff --git a/apps/web/src/components/ui/Switch.tsx b/apps/web/src/components/ui/Switch.tsx index 3582f1f5f2..cc77262bbe 100644 --- a/apps/web/src/components/ui/Switch.tsx +++ b/apps/web/src/components/ui/Switch.tsx @@ -17,7 +17,7 @@ export function Switch({ checked, disabled, label, onToggle }: Props) { e.stopPropagation(); onToggle(); }} - class={`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-[var(--color-accent)] focus:ring-offset-2 focus:ring-offset-[var(--color-bg)] disabled:cursor-not-allowed disabled:opacity-50 ${ + class={`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-accent)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-bg)] disabled:cursor-not-allowed disabled:opacity-50 ${ checked ? 'bg-[var(--color-accent)]' : 'bg-[var(--color-line)]' }`} >