fix(a11y): enhance accessibility for chat settings components (#21715)

This commit adds aria-labels to the text inputs and textareas that previously lacked them, applies role=switch to inputs, and adds accessible titles to floating quick actions.
This commit is contained in:
Classic298
2026-02-22 21:33:07 +01:00
committed by GitHub
parent 1542dad51a
commit 16e567df57
8 changed files with 34 additions and 2 deletions

View File

@@ -150,6 +150,7 @@
class="w-full text-sm dark:text-gray-300 bg-transparent outline-hidden"
type="text"
bind:value={name}
aria-label={$i18n.t('Name')}
required
placeholder={$i18n.t('Enter your name')}
/>
@@ -164,6 +165,7 @@
className="w-full text-sm dark:text-gray-300 bg-transparent outline-hidden"
minSize={60}
bind:value={bio}
ariaLabel={$i18n.t('Bio')}
placeholder={$i18n.t('Share your background and interests')}
/>
</div>
@@ -176,6 +178,7 @@
<select
class="w-full text-sm dark:text-gray-300 bg-transparent outline-hidden"
bind:value={_gender}
aria-label={$i18n.t('Gender')}
on:change={(e) => {
console.log(_gender);
@@ -199,6 +202,7 @@
class="w-full text-sm dark:text-gray-300 bg-transparent outline-hidden mt-1"
type="text"
required
aria-label={$i18n.t('Custom Gender')}
placeholder={$i18n.t('Enter your gender')}
bind:value={gender}
/>
@@ -212,6 +216,7 @@
<input
class="w-full text-sm dark:text-gray-300 dark:placeholder:text-gray-300 bg-transparent outline-hidden"
type="date"
aria-label={$i18n.t('Birth Date')}
bind:value={dateOfBirth}
required
/>
@@ -232,6 +237,7 @@
class="w-full text-sm outline-hidden"
type="url"
placeholder={$i18n.t('Enter your webhook URL')}
aria-label={$i18n.t('Notification Webhook')}
bind:value={webhookUrl}
required
/>
@@ -273,6 +279,7 @@
<button
class="ml-1.5 px-1.5 py-1 dark:hover:bg-gray-850 transition rounded-lg"
aria-label={$i18n.t('Copy Token')}
on:click={() => {
copyToClipboard(localStorage.token);
JWTTokenCopied = true;
@@ -331,6 +338,7 @@
<button
class="ml-1.5 px-1.5 py-1 dark:hover:bg-gray-850 transition rounded-lg"
aria-label={$i18n.t('Copy API Key')}
on:click={() => {
copyToClipboard(APIKey);
APIKeyCopied = true;
@@ -376,6 +384,7 @@
<Tooltip content={$i18n.t('Create new key')}>
<button
class=" px-1.5 py-1 dark:hover:bg-gray-850transition rounded-lg"
aria-label={$i18n.t('Create new key')}
on:click={() => {
createAPIKeyHandler();
}}

View File

@@ -186,6 +186,7 @@
<select
class="w-fit pr-8 rounded-sm px-2 p-1 text-xs bg-transparent outline-hidden text-right"
bind:value={STTEngine}
aria-label={$i18n.t('Speech-to-Text Engine')}
placeholder={$i18n.t('Select an engine')}
>
<option value="">{$i18n.t('Default')}</option>
@@ -207,6 +208,7 @@
<input
type="text"
bind:value={STTLanguage}
aria-label={$i18n.t('Speech-to-Text Language')}
placeholder={$i18n.t('e.g. en')}
class=" text-sm text-right bg-transparent dark:text-gray-300 outline-hidden"
/>
@@ -226,6 +228,8 @@
toggleSpeechAutoSend();
}}
type="button"
role="switch"
aria-checked={speechAutoSend}
>
{#if speechAutoSend === true}
<span class="ml-2 self-center">{$i18n.t('On')}</span>
@@ -245,6 +249,7 @@
<select
class="w-fit pr-8 rounded-sm px-2 p-1 text-xs bg-transparent outline-hidden text-right"
bind:value={TTSEngine}
aria-label={$i18n.t('Text-to-Speech Engine')}
placeholder={$i18n.t('Select an engine')}
>
<option value="">{$i18n.t('Default')}</option>
@@ -260,6 +265,7 @@
<select
class="w-fit pr-8 rounded-sm px-2 p-1 text-xs bg-transparent outline-hidden text-right"
bind:value={TTSEngineConfig.dtype}
aria-label={$i18n.t('Kokoro.js Dtype')}
placeholder={$i18n.t('Select dtype')}
>
<option value="" disabled selected>{$i18n.t('Select dtype')}</option>
@@ -281,6 +287,8 @@
toggleResponseAutoPlayback();
}}
type="button"
role="switch"
aria-checked={responseAutoPlayback}
>
{#if responseAutoPlayback === true}
<span class="ml-2 self-center">{$i18n.t('On')}</span>
@@ -299,6 +307,7 @@
min="0"
step="0.01"
bind:value={playbackRate}
aria-label={$i18n.t('Speech Playback Speed')}
class=" text-sm text-right bg-transparent dark:text-gray-300 outline-hidden"
/>
x
@@ -318,6 +327,7 @@
list="voice-list"
class="w-full text-sm bg-transparent dark:text-gray-300 outline-hidden"
bind:value={voice}
aria-label={$i18n.t('Voice')}
placeholder={$i18n.t('Select a voice')}
/>
@@ -355,6 +365,7 @@
<select
class="w-full text-sm bg-transparent dark:text-gray-300 outline-hidden"
bind:value={voice}
aria-label={$i18n.t('Voice')}
>
<option value="" selected={voice !== ''}>{$i18n.t('Default')}</option>
{#each voices.filter((v) => nonLocalVoices || v.localService === true) as _voice}
@@ -386,6 +397,7 @@
list="voice-list"
class="w-full text-sm bg-transparent dark:text-gray-300 outline-hidden"
bind:value={voice}
aria-label={$i18n.t('Voice')}
placeholder={$i18n.t('Select a voice')}
/>

View File

@@ -87,6 +87,7 @@
<Tooltip content={$i18n.t(`Add Connection`)}>
<button
class="px-1"
aria-label={$i18n.t('Add Connection')}
on:click={() => {
showConnectionModal = true;
}}

View File

@@ -269,6 +269,8 @@
toggleNotification();
}}
type="button"
role="switch"
aria-checked={notificationEnabled}
>
{#if notificationEnabled === true}
<span class="ml-2 self-center">{$i18n.t('On')}</span>
@@ -306,6 +308,7 @@
? 'text-gray-800 dark:text-gray-100'
: 'text-gray-400 dark:text-gray-500'}"
type="button"
aria-expanded={showAdvanced}
on:click={() => {
showAdvanced = !showAdvanced;
}}>{showAdvanced ? $i18n.t('Hide') : $i18n.t('Show')}</button

View File

@@ -129,12 +129,14 @@
<input
class=" self-center text-xs outline-none w-20"
placeholder={$i18n.t('Button Label')}
aria-label={$i18n.t('Button Label')}
bind:value={button.label}
/>
<input
class=" self-center text-xs outline-none w-20 text-gray-600 dark:text-gray-400"
placeholder={$i18n.t('Button ID')}
aria-label={$i18n.t('Button ID')}
bind:value={button.id}
/>
</div>
@@ -143,12 +145,14 @@
<Textarea
className=" self-center text-xs w-full outline-none"
placeholder={$i18n.t('Button Prompt')}
ariaLabel={$i18n.t('Button Prompt')}
minSize={30}
bind:value={button.prompt}
/>
</div>
<button
class="pl-3 text-xs flex rounded-sm transition"
aria-label={$i18n.t('Remove action')}
on:click={() => {
floatingActionButtons = floatingActionButtons.filter(
(b) => b.id !== button.id

View File

@@ -62,9 +62,9 @@
>{$i18n.t('Image Max Compression Size width')}</label
>
<input
id="image-comp-width"
bind:value={size.width}
type="number"
aria-labelledby="image-comp-width"
class="w-full bg-transparent outline-hidden text-center"
min="0"
placeholder={$i18n.t('Width')}
@@ -80,9 +80,9 @@
>{$i18n.t('Image Max Compression Size height')}</label
>
<input
id="image-comp-height"
bind:value={size.height}
type="number"
aria-labelledby="image-comp-height"
class="w-full bg-transparent outline-hidden text-center"
min="0"
placeholder={$i18n.t('Height')}

View File

@@ -358,6 +358,7 @@
<div class="text-lg font-medium self-center">{$i18n.t('Sync Usage Stats')}</div>
<button
class="self-center"
aria-label={$i18n.t('Close modal')}
on:click={() => {
show = false;
}}

View File

@@ -10,6 +10,7 @@
export let readonly = false;
export let className =
'w-full rounded-lg px-3.5 py-2 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-hidden h-full';
export let ariaLabel = null;
export let onInput = () => {};
export let onBlur = () => {};
@@ -53,6 +54,7 @@
bind:this={textareaElement}
bind:value
{placeholder}
aria-label={ariaLabel || placeholder}
class={className}
style="field-sizing: content;"
{rows}