From a90c73526187eb46f7b37e485512f35135b7be2a Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 10:22:41 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20Add=20accessibility?= =?UTF-8?q?=20attributes=20to=20WikiCollapsible?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added `useId` to generate dynamic aria-controls mappings. Added `aria-expanded` and `focus-visible` styles to the toggle button. Documented critical UX learning in `.jules/palette.md`. Co-authored-by: aicoder2009 <127642633+aicoder2009@users.noreply.github.com> --- .jules/palette.md | 3 +++ src/components/wiki/wiki-collapsible.tsx | 9 ++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 .jules/palette.md diff --git a/.jules/palette.md b/.jules/palette.md new file mode 100644 index 0000000..36a8913 --- /dev/null +++ b/.jules/palette.md @@ -0,0 +1,3 @@ +## 2025-04-30 - Accessible Interactive Widgets with useId +**Learning:** In the `opencitation` Next.js codebase, when building or enhancing accessible React interactive widgets like collapsibles, tabs, or dropdowns, it's critical to use React's `useId` hook to generate unique IDs for ARIA mappings (e.g., `aria-controls` to the content container). This prevents ID collisions across multiple component instances on the same page, ensuring correct screen reader context. +**Action:** Always check `aria-controls` and `id` mappings for dynamic components and standardize on using `useId()` when creating or improving interactive UI patterns in this project. diff --git a/src/components/wiki/wiki-collapsible.tsx b/src/components/wiki/wiki-collapsible.tsx index 5284dd8..72df885 100644 --- a/src/components/wiki/wiki-collapsible.tsx +++ b/src/components/wiki/wiki-collapsible.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState } from "react"; +import { useState, useId } from "react"; interface WikiCollapsibleProps { title: string; @@ -14,6 +14,7 @@ export function WikiCollapsible({ defaultOpen = true, }: WikiCollapsibleProps) { const [isOpen, setIsOpen] = useState(defaultOpen); + const contentId = useId(); return (