Merge pull request #16348 from itk-dev/feature/add-label-to-settings-modal-controls

FEAT: add label to settings modal controls
This commit is contained in:
Tim Jaeryang Baek 2025-08-07 20:43:17 +04:00 committed by GitHub
commit 55248bed2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 80 additions and 41 deletions

View file

@ -299,6 +299,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="high-contrast-mode-label"
tooltip={true} tooltip={true}
bind:state={highContrastMode} bind:state={highContrastMode}
on:change={() => { on:change={() => {
@ -317,6 +318,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="notification-sound-label"
tooltip={true} tooltip={true}
bind:state={notificationSound} bind:state={notificationSound}
on:change={() => { on:change={() => {
@ -336,6 +338,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="play-notification-sound-label"
tooltip={true} tooltip={true}
bind:state={notificationSoundAlways} bind:state={notificationSoundAlways}
on:change={() => { on:change={() => {
@ -353,6 +356,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="allow-user-location-label"
tooltip={true} tooltip={true}
bind:state={userLocation} bind:state={userLocation}
on:change={() => { on:change={() => {
@ -371,6 +375,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="haptic-feedback-label"
tooltip={true} tooltip={true}
bind:state={hapticFeedback} bind:state={hapticFeedback}
on:change={() => { on:change={() => {
@ -389,6 +394,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="copy-formatted-label"
tooltip={true} tooltip={true}
bind:state={copyFormatted} bind:state={copyFormatted}
on:change={() => { on:change={() => {
@ -408,6 +414,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="toast-notifications-label"
tooltip={true} tooltip={true}
bind:state={showUpdateToast} bind:state={showUpdateToast}
on:change={() => { on:change={() => {
@ -426,6 +433,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="whats-new-label"
tooltip={true} tooltip={true}
bind:state={showChangelog} bind:state={showChangelog}
on:change={() => { on:change={() => {
@ -446,18 +454,18 @@
</div> </div>
<button <button
aria-labelledby="chat-direction-label" aria-labelledby="chat-direction-label chat-direction-mode"
class="p-1 px-3 text-xs flex rounded-sm transition" class="p-1 px-3 text-xs flex rounded-sm transition"
on:click={toggleChangeChatDirection} on:click={toggleChangeChatDirection}
type="button" type="button"
> >
{#if chatDirection === 'LTR'} <span class="ml-2 self-center" id="chat-direction-mode">
<span class="ml-2 self-center">{$i18n.t('LTR')}</span> {chatDirection === 'LTR'
{:else if chatDirection === 'RTL'} ? $i18n.t('LTR')
<span class="ml-2 self-center">{$i18n.t('RTL')}</span> : chatDirection === 'RTL'
{:else} ? $i18n.t('RTL')
<span class="ml-2 self-center">{$i18n.t('Auto')}</span> : $i18n.t('Auto')}
{/if} </span>
</button> </button>
</div> </div>
</div> </div>
@ -469,18 +477,16 @@
</div> </div>
<button <button
aria-labelledby="landing-page-mode-label" aria-labelledby="landing-page-mode-label notification-sound-state"
class="p-1 px-3 text-xs flex rounded-sm transition" class="p-1 px-3 text-xs flex rounded-sm transition"
on:click={() => { on:click={() => {
toggleLandingPageMode(); toggleLandingPageMode();
}} }}
type="button" type="button"
> >
{#if landingPageMode === ''} <span class="ml-2 self-center" id="notification-sound-state"
<span class="ml-2 self-center">{$i18n.t('Default')}</span> >{notificationSound === true ? $i18n.t('On') : $i18n.t('Off')}</span
{:else} >
<span class="ml-2 self-center">{$i18n.t('Chat')}</span>
{/if}
</button> </button>
</div> </div>
</div> </div>
@ -492,7 +498,7 @@
</div> </div>
<button <button
aria-labelledby="chat-background-label" aria-labelledby="chat-background-label background-image-url-state"
class="p-1 px-3 text-xs flex rounded-sm transition" class="p-1 px-3 text-xs flex rounded-sm transition"
on:click={() => { on:click={() => {
if (backgroundImageUrl !== null) { if (backgroundImageUrl !== null) {
@ -504,11 +510,9 @@
}} }}
type="button" type="button"
> >
{#if backgroundImageUrl !== null} <span class="ml-2 self-center" id="background-image-url-state"
<span class="ml-2 self-center">{$i18n.t('Reset')}</span> >{backgroundImageUrl !== null ? $i18n.t('Reset') : $i18n.t('Upload')}</span
{:else} >
<span class="ml-2 self-center">{$i18n.t('Upload')}</span>
{/if}
</button> </button>
</div> </div>
</div> </div>
@ -522,6 +526,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
tooltip={true} tooltip={true}
ariaLabelledbyId="chat-bubble-ui-label"
bind:state={chatBubble} bind:state={chatBubble}
on:change={() => { on:change={() => {
saveSettings({ chatBubble }); saveSettings({ chatBubble });
@ -540,6 +545,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="chat-bubble-username-label"
tooltip={true} tooltip={true}
bind:state={showUsername} bind:state={showUsername}
on:change={() => { on:change={() => {
@ -559,6 +565,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="widescreen-mode-label"
tooltip={true} tooltip={true}
bind:state={widescreenMode} bind:state={widescreenMode}
on:change={() => { on:change={() => {
@ -577,6 +584,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="fade-streaming-label"
tooltip={true} tooltip={true}
bind:state={chatFadeStreamingText} bind:state={chatFadeStreamingText}
on:change={() => { on:change={() => {
@ -595,6 +603,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="auto-generation-label"
tooltip={true} tooltip={true}
bind:state={titleAutoGenerate} bind:state={titleAutoGenerate}
on:change={() => { on:change={() => {
@ -607,10 +616,13 @@
<div> <div>
<div class=" py-0.5 flex w-full justify-between"> <div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs">{$i18n.t('Follow-Up Auto-Generation')}</div> <div class=" self-center text-xs" id="follow-up-auto-generation-label">
{$i18n.t('Follow-Up Auto-Generation')}
</div>
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="follow-up-auto-generation-label"
tooltip={true} tooltip={true}
bind:state={autoFollowUps} bind:state={autoFollowUps}
on:change={() => { on:change={() => {
@ -629,6 +641,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="chat-tags-label"
tooltip={true} tooltip={true}
bind:state={autoTags} bind:state={autoTags}
on:change={() => { on:change={() => {
@ -647,6 +660,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="auto-copy-label"
tooltip={true} tooltip={true}
bind:state={responseAutoCopy} bind:state={responseAutoCopy}
on:change={() => { on:change={() => {
@ -659,12 +673,13 @@
<div> <div>
<div class=" py-0.5 flex w-full justify-between"> <div class=" py-0.5 flex w-full justify-between">
<div id="keep-followup-prompts-label" class=" self-center text-xs"> <div id="keep-follow-up-prompts-label" class=" self-center text-xs">
{$i18n.t('Keep Follow-Up Prompts in Chat')} {$i18n.t('Keep Follow-Up Prompts in Chat')}
</div> </div>
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="keep-follow-up-prompts-label"
tooltip={true} tooltip={true}
bind:state={keepFollowUpPrompts} bind:state={keepFollowUpPrompts}
on:change={() => { on:change={() => {
@ -677,12 +692,13 @@
<div> <div>
<div class=" py-0.5 flex w-full justify-between"> <div class=" py-0.5 flex w-full justify-between">
<div id="insert-followup-prompt-label" class=" self-center text-xs"> <div id="insert-follow-up-prompt-label" class=" self-center text-xs">
{$i18n.t('Insert Follow-Up Prompt to Input')} {$i18n.t('Insert Follow-Up Prompt to Input')}
</div> </div>
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="insert-follow-up-prompt-label"
tooltip={true} tooltip={true}
bind:state={insertFollowUpPrompt} bind:state={insertFollowUpPrompt}
on:change={() => { on:change={() => {
@ -701,6 +717,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="always-collapse-label"
tooltip={true} tooltip={true}
bind:state={collapseCodeBlocks} bind:state={collapseCodeBlocks}
on:change={() => { on:change={() => {
@ -719,6 +736,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="always-expand-label"
tooltip={true} tooltip={true}
bind:state={expandDetails} bind:state={expandDetails}
on:change={() => { on:change={() => {
@ -737,6 +755,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="keep-followup-prompts-label"
tooltip={true} tooltip={true}
bind:state={displayMultiModelResponsesInTabs} bind:state={displayMultiModelResponsesInTabs}
on:change={() => { on:change={() => {
@ -755,6 +774,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="scroll-on-branch-change-label"
tooltip={true} tooltip={true}
bind:state={scrollOnBranchChange} bind:state={scrollOnBranchChange}
on:change={() => { on:change={() => {
@ -773,6 +793,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="stylized-pdf-export-label"
tooltip={true} tooltip={true}
bind:state={stylizedPdfExport} bind:state={stylizedPdfExport}
on:change={() => { on:change={() => {
@ -785,15 +806,16 @@
<div> <div>
<div class=" py-0.5 flex w-full justify-between"> <div class=" py-0.5 flex w-full justify-between">
<div id="floating-action-buttons-label" class=" self-center text-xs"> <label id="floating-action-buttons-label" class=" self-center text-xs">
{$i18n.t('Floating Action Buttons')} {$i18n.t('Floating Action Buttons')}
</div> </label>
<div class="flex items-center gap-3 p-1"> <div class="flex items-center gap-3 p-1">
{#if showFloatingActionButtons} {#if showFloatingActionButtons}
<button <button
class="text-xs text-gray-700 dark:text-gray-400 underline" class="text-xs text-gray-700 dark:text-gray-400 underline"
type="button" type="button"
aria-label={$i18n.t('Open Modal To Manage Floating Action Buttons')}
on:click={() => { on:click={() => {
showManageFloatingActionButtonsModal = true; showManageFloatingActionButtonsModal = true;
}} }}
@ -803,6 +825,7 @@
{/if} {/if}
<Switch <Switch
ariaLabelledbyId="floating-action-buttons-label"
tooltip={true} tooltip={true}
bind:state={showFloatingActionButtons} bind:state={showFloatingActionButtons}
on:change={() => { on:change={() => {
@ -820,18 +843,16 @@
</div> </div>
<button <button
aria-labelledby="web-search-in-chat-label" aria-labelledby="web-search-in-chat-label web-search-state"
class="p-1 px-3 text-xs flex rounded-sm transition" class="p-1 px-3 text-xs flex rounded-sm transition"
on:click={() => { on:click={() => {
toggleWebSearch(); toggleWebSearch();
}} }}
type="button" type="button"
> >
{#if webSearch === 'always'} <span class="ml-2 self-center" id="web-search-state"
<span class="ml-2 self-center">{$i18n.t('Always')}</span> >{webSearch === 'always' ? $i18n.t('Always') : $i18n.t('Default')}</span
{:else} >
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{/if}
</button> </button>
</div> </div>
</div> </div>
@ -840,7 +861,7 @@
<div> <div>
<div class=" py-0.5 flex w-full justify-between"> <div class=" py-0.5 flex w-full justify-between">
<div id="enter-key-behavior-label" class=" self-center text-xs"> <div id="enter-key-behavior-label ctrl-enter-to-send-state" class=" self-center text-xs">
{$i18n.t('Enter Key Behavior')} {$i18n.t('Enter Key Behavior')}
</div> </div>
@ -852,11 +873,11 @@
}} }}
type="button" type="button"
> >
{#if ctrlEnterToSend === true} <span class="ml-2 self-center" id="ctrl-enter-to-send-state"
<span class="ml-2 self-center">{$i18n.t('Ctrl+Enter to Send')}</span> >{ctrlEnterToSend === true
{:else} ? $i18n.t('Ctrl+Enter to Send')
<span class="ml-2 self-center">{$i18n.t('Enter to Send')}</span> : $i18n.t('Enter to Send')}</span
{/if} >
</button> </button>
</div> </div>
</div> </div>
@ -870,6 +891,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
tooltip={true} tooltip={true}
ariaLabelledbyId="rich-input-label"
bind:state={richTextInput} bind:state={richTextInput}
on:change={() => { on:change={() => {
saveSettings({ richTextInput }); saveSettings({ richTextInput });
@ -882,12 +904,13 @@
{#if richTextInput} {#if richTextInput}
<div> <div>
<div class=" py-0.5 flex w-full justify-between"> <div class=" py-0.5 flex w-full justify-between">
<div id="rich-input-label" class=" self-center text-xs"> <div id="show-formatting-toolbar-label" class=" self-center text-xs">
{$i18n.t('Show Formatting Toolbar')} {$i18n.t('Show Formatting Toolbar')}
</div> </div>
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="show-formatting-toolbar-label"
tooltip={true} tooltip={true}
bind:state={showFormattingToolbar} bind:state={showFormattingToolbar}
on:change={() => { on:change={() => {
@ -900,12 +923,13 @@
<div> <div>
<div class=" py-0.5 flex w-full justify-between"> <div class=" py-0.5 flex w-full justify-between">
<div id="rich-input-label" class=" self-center text-xs"> <div id="insert-prompt-as-rich-text-label" class=" self-center text-xs">
{$i18n.t('Insert Prompt as Rich Text')} {$i18n.t('Insert Prompt as Rich Text')}
</div> </div>
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="insert-prompt-as-rich-text-label"
tooltip={true} tooltip={true}
bind:state={insertPromptAsRichText} bind:state={insertPromptAsRichText}
on:change={() => { on:change={() => {
@ -925,6 +949,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="prompt-autocompletion-label"
tooltip={true} tooltip={true}
bind:state={promptAutocomplete} bind:state={promptAutocomplete}
on:change={() => { on:change={() => {
@ -946,6 +971,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
tooltip={true} tooltip={true}
ariaLabelledbyId="paste-large-label"
bind:state={largeTextAsFile} bind:state={largeTextAsFile}
on:change={() => { on:change={() => {
saveSettings({ largeTextAsFile }); saveSettings({ largeTextAsFile });
@ -965,6 +991,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="detect-artifacts-label"
tooltip={true} tooltip={true}
bind:state={detectArtifacts} bind:state={detectArtifacts}
on:change={() => { on:change={() => {
@ -983,6 +1010,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="iframe-sandbox-allow-same-origin-label"
tooltip={true} tooltip={true}
bind:state={iframeSandboxAllowSameOrigin} bind:state={iframeSandboxAllowSameOrigin}
on:change={() => { on:change={() => {
@ -1001,6 +1029,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="iframe-sandbox-allow-forms-label"
tooltip={true} tooltip={true}
bind:state={iframeSandboxAllowForms} bind:state={iframeSandboxAllowForms}
on:change={() => { on:change={() => {
@ -1015,10 +1044,13 @@
<div> <div>
<div class=" py-0.5 flex w-full justify-between"> <div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs">{$i18n.t('Allow Voice Interruption in Call')}</div> <div class=" self-center text-xs" id="allow-voice-interruption-in-call-label">
{$i18n.t('Allow Voice Interruption in Call')}
</div>
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="allow-voice-interruption-in-call-label"
tooltip={true} tooltip={true}
bind:state={voiceInterruption} bind:state={voiceInterruption}
on:change={() => { on:change={() => {
@ -1037,6 +1069,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="display-emoji-label"
tooltip={true} tooltip={true}
bind:state={showEmojiInCall} bind:state={showEmojiInCall}
on:change={() => { on:change={() => {
@ -1057,6 +1090,7 @@
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="image-compression-label"
tooltip={true} tooltip={true}
bind:state={imageCompression} bind:state={imageCompression}
on:change={() => { on:change={() => {
@ -1081,6 +1115,7 @@
<input <input
bind:value={imageCompressionSize.width} bind:value={imageCompressionSize.width}
type="number" type="number"
aria-labelledby="image-comp-width"
class="w-20 bg-transparent outline-hidden text-center" class="w-20 bg-transparent outline-hidden text-center"
min="0" min="0"
placeholder="Width" placeholder="Width"
@ -1091,6 +1126,7 @@
<input <input
bind:value={imageCompressionSize.height} bind:value={imageCompressionSize.height}
type="number" type="number"
aria-labelledby="image-comp-height"
class="w-20 bg-transparent outline-hidden text-center" class="w-20 bg-transparent outline-hidden text-center"
min="0" min="0"
placeholder="Height" placeholder="Height"
@ -1101,12 +1137,13 @@
<div> <div>
<div class=" py-0.5 flex w-full justify-between"> <div class=" py-0.5 flex w-full justify-between">
<div id="image-compression-label" class=" self-center text-xs"> <div id="image-compression-in-channels-label" class=" self-center text-xs">
{$i18n.t('Compress Images in Channels')} {$i18n.t('Compress Images in Channels')}
</div> </div>
<div class="flex items-center gap-2 p-1"> <div class="flex items-center gap-2 p-1">
<Switch <Switch
ariaLabelledbyId="image-compression-in-channels-label"
tooltip={true} tooltip={true}
bind:state={imageCompressionInChannels} bind:state={imageCompressionInChannels}
on:change={() => { on:change={() => {

View file

@ -5,6 +5,7 @@
import Tooltip from './Tooltip.svelte'; import Tooltip from './Tooltip.svelte';
export let state = true; export let state = true;
export let id = ''; export let id = '';
export let ariaLabelledbyId = '';
export let tooltip = false; export let tooltip = false;
const i18n = getContext('i18n'); const i18n = getContext('i18n');
@ -20,6 +21,7 @@
<Switch.Root <Switch.Root
bind:checked={state} bind:checked={state}
{id} {id}
aria-labelledby={ariaLabelledbyId}
class="flex h-5 min-h-5 w-9 shrink-0 cursor-pointer items-center rounded-full px-[3px] mx-[1px] transition {($settings?.highContrastMode ?? class="flex h-5 min-h-5 w-9 shrink-0 cursor-pointer items-center rounded-full px-[3px] mx-[1px] transition {($settings?.highContrastMode ??
false) false)
? 'focus:outline focus:outline-2 focus:outline-gray-800 focus:dark:outline-gray-200' ? 'focus:outline focus:outline-2 focus:outline-gray-800 focus:dark:outline-gray-200'