From 435dca09974ce7ae41de6a92e7f9ac9c4eaf35b8 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 17 Feb 2026 10:00:57 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20Enhance=20accessibili?= =?UTF-8?q?ty=20and=20UX=20with=20ARIA=20labels=20and=20Tooltips?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added `TooltipProvider` to enable tooltips globally. - Implemented `Tooltip` and `aria-label` for icon-only buttons in `Header` and `History`. - Added Tooltips and `aria-label` to desktop `ChatPanel` buttons. - Fixed non-functional mobile search button by adding the missing portal container. - Ensured consistent accessibility text across main navigation and action buttons. Co-authored-by: ngoiyaeric <115367894+ngoiyaeric@users.noreply.github.com> --- .Jules/palette.md | 7 ++++ app/layout.tsx | 23 ++++++----- components/chat-panel.tsx | 64 ++++++++++++++++++----------- components/header-search-button.tsx | 2 + components/header.tsx | 55 +++++++++++++++++-------- components/history.tsx | 19 ++++++++- components/mobile-icons-bar.tsx | 14 +++---- 7 files changed, 125 insertions(+), 59 deletions(-) create mode 100644 .Jules/palette.md diff --git a/.Jules/palette.md b/.Jules/palette.md new file mode 100644 index 00000000..3153df6b --- /dev/null +++ b/.Jules/palette.md @@ -0,0 +1,7 @@ +## 2025-05-15 - [Consistency in Icon-Only Button Feedback] +**Learning:** Sighted users rely on visual tooltips (like the native `title` attribute or custom `Tooltip` components) to understand icon-only buttons. Removing these without providing a replacement degrades the UX. Accessibility improvements (`aria-label`) should complement, not replace, visual labels. +**Action:** Always ensure icon-only buttons have either a `title` attribute or are wrapped in a `Tooltip` component for visual feedback, in addition to `aria-label` for screen readers. + +## 2025-05-15 - [Portal-based Component Injection] +**Learning:** When using portals to inject buttons (e.g., `HeaderSearchButton`), the target container must exist in the DOM for the button to appear. If the target container is moved or replaced, the portal ID must be maintained or updated. +**Action:** When refactoring layouts that host portal targets, verify that the target IDs (like `mobile-header-search-portal`) are preserved or correctly re-implemented. diff --git a/app/layout.tsx b/app/layout.tsx index b9ea46ea..419ff31c 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -18,6 +18,7 @@ import { HistoryToggleProvider } from '@/components/history-toggle-context' import { HistorySidebar } from '@/components/history-sidebar' import { MapLoadingProvider } from '@/components/map-loading-context'; import ConditionalLottie from '@/components/conditional-lottie'; +import { TooltipProvider } from '@/components/ui/tooltip' import { MapProvider as MapContextProvider } from '@/components/map/map-context' const fontSans = FontSans({ @@ -107,16 +108,18 @@ export default function RootLayout({ disableTransitionOnChange themes={['light', 'dark', 'earth']} > - - - - - {children} - - - - - + + + + + + {children} + + + + + + diff --git a/components/chat-panel.tsx b/components/chat-panel.tsx index ca2fbc6f..e02c1b10 100644 --- a/components/chat-panel.tsx +++ b/components/chat-panel.tsx @@ -7,6 +7,11 @@ import { cn } from '@/lib/utils' import { UserMessage } from './user-message' import { Button } from './ui/button' import { ArrowRight, Plus, Paperclip, X, Sprout } from 'lucide-react' +import { + Tooltip, + TooltipContent, + TooltipTrigger +} from '@/components/ui/tooltip' import Textarea from 'react-textarea-autosize' import { nanoid } from '@/lib/utils' import { useSettingsStore } from '@/lib/store/settings' @@ -169,17 +174,22 @@ export const ChatPanel = forwardRef(({ messages, i 'fixed bottom-4 left-4 flex justify-start items-center pointer-events-none z-50' )} > - handleClear()} - data-testid="new-chat-button" - title="New Chat" - > - - + + + handleClear()} + data-testid="new-chat-button" + aria-label="New Chat" + > + + + + New Chat + ) } @@ -216,18 +226,24 @@ export const ChatPanel = forwardRef(({ messages, i accept="text/plain,image/png,image/jpeg,image/webp" /> {!isMobile && ( - - - + + + + + + + Attach file + )} (({ messages, i {selectedFile.name} - + diff --git a/components/header-search-button.tsx b/components/header-search-button.tsx index 04896457..e34bc26d 100644 --- a/components/header-search-button.tsx +++ b/components/header-search-button.tsx @@ -153,6 +153,8 @@ export function HeaderSearchButton() { size="icon" onClick={handleResolutionSearch} disabled={isAnalyzing || !map || !actions} + data-testid="resolution-search" + aria-label="Analyze current map view" title="Analyze current map view" > {isAnalyzing ? ( diff --git a/components/header.tsx b/components/header.tsx index fd80bc44..d38b8e25 100644 --- a/components/header.tsx +++ b/components/header.tsx @@ -20,6 +20,11 @@ import { useUsageToggle } from './usage-toggle-context' import { useProfileToggle } from './profile-toggle-context' import { useHistoryToggle } from './history-toggle-context' import { useState, useEffect } from 'react' +import { + Tooltip, + TooltipContent, + TooltipTrigger +} from '@/components/ui/tooltip' export const Header = () => { const { toggleCalendar } = useCalendarToggle() @@ -52,15 +57,21 @@ export const Header = () => { - - - + + + + + Toggle history + + + Toggle history + QCX @@ -71,15 +82,27 @@ export const Header = () => { - - - + + + + + Open Calendar + + + Open Calendar + - - - + + + + + Usage & Credits + + + Usage & Credits + @@ -89,7 +112,7 @@ export const Header = () => { {/* Mobile menu buttons */} - + diff --git a/components/history.tsx b/components/history.tsx index 5bae1a39..03910a90 100644 --- a/components/history.tsx +++ b/components/history.tsx @@ -3,6 +3,11 @@ import { Button } from '@/components/ui/button' import { ChevronLeft, Menu } from 'lucide-react' import { cn } from '@/lib/utils' import { useHistoryToggle } from './history-toggle-context' +import { + Tooltip, + TooltipContent, + TooltipTrigger +} from '@/components/ui/tooltip' type HistoryProps = { location: 'sidebar' | 'header' @@ -10,7 +15,7 @@ type HistoryProps = { export function History({ location }: HistoryProps) { const { toggleHistory } = useHistoryToggle() - return ( + const button = ( {location === 'header' ? : } ) + + if (location === 'header') { + return ( + + {button} + Toggle history + + ) + } + + return button } diff --git a/components/mobile-icons-bar.tsx b/components/mobile-icons-bar.tsx index d0db2cfa..ebe4651d 100644 --- a/components/mobile-icons-bar.tsx +++ b/components/mobile-icons-bar.tsx @@ -37,26 +37,24 @@ export const MobileIconsBar: React.FC = ({ onAttachmentClic return ( - + - + - - - + - + - + - +