🔇 fix: Hide Button Icons from Screen Readers (#10776)
Some checks failed
Docker Dev Branch Images Build / build (Dockerfile, lc-dev, node) (push) Has been cancelled
Docker Dev Branch Images Build / build (Dockerfile.multi, lc-dev-api, api-build) (push) Has been cancelled

If you've got a screen reader that is reading out the whole page,
each icon button (i.e., `<button><SVG></button>`) will have both
the button's aria-label read out as well as the title from the
SVG (which is usually just "image").

Since we are pretty good about setting aria-labels, we should instead
use `aria-hidden="true"` on these images, since they are not useful
to be read out.

I don't consider this a comprehensive review of all icons in the app,
but I knocked out all the low hanging fruit in this commit.
This commit is contained in:
Daniel Lew 2025-12-11 15:35:17 -06:00 committed by GitHub
parent b288d81f5a
commit 1143f73f59
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
175 changed files with 340 additions and 183 deletions

View file

@ -35,7 +35,7 @@ export default function AdvancedPanel() {
aria-label={localize('com_ui_back_to_builder')}
>
<div className="advanced-panel-content flex w-full items-center justify-center gap-2">
<ChevronLeft />
<ChevronLeft aria-hidden="true" />
</div>
</button>
</div>

View file

@ -150,7 +150,7 @@ const AgentChain: React.FC<AgentChainProps> = ({ field, currentAgentId }) => {
0: getAgentDetails(agentId)?.name || localize('com_ui_agent'),
})}
>
<X size={18} className="text-text-secondary" />
<X size={18} className="text-text-secondary" aria-hidden="true" />
</button>
</div>
{idx < agentIds.length - 1 && (

View file

@ -512,7 +512,7 @@ export default function AgentPanel() {
localize('com_ui_agent')
}
>
<Plus className="mr-1 h-4 w-4" />
<Plus className="mr-1 h-4 w-4" aria-hidden="true" />
{localize('com_ui_create') +
' ' +
localize('com_ui_new') +

View file

@ -87,7 +87,7 @@ export default function Action({ authType = '', isToolAuthenticated = false }) {
onClick={() => setIsDialogOpen(true)}
aria-label={localize('com_ui_add_api_key')}
>
<KeyRoundIcon className="h-5 w-5 text-text-primary" />
<KeyRoundIcon className="h-5 w-5 text-text-primary" aria-hidden="true" />
</button>
)}
<HoverCardTrigger>

View file

@ -291,7 +291,7 @@ export default function MCPTool({ serverInfo }: { serverInfo?: MCPServerInfo })
<Ariakit.VisuallyHidden>
{localize('com_ui_tool_more_info')}
</Ariakit.VisuallyHidden>
<ChevronDown className="h-4 w-4" />
<ChevronDown className="h-4 w-4" aria-hidden="true" />
</Ariakit.HovercardDisclosure>
</div>
<Ariakit.Hovercard

View file

@ -114,9 +114,15 @@ export default function InputSection({
>
<div className="relative h-4 w-4">
{passwordVisibility[name] ? (
<EyeOff className="absolute inset-0 h-4 w-4 duration-200 animate-in fade-in" />
<EyeOff
className="absolute inset-0 h-4 w-4 duration-200 animate-in fade-in"
aria-hidden="true"
/>
) : (
<Eye className="absolute inset-0 h-4 w-4 duration-200 animate-in fade-in" />
<Eye
className="absolute inset-0 h-4 w-4 duration-200 animate-in fade-in"
aria-hidden="true"
/>
)}
</div>
</button>