fix: make switch labels properly clickable (#25898)

This commit is contained in:
Michel Heusschen 2026-02-05 12:09:27 +01:00 committed by GitHub
parent fdf06a91cc
commit e97030a7ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 53 additions and 13 deletions

35
pnpm-lock.yaml generated
View File

@ -741,8 +741,8 @@ importers:
specifier: file:../open-api/typescript-sdk
version: link:../open-api/typescript-sdk
'@immich/ui':
specifier: ^0.59.0
version: 0.59.0(@sveltejs/kit@2.49.5(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.48.0)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.48.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.48.0)
specifier: ^0.61.3
version: 0.61.3(@sveltejs/kit@2.49.5(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.48.0)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.48.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.48.0)
'@mapbox/mapbox-gl-rtl-text':
specifier: 0.2.3
version: 0.2.3(mapbox-gl@1.13.3)
@ -3126,13 +3126,13 @@ packages:
'@immich/justified-layout-wasm@0.4.3':
resolution: {integrity: sha512-fpcQ7zPhP3Cp1bEXhONVYSUeIANa2uzaQFGKufUZQo5FO7aFT77szTVChhlCy4XaVy5R4ZvgSkA/1TJmeORz7Q==}
'@immich/svelte-markdown-preprocess@0.1.0':
resolution: {integrity: sha512-jgSOJEGLPKEXQCNRI4r4YUayeM2b0ZYLdzgKGl891jZBhOQIetlY7rU44kPpV1AA3/8wGDwNFKduIQZZ/qJYzg==}
'@immich/svelte-markdown-preprocess@0.2.1':
resolution: {integrity: sha512-mbr/g75lO8Zh+ELCuYrZP0XB4gf2UbK8rJcGYMYxFJJzMMunV+sm9FqtV1dbwW2dpXzCZGz1XPCEZ6oo526TbA==}
peerDependencies:
svelte: ^5.0.0
'@immich/ui@0.59.0':
resolution: {integrity: sha512-7yxvyhhd99T0AHhjMakp7c/U4n0jGAmRO5xpncsRASRvqZve/LAibjr6N5FJc5IAd222DROTMLn6imsxVfqfvg==}
'@immich/ui@0.61.3':
resolution: {integrity: sha512-9cz/7kc/CSmJ37gH5nIZNiHxw5OlBCGbdlSGkCOtaMJ458wmcdUFVmF5arjGioaOa4NMwseOVyln7rMhkNU7ww==}
peerDependencies:
svelte: ^5.0.0
@ -7802,6 +7802,9 @@ packages:
resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
engines: {node: '>= 0.8'}
front-matter@4.0.2:
resolution: {integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==}
fs-constants@1.0.0:
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
@ -9081,6 +9084,11 @@ packages:
engines: {node: '>= 20'}
hasBin: true
marked@17.0.1:
resolution: {integrity: sha512-boeBdiS0ghpWcSwoNm/jJBwdpFaMnZWRzjA6SkUMYb40SVaN1x7mmfGKp0jvexGcx+7y2La5zRZsYFZI6Qpypg==}
engines: {node: '>= 20'}
hasBin: true
math-intrinsics@1.1.0:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
@ -15747,13 +15755,16 @@ snapshots:
'@immich/justified-layout-wasm@0.4.3': {}
'@immich/svelte-markdown-preprocess@0.1.0(svelte@5.48.0)':
'@immich/svelte-markdown-preprocess@0.2.1(svelte@5.48.0)':
dependencies:
front-matter: 4.0.2
marked: 17.0.1
node-emoji: 2.2.0
svelte: 5.48.0
'@immich/ui@0.59.0(@sveltejs/kit@2.49.5(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.48.0)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.48.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.48.0)':
'@immich/ui@0.61.3(@sveltejs/kit@2.49.5(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.48.0)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.48.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.48.0)':
dependencies:
'@immich/svelte-markdown-preprocess': 0.1.0(svelte@5.48.0)
'@immich/svelte-markdown-preprocess': 0.2.1(svelte@5.48.0)
'@internationalized/date': 3.10.0
'@mdi/js': 7.4.47
bits-ui: 2.14.4(@internationalized/date@3.10.0)(@sveltejs/kit@2.49.5(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.48.0)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.48.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.48.0)
@ -21100,6 +21111,10 @@ snapshots:
fresh@2.0.0: {}
front-matter@4.0.2:
dependencies:
js-yaml: 3.14.2
fs-constants@1.0.0: {}
fs-extra@10.1.0:
@ -22570,6 +22585,8 @@ snapshots:
marked@16.4.2: {}
marked@17.0.1: {}
math-intrinsics@1.1.0: {}
mdast-util-directive@3.1.0:

View File

@ -27,7 +27,7 @@
"@formatjs/icu-messageformat-parser": "^3.0.0",
"@immich/justified-layout-wasm": "^0.4.3",
"@immich/sdk": "file:../open-api/typescript-sdk",
"@immich/ui": "^0.59.0",
"@immich/ui": "^0.61.3",
"@mapbox/mapbox-gl-rtl-text": "0.2.3",
"@mdi/js": "^7.4.47",
"@photo-sphere-viewer/core": "^5.14.0",

View File

@ -0,0 +1,23 @@
import { render } from '@testing-library/svelte';
import SettingSwitch from './setting-switch.svelte';
describe('SettingSwitch component', () => {
it('links switch and subtitle ids on the switch', () => {
const { getByText } = render(SettingSwitch, {
props: {
title: 'Enable feature',
subtitle: 'Controls the feature state.',
},
});
const label = getByText('Enable feature') as HTMLLabelElement;
const subtitle = getByText('Controls the feature state.');
const subtitleId = subtitle.getAttribute('id');
const switchElement = document.querySelector(`#${label.htmlFor}`);
expect(subtitleId).not.toBeNull();
expect(label.htmlFor).not.toBe('');
expect(switchElement).not.toBeNull();
expect(switchElement?.getAttribute('aria-describedby')).toBe(subtitleId);
});
});

View File

@ -28,14 +28,14 @@
let id: string = generateId();
let sliderId = $derived(`${id}-slider`);
let switchId = $derived(`input-${id}`);
let subtitleId = $derived(subtitle ? `${id}-subtitle` : undefined);
</script>
<div class="flex place-items-center justify-between">
<div class="me-2">
<div class="flex h-6.5 place-items-center gap-1">
<label class="font-medium text-primary text-sm" for={sliderId}>
<label class="font-medium text-primary text-sm" for={switchId}>
{title}
</label>
{#if isEdited}
@ -54,5 +54,5 @@
{@render children?.()}
</div>
<Switch id={sliderId} bind:checked {disabled} onCheckedChange={onToggle} aria-describedby={subtitleId} />
<Switch {id} bind:checked {disabled} onCheckedChange={onToggle} aria-describedby={subtitleId} />
</div>