fix(a11y): icon buttons named only by a tooltip have names (#33454)

This commit is contained in:
G30 2026-10-31 04:37:16 -04:00 • committed by GitHub
parent 68df5123ff
commit c4daef0c94
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 76 additions and 1 deletions

View file

@ -824,6 +824,7 @@
/>
<button
type="button"
aria-label={$i18n.t('Remove')}
class="text-xs text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition px-1"
on:click={() =>
(policyEnvPairs = policyEnvPairs.filter((_, i) => i !== idx))}

View file

@ -51,6 +51,7 @@
<div class="flex items-center">
<button
aria-label={$i18n.t('Configure')}
class="self-center w-fit text-sm p-1.5 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
type="button"
on:click={() => {

View file

@ -743,6 +743,7 @@
<div class="flex gap-1 items-center">
<Tooltip content={$i18n.t('Configure')}>
<button
aria-label={$i18n.t('Configure')}
class="self-center p-1 bg-transparent hover:bg-gray-50/70 dark:hover:bg-gray-850/50 rounded-lg transition"
on:click={() => editWebhook(webhook)}
type="button"

View file

@ -291,6 +291,7 @@
<div class="flex gap-1 items-center">
<Tooltip content={$i18n.t('Configure')}>
<button
aria-label={$i18n.t('Configure')}
class="self-center p-1 bg-transparent hover:bg-black/5 dark:hover:bg-white/5 rounded-lg transition"
on:click={() => {
editTerminalIdx = idx;

View file

@ -1131,6 +1131,7 @@
{#if shiftKey}
<Tooltip content={model?.meta?.hidden ? $i18n.t('Show') : $i18n.t('Hide')}>
<button
aria-label={model?.meta?.hidden ? $i18n.t('Show') : $i18n.t('Hide')}
class="self-center w-fit text-sm p-1.5 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
type="button"
on:click={() => {

View file

@ -193,7 +193,13 @@
<div class="flex items-center justify-between">
<div class="text-sm font-normal">{providerLabel || provider}</div>
<Tooltip content={$i18n.t('Refresh')}>
<button class={iconButtonClass} type="button" on:click={refreshModels} disabled={loading}>
<button
aria-label={$i18n.t('Refresh')}
class={iconButtonClass}
type="button"
on:click={refreshModels}
disabled={loading}
>
<Refresh className="size-4" />
</button>
</Tooltip>
@ -209,6 +215,7 @@
/>
<Tooltip content={$i18n.t('Download Model')}>
<button
aria-label={$i18n.t('Download Model')}
class={iconButtonClass}
type="submit"
disabled={actionModel !== '' || modelRef.trim() === ''}

View file

@ -309,6 +309,7 @@
{#if onRemove}
<div>
<button
aria-label={$i18n.t('Remove {{name}}', { name: user.name })}
class="rounded-full py-1 transition disabled:opacity-50 disabled:cursor-not-allowed hover:text-gray-900 dark:hover:text-gray-100 text-gray-500 dark:text-gray-400 px-0"
type="button"
disabled={user.id === $_user?.id}

View file

@ -75,6 +75,7 @@
<div class="flex gap-1 items-center">
<Tooltip content={$i18n.t('Configure')}>
<button
aria-label={$i18n.t('Configure')}
class="self-center p-1 bg-transparent hover:bg-black/5 dark:hover:bg-white/5 rounded-lg transition"
on:click={() => {
showConfigModal = true;

View file

@ -98,6 +98,7 @@
{#if floatingActionButtons !== null}
<button
aria-label={$i18n.t('Add')}
class=""
type="button"
on:click={() => {

View file

@ -78,6 +78,7 @@
<div class="flex shrink-0 items-center gap-1">
<Tooltip content={$i18n.t('Configure')} className="self-start">
<button
aria-label={$i18n.t('Configure')}
class="flex size-6 items-center justify-center rounded-lg text-gray-400 transition-colors hover:text-gray-700 dark:text-gray-600 dark:hover:text-gray-300"
on:click={() => {
showConfigModal = true;

View file

@ -417,6 +417,7 @@
<div class="absolute top-2 right-2 z-10">
<Tooltip content={$i18n.t('Reset view')}>
<button
aria-label={$i18n.t('Reset view')}
class="p-1.5 rounded-lg bg-white/80 dark:bg-gray-850/80 backdrop-blur-sm shadow-sm hover:bg-gray-100 dark:hover:bg-gray-800 transition text-gray-500 dark:text-gray-400"
on:click={resetImageView}
>

View file

@ -30,6 +30,8 @@
>
<Tooltip placement="top" content={$i18n.t('H1')}>
<button
aria-label={$i18n.t('H1')}
aria-pressed={editor?.isActive('heading', { level: 1 })}
on:click={() => editor?.chain().focus().toggleHeading({ level: 1 }).run()}
class="{editor?.isActive('heading', { level: 1 })
? 'bg-gray-50 dark:bg-gray-700'
@ -42,6 +44,8 @@
<Tooltip placement="top" content={$i18n.t('H2')}>
<button
aria-label={$i18n.t('H2')}
aria-pressed={editor?.isActive('heading', { level: 2 })}
on:click={() => editor?.chain().focus().toggleHeading({ level: 2 }).run()}
class="{editor?.isActive('heading', { level: 2 })
? 'bg-gray-50 dark:bg-gray-700'
@ -54,6 +58,8 @@
<Tooltip placement="top" content={$i18n.t('H3')}>
<button
aria-label={$i18n.t('H3')}
aria-pressed={editor?.isActive('heading', { level: 3 })}
on:click={() => editor?.chain().focus().toggleHeading({ level: 3 }).run()}
class="{editor?.isActive('heading', { level: 3 })
? 'bg-gray-50 dark:bg-gray-700'
@ -67,6 +73,7 @@
{#if editor?.isActive('bulletList') || editor?.isActive('orderedList') || editor?.isActive('taskList')}
<Tooltip placement="top" content={$i18n.t('Lift List')}>
<button
aria-label={$i18n.t('Lift List')}
on:click={() => {
editor?.commands.liftListItem(editor?.isActive('taskList') ? 'taskItem' : 'listItem');
}}
@ -78,6 +85,7 @@
</Tooltip>
<Tooltip placement="top" content={$i18n.t('Sink List')}>
<button
aria-label={$i18n.t('Sink List')}
on:click={() =>
editor?.commands.sinkListItem(editor?.isActive('taskList') ? 'taskItem' : 'listItem')}
class="hover:bg-gray-50 dark:hover:bg-gray-700 rounded-lg p-1.5 transition-all"
@ -90,6 +98,8 @@
<Tooltip placement="top" content={$i18n.t('Bullet List')}>
<button
aria-label={$i18n.t('Bullet List')}
aria-pressed={editor?.isActive('bulletList')}
on:click={() => editor?.chain().focus().toggleBulletList().run()}
class="{editor?.isActive('bulletList')
? 'bg-gray-50 dark:bg-gray-700'
@ -102,6 +112,8 @@
<Tooltip placement="top" content={$i18n.t('Ordered List')}>
<button
aria-label={$i18n.t('Ordered List')}
aria-pressed={editor?.isActive('orderedList')}
on:click={() => editor?.chain().focus().toggleOrderedList().run()}
class="{editor?.isActive('orderedList')
? 'bg-gray-50 dark:bg-gray-700'
@ -114,6 +126,8 @@
<Tooltip placement="top" content={$i18n.t('Task List')}>
<button
aria-label={$i18n.t('Task List')}
aria-pressed={editor?.isActive('taskList')}
on:click={() => editor?.chain().focus().toggleTaskList().run()}
class="{editor?.isActive('taskList')
? 'bg-gray-50 dark:bg-gray-700'
@ -126,6 +140,8 @@
<Tooltip placement="top" content={$i18n.t('Bold')}>
<button
aria-label={$i18n.t('Bold')}
aria-pressed={editor?.isActive('bold')}
on:click={() => editor?.chain().focus().toggleBold().run()}
class="{editor?.isActive('bold')
? 'bg-gray-50 dark:bg-gray-700'
@ -138,6 +154,8 @@
<Tooltip placement="top" content={$i18n.t('Italic')}>
<button
aria-label={$i18n.t('Italic')}
aria-pressed={editor?.isActive('italic')}
on:click={() => editor?.chain().focus().toggleItalic().run()}
class="{editor?.isActive('italic')
? 'bg-gray-50 dark:bg-gray-700'
@ -150,6 +168,8 @@
<Tooltip placement="top" content={$i18n.t('Underline')}>
<button
aria-label={$i18n.t('Underline')}
aria-pressed={editor?.isActive('underline')}
on:click={() => editor?.chain().focus().toggleUnderline().run()}
class="{editor?.isActive('underline')
? 'bg-gray-50 dark:bg-gray-700'
@ -162,6 +182,8 @@
<Tooltip placement="top" content={$i18n.t('Strikethrough')}>
<button
aria-label={$i18n.t('Strikethrough')}
aria-pressed={editor?.isActive('strike')}
on:click={() => editor?.chain().focus().toggleStrike().run()}
class="{editor?.isActive('strike')
? 'bg-gray-50 dark:bg-gray-700'
@ -174,6 +196,8 @@
<Tooltip placement="top" content={$i18n.t('Code Block')}>
<button
aria-label={$i18n.t('Code Block')}
aria-pressed={editor?.isActive('codeBlock')}
on:click={() => editor?.chain().focus().toggleCodeBlock().run()}
class="{editor?.isActive('codeBlock')
? 'bg-gray-50 dark:bg-gray-700'
@ -198,6 +222,7 @@
>
<Tooltip placement="top" content={$i18n.t('Emoji')}>
<button
aria-label={$i18n.t('Emoji')}
class="hover:bg-gray-50 dark:hover:bg-gray-700 rounded-lg p-1.5 transition-all"
type="button"
>

View file

@ -43,6 +43,7 @@
<div class="flex gap-1">
<Tooltip content={$i18n.t('Download as SVG')}>
<button
aria-label={$i18n.t('Download as SVG')}
class="p-1.5 rounded-lg border border-gray-100 dark:border-none dark:bg-gray-850 hover:bg-gray-50 dark:hover:bg-gray-800 transition"
on:click={() => {
downloadAsSVG();
@ -54,6 +55,7 @@
<Tooltip content={$i18n.t('Reset view')}>
<button
aria-label={$i18n.t('Reset view')}
class="p-1.5 rounded-lg border border-gray-100 dark:border-none dark:bg-gray-850 hover:bg-gray-50 dark:hover:bg-gray-800 transition"
on:click={() => {
resetPanZoomViewport();
@ -65,6 +67,7 @@
<Tooltip content={$i18n.t('Copy to clipboard')}>
<button
aria-label={$i18n.t('Copy to clipboard')}
class="p-1.5 rounded-lg border border-gray-100 dark:border-none dark:bg-gray-850 hover:bg-gray-50 dark:hover:bg-gray-800 transition"
on:click={() => {
copyToClipboard(content);

View file

@ -350,6 +350,7 @@
{#if unshareHandler && chat.share_id}
<Tooltip content={$i18n.t('Copy Share Link')}>
<button
aria-label={$i18n.t('Copy Share Link')}
class="self-center w-fit px-1 text-sm rounded-xl"
on:click={async (e) => {
e.stopImmediatePropagation();
@ -370,6 +371,9 @@
: $i18n.t('Delete Chat')}
>
<button
aria-label={unshareHandler
? $i18n.t('Unshare Chat')
: $i18n.t('Delete Chat')}
class="self-center w-fit px-1 text-sm rounded-xl"
on:click={async (e) => {
e.stopImmediatePropagation();
@ -480,6 +484,7 @@
{#if unarchiveHandler}
<Tooltip content={$i18n.t('Unarchive Chat')}>
<button
aria-label={$i18n.t('Unarchive Chat')}
class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
on:click={async () => {
unarchiveHandler(chat.id);
@ -505,6 +510,7 @@
<Tooltip content={$i18n.t('Delete Chat')}>
<button
aria-label={$i18n.t('Delete Chat')}
class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
on:click={async () => {
deleteHandler(chat.id);

View file

@ -789,6 +789,7 @@
>
<Tooltip content={$i18n.t('Generate')}>
<button
aria-label={$i18n.t('Generate')}
class="flex size-5 items-center justify-center self-center dark:hover:text-white transition disabled:cursor-not-allowed"
id="generate-title-button"
disabled={generating}
@ -805,6 +806,7 @@
{#if $visibleControls['chat.archive']}
<Tooltip content={$i18n.t('Archive')} className="flex items-center">
<button
aria-label={$i18n.t('Archive')}
class="flex size-5 items-center justify-center self-center dark:hover:text-white transition disabled:cursor-not-allowed"
disabled={archiving}
on:click={() => {
@ -820,6 +822,7 @@
{#if $user?.role === 'admin' || ($user?.permissions?.chat?.delete ?? true)}
<Tooltip content={$i18n.t('Delete')}>
<button
aria-label={$i18n.t('Delete')}
class=" self-center dark:hover:text-white transition disabled:cursor-not-allowed"
disabled={deleting}
on:click={() => {

View file

@ -63,6 +63,7 @@
<div class=" flex items-center self-center space-x-1.5">
<Tooltip content={$i18n.t('Unpin')} className="flex items-center">
<button
aria-label={$i18n.t('Unpin')}
class=" self-center dark:hover:text-white transition"
on:click={() => {
onUnpin();

View file

@ -277,6 +277,9 @@
: $i18n.t('Pin to Sidebar')}
>
<button
aria-label={pinnedItems.includes('workspace')
? $i18n.t('Unpin from Sidebar')
: $i18n.t('Pin to Sidebar')}
role="menuitem"
type="button"
class="p-1 mr-1 rounded-lg hover:bg-gray-100/60 dark:hover:bg-gray-700/60 transition"
@ -325,6 +328,9 @@
: $i18n.t('Pin to Sidebar')}
>
<button
aria-label={pinnedItems.includes('notes')
? $i18n.t('Unpin from Sidebar')
: $i18n.t('Pin to Sidebar')}
role="menuitem"
type="button"
class="p-1 mr-1 rounded-lg hover:bg-gray-100/60 dark:hover:bg-gray-700/60 transition"
@ -373,6 +379,9 @@
: $i18n.t('Pin to Sidebar')}
>
<button
aria-label={pinnedItems.includes('calendar')
? $i18n.t('Unpin from Sidebar')
: $i18n.t('Pin to Sidebar')}
role="menuitem"
type="button"
class="p-1 mr-1 rounded-lg hover:bg-gray-100/60 dark:hover:bg-gray-700/60 transition"
@ -421,6 +430,9 @@
: $i18n.t('Pin to Sidebar')}
>
<button
aria-label={pinnedItems.includes('automations')
? $i18n.t('Unpin from Sidebar')
: $i18n.t('Pin to Sidebar')}
role="menuitem"
type="button"
class="p-1 mr-1 rounded-lg hover:bg-gray-100/60 dark:hover:bg-gray-700/60 transition"
@ -469,6 +481,9 @@
: $i18n.t('Pin to Sidebar')}
>
<button
aria-label={pinnedItems.includes('playground')
? $i18n.t('Unpin from Sidebar')
: $i18n.t('Pin to Sidebar')}
role="menuitem"
type="button"
class="p-1 mr-1 rounded-lg hover:bg-gray-100/60 dark:hover:bg-gray-700/60 transition"

View file

@ -135,6 +135,7 @@
<button
type="button"
aria-label={$i18n.t('Clear')}
on:click={() => {
emoji = '';
message = '';

View file

@ -135,6 +135,7 @@
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-3">
{#each generatedImages as image, index}
<button
aria-label={$i18n.t('Download')}
class="relative group cursor-pointer"
on:click={() => downloadImage(image.url, index)}
>

View file

@ -103,6 +103,7 @@
{:else}
<Tooltip content={$i18n.t('Voice Input')}>
<button
aria-label={$i18n.t('Voice Input')}
class=" p-2 bg-gray-50 text-gray-700 dark:bg-gray-700 dark:text-white transition rounded-full"
type="button"
on:click={async () => {

View file

@ -637,6 +637,7 @@
{/if}
<button
aria-label={$i18n.t('Remove {{name}}', { name: group.name })}
class="rounded-full py-1 transition hover:text-gray-900 dark:hover:text-gray-100 text-gray-500 dark:text-gray-400 px-0"
type="button"
on:click={() => {
@ -689,6 +690,7 @@
{/if}
<button
aria-label={$i18n.t('Remove {{name}}', { name: user.name ?? user.id })}
class="rounded-full py-1 transition hover:text-gray-900 dark:hover:text-gray-100 text-gray-500 dark:text-gray-400 px-0"
type="button"
on:click={() => {