Bläddra i källkod

Merge pull request #15018 from itk-dev/feature/interface-tab-settings-modal-accessibility

Feat: interface tab settings modal accessibility
Tim Jaeryang Baek 3 månader sedan
förälder
incheckning
b8103807cf
1 ändrade filer med 72 tillägg och 35 borttagningar
  1. 72 35
      src/lib/components/chat/Settings/Interface.svelte

+ 72 - 35
src/lib/components/chat/Settings/Interface.svelte

@@ -385,15 +385,16 @@
 
 	<div class=" space-y-3 overflow-y-scroll max-h-[28rem] lg:max-h-full">
 		<div>
-			<div class=" mb-1.5 text-sm font-medium">{$i18n.t('UI')}</div>
+			<h1 class=" mb-1.5 text-sm font-medium">{$i18n.t('UI')}</h1>
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">
+					<div id="high-contrast-mode-label" class=" self-center text-xs">
 						{$i18n.t('High Contrast Mode')} ({$i18n.t('Beta')})
 					</div>
 
 					<button
+					aria-labelledby="high-contrast-mode-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleHighContrastMode();
@@ -411,9 +412,10 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">{$i18n.t('Landing Page Mode')}</div>
+					<div id="landing-page-mode-label" class=" self-center text-xs">{$i18n.t('Landing Page Mode')}</div>
 
 					<button
+					aria-labelledby="landing-page-mode-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleLandingPageMode();
@@ -431,9 +433,10 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">{$i18n.t('Chat Bubble UI')}</div>
+					<div id="chat-bubble-ui-label" class=" self-center text-xs">{$i18n.t('Chat Bubble UI')}</div>
 
 					<button
+					aria-labelledby="chat-bubble-ui-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleChatBubble();
@@ -452,11 +455,12 @@
 			{#if !$settings.chatBubble}
 				<div>
 					<div class=" py-0.5 flex w-full justify-between">
-						<div class=" self-center text-xs">
+						<div id="chat-bubble-username-label" class=" self-center text-xs">
 							{$i18n.t('Display the username instead of You in the Chat')}
 						</div>
 
 						<button
+					aria-labelledby="chat-bubble-username-label"
 							class="p-1 px-3 text-xs flex rounded-sm transition"
 							on:click={() => {
 								toggleShowUsername();
@@ -475,13 +479,14 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">{$i18n.t('Widescreen Mode')}</div>
+					<div id="widescreen-mode-label" class=" self-center text-xs">{$i18n.t('Widescreen Mode')}</div>
 
 					<button
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleWidescreenMode();
 						}}
+					aria-labelledby="widescreen-mode-label"
 						type="button"
 					>
 						{#if widescreenMode === true}
@@ -495,9 +500,10 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">{$i18n.t('Chat direction')}</div>
+					<div id="chat-direction-label" class=" self-center text-xs">{$i18n.t('Chat direction')}</div>
 
 					<button
+					aria-labelledby="chat-direction-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={toggleChangeChatDirection}
 						type="button"
@@ -514,12 +520,13 @@
 			</div>
 
 			<div>
-				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">
+				<div class="py-0.5 flex w-full justify-between">
+					<div id=""notification-sound-label"" class=" self-center text-xs">
 						{$i18n.t('Notification Sound')}
 					</div>
 
 					<button
+					aria-labelledby="notification-sound-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleNotificationSound();
@@ -538,11 +545,12 @@
 			{#if notificationSound}
 				<div>
 					<div class=" py-0.5 flex w-full justify-between">
-						<div class=" self-center text-xs">
+						<div id="play-notification-sound-label" class=" self-center text-xs">
 							{$i18n.t('Always Play Notification Sound')}
 						</div>
 
 						<button
+					aria-labelledby="play-notification-sound-label"
 							class="p-1 px-3 text-xs flex rounded-sm transition"
 							on:click={() => {
 								toggleNotificationSoundAlways();
@@ -562,11 +570,12 @@
 			{#if $user?.role === 'admin'}
 				<div>
 					<div class=" py-0.5 flex w-full justify-between">
-						<div class=" self-center text-xs">
+						<div id="toast-notifications-label" class=" self-center text-xs">
 							{$i18n.t('Toast notifications for new updates')}
 						</div>
 
 						<button
+							aria-labelledby="toast-notifications-label"
 							class="p-1 px-3 text-xs flex rounded-sm transition"
 							on:click={() => {
 								toggleShowUpdateToast();
@@ -584,11 +593,12 @@
 
 				<div>
 					<div class=" py-0.5 flex w-full justify-between">
-						<div class=" self-center text-xs">
+						<div id="whats-new-label" class=" self-center text-xs">
 							{$i18n.t(`Show "What's New" modal on login`)}
 						</div>
 
 						<button
+							aria-labelledby="whats-new-label"
 							class="p-1 px-3 text-xs flex rounded-sm transition"
 							on:click={() => {
 								toggleShowChangelog();
@@ -609,9 +619,10 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">{$i18n.t('Title Auto-Generation')}</div>
+					<div id="auto-generation-label" class=" self-center text-xs">{$i18n.t('Title Auto-Generation')}</div>
 
 					<button
+							aria-labelledby="auto-generation-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleTitleAutoGenerate();
@@ -632,6 +643,7 @@
 					<div class=" self-center text-xs">{$i18n.t('Follow-Up Auto-Generation')}</div>
 
 					<button
+							aria-labelledby="auto-generation-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleAutoFollowUps();
@@ -649,9 +661,10 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">{$i18n.t('Chat Tags Auto-Generation')}</div>
+					<div id="chat-tags-label" class=" self-center text-xs">{$i18n.t('Chat Tags Auto-Generation')}</div>
 
 					<button
+							aria-labelledby="chat-tags-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleAutoTags();
@@ -669,11 +682,13 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">
+					<div id="detect-artifacts-label" class=" self-center text-xs">
 						{$i18n.t('Detect Artifacts Automatically')}
 					</div>
 
 					<button
+							aria-labelledby="detect-artifacts-label"
+					
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleDetectArtifacts();
@@ -691,11 +706,12 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">
+					<div id="auto-copy-label" class=" self-center text-xs">
 						{$i18n.t('Auto-Copy Response to Clipboard')}
 					</div>
 
 					<button
+					aria-labelledby="auto-copy-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleResponseAutoCopy();
@@ -713,11 +729,12 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">
+					<div id="rich-input-label" class=" self-center text-xs">
 						{$i18n.t('Rich Text Input for Chat')}
 					</div>
 
 					<button
+					aria-labelledby="rich-input-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleRichTextInput();
@@ -736,11 +753,12 @@
 			{#if $config?.features?.enable_autocomplete_generation && richTextInput}
 				<div>
 					<div class=" py-0.5 flex w-full justify-between">
-						<div class=" self-center text-xs">
+						<div id="prompt-autocompletion-label" class=" self-center text-xs">
 							{$i18n.t('Prompt Autocompletion')}
 						</div>
 
 						<button
+					aria-labelledby="prompt-autocompletion-label"
 							class="p-1 px-3 text-xs flex rounded-sm transition"
 							on:click={() => {
 								togglePromptAutocomplete();
@@ -759,11 +777,12 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">
+					<div id="paste-large-label" class=" self-center text-xs">
 						{$i18n.t('Paste Large Text as File')}
 					</div>
 
 					<button
+					aria-labelledby="paste-large-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleLargeTextAsFile();
@@ -781,11 +800,12 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">
+					<div id="copy-formatted-label" class=" self-center text-xs">
 						{$i18n.t('Copy Formatted Text')}
 					</div>
 
 					<button
+					aria-labelledby="copy-formatted-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleCopyFormatted();
@@ -803,9 +823,10 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">{$i18n.t('Always Collapse Code Blocks')}</div>
+					<div id="always-collapse-label" class=" self-center text-xs">{$i18n.t('Always Collapse Code Blocks')}</div>
 
 					<button
+					aria-labelledby="always-collapse-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleCollapseCodeBlocks();
@@ -823,9 +844,10 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">{$i18n.t('Always Expand Details')}</div>
+					<div id="always-expand-label" class=" self-center text-xs">{$i18n.t('Always Expand Details')}</div>
 
 					<button
+					aria-labelledby="always-expand-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleExpandDetails();
@@ -843,11 +865,12 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">
+					<div id="chat-background-label" class=" self-center text-xs">
 						{$i18n.t('Chat Background Image')}
 					</div>
 
 					<button
+					aria-labelledby="chat-background-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							if (backgroundImageUrl !== null) {
@@ -869,10 +892,11 @@
 			</div>
 
 			<div>
-				<div class=" py-0.5 flex w-full justify-between">
+				<div id="allow-user-location-label" class=" py-0.5 flex w-full justify-between">
 					<div class=" self-center text-xs">{$i18n.t('Allow User Location')}</div>
 
 					<button
+					aria-labelledby="allow-user-location-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleUserLocation();
@@ -890,11 +914,12 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">
+					<div id="haptic-feedback-label" class=" self-center text-xs">
 						{$i18n.t('Haptic Feedback')} ({$i18n.t('Android')})
 					</div>
 
 					<button
+					aria-labelledby="haptic-feedback-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleHapticFeedback();
@@ -912,11 +937,12 @@
 
 			<!-- <div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">
+					<div id="fluidly-stream-label" class=" self-center text-xs">
 						{$i18n.t('Fluidly stream large external response chunks')}
 					</div>
 
 					<button
+					aria-labelledby="fluidly-stream-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleSplitLargeChunks();
@@ -934,11 +960,12 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">
+					<div id="enter-key-behavior-label" class=" self-center text-xs">
 						{$i18n.t('Enter Key Behavior')}
 					</div>
 
 					<button
+					aria-labelledby="enter-key-behavior-label"
 						class="p-1 px-3 text-xs flex rounded transition"
 						on:click={() => {
 							togglectrlEnterToSend();
@@ -956,11 +983,12 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">
+					<div id="scroll-on-branch-change-label" class=" self-center text-xs">
 						{$i18n.t('Scroll On Branch Change')}
 					</div>
 
 					<button
+					aria-labelledby="scroll-on-branch-change-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							togglesScrollOnBranchChange();
@@ -978,9 +1006,10 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">{$i18n.t('Web Search in Chat')}</div>
+					<div id="web-search-in-chat-label" class=" self-center text-xs">{$i18n.t('Web Search in Chat')}</div>
 
 					<button
+					aria-labelledby="web-search-in-chat-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleWebSearch();
@@ -998,9 +1027,10 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">{$i18n.t('iframe Sandbox Allow Same Origin')}</div>
+					<div id="iframe-sandbox-allow-same-origin-label" class=" self-center text-xs">{$i18n.t('iframe Sandbox Allow Same Origin')}</div>
 
 					<button
+					aria-labelledby="iframe-sandbox-allow-same-origin-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleIframeSandboxAllowSameOrigin();
@@ -1018,9 +1048,10 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">{$i18n.t('iframe Sandbox Allow Forms')}</div>
+					<div id="iframe-sandbox-allow-forms-label" class=" self-center text-xs">{$i18n.t('iframe Sandbox Allow Forms')}</div>
 
 					<button
+					aria-labelledby="iframe-sandbox-allow-forms-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleIframeSandboxAllowForms();
@@ -1038,11 +1069,12 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">
+					<div id="stylized-pdf-export-label" class=" self-center text-xs">
 						{$i18n.t('Stylized PDF Export')}
 					</div>
 
 					<button
+					aria-labelledby="stylized-pdf-export-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleStylizedPdfExport();
@@ -1065,6 +1097,7 @@
 					<div class=" self-center text-xs">{$i18n.t('Allow Voice Interruption in Call')}</div>
 
 					<button
+					aria-labelledby="allow-voice-interruption-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleVoiceInterruption();
@@ -1082,9 +1115,10 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">{$i18n.t('Display Emoji in Call')}</div>
+					<div id="display-emoji-label" class=" self-center text-xs">{$i18n.t('Display Emoji in Call')}</div>
 
 					<button
+					aria-labelledby="display-emoji-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleEmojiInCall();
@@ -1104,9 +1138,10 @@
 
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs">{$i18n.t('Image Compression')}</div>
+					<div id="image-compression-label" class=" self-center text-xs">{$i18n.t('Image Compression')}</div>
 
 					<button
+					aria-labelledby="image-compression-label"
 						class="p-1 px-3 text-xs flex rounded-sm transition"
 						on:click={() => {
 							toggleImageCompression();
@@ -1125,9 +1160,10 @@
 			{#if imageCompression}
 				<div>
 					<div class=" py-0.5 flex w-full justify-between text-xs">
-						<div class=" self-center text-xs">{$i18n.t('Image Max Compression Size')}</div>
+						<div id="image-compression-size-label" class=" self-center text-xs">{$i18n.t('Image Max Compression Size')}</div>
 
 						<div>
+							<label class="sr-only" for="image-comp-width">{$i18n.t('Image Max Compression Size width')}</label>
 							<input
 								bind:value={imageCompressionSize.width}
 								type="number"
@@ -1135,6 +1171,7 @@
 								min="0"
 								placeholder="Width"
 							/>x
+							<label class="sr-only" for="image-comp-height">{$i18n.t('Image Max Compression Size height')}</label>
 							<input
 								bind:value={imageCompressionSize.height}
 								type="number"