refactor(web): use ui's Select and remove old settings dropdown component (#31841)

This commit is contained in:
Mees Frensel
2026-09-28 14:12:52 -04:00
committed by GitHub
parent d73acbbfc0
commit 4d51dcafab
3 changed files with 28 additions and 145 deletions
@@ -1,65 +0,0 @@
<script lang="ts">
import Dropdown, { type RenderedOption } from '$lib/elements/Dropdown.svelte';
import type { Snippet } from 'svelte';
import { t } from 'svelte-i18n';
import { quintOut } from 'svelte/easing';
import { fly } from 'svelte/transition';
interface Props {
title: string;
subtitle?: string;
options: RenderedOption[];
selectedOption: RenderedOption;
isEdited?: boolean;
disabled?: boolean;
onToggle: (option: RenderedOption) => void;
children?: Snippet;
}
let {
title,
subtitle = '',
options,
selectedOption = $bindable(),
isEdited = false,
disabled = false,
onToggle,
children,
}: Props = $props();
</script>
<div class="flex place-items-center justify-between" class:pointer-events-none={disabled} class:opacity-50={disabled}>
<div>
<div class="flex h-6.5 place-items-center gap-1">
<label class="text-sm font-medium" for={title}>
{title}
</label>
{#if isEdited}
<div
transition:fly={{ x: 10, duration: 200, easing: quintOut }}
class="rounded-full bg-orange-100 px-2 text-[10px] text-orange-900"
>
{$t('unsaved_change')}
</div>
{/if}
</div>
<p class="text-sm dark:text-immich-dark-fg">{subtitle}</p>
{@render children?.()}
</div>
<div class="w-fit">
<Dropdown
{options}
position="bottom-right"
hideTextOnSmallScreen={false}
bind:selectedOption
render={(option) => {
return {
title: option.title,
icon: option.icon,
};
}}
onSelect={onToggle}
/>
</div>
</div>
-16
View File
@@ -1,16 +0,0 @@
<script lang="ts">
interface Props {
id: string;
label: string;
name: string;
value: string;
group?: string | undefined;
}
let { id, label, name, value, group = $bindable(undefined) }: Props = $props();
</script>
<div class="flex items-center gap-2">
<input type="radio" {name} {id} {value} class="focus-visible:ring" bind:group />
<label for={id} class="text-sm">{label}</label>
</div>
@@ -1,16 +1,6 @@
<script lang="ts">
import type { RenderedOption } from '$lib/elements/Dropdown.svelte';
import { Field, FormModal, HelperText, NumberInput, Switch } from '@immich/ui';
import {
mdiArrowDownThin,
mdiArrowUpThin,
mdiFitToPageOutline,
mdiFitToScreenOutline,
mdiPanorama,
mdiShuffle,
} from '@mdi/js';
import { Field, FormModal, HelperText, NumberInput, Select, Switch } from '@immich/ui';
import { t } from 'svelte-i18n';
import SettingDropdown from '../components/shared-components/settings/SettingDropdown.svelte';
import {
SlideshowLook,
SlideshowMetadataOverlayMode,
@@ -49,37 +39,28 @@
let tempSlideshowShowMetadataOverlay = $state($slideshowShowMetadataOverlay);
let tempSlideshowMetadataOverlayMode = $state($slideshowMetadataOverlayMode);
const navigationOptions: Record<SlideshowNavigation, RenderedOption> = {
[SlideshowNavigation.Shuffle]: { icon: mdiShuffle, title: $t('shuffle') },
[SlideshowNavigation.AscendingOrder]: { icon: mdiArrowUpThin, title: $t('backward') },
[SlideshowNavigation.DescendingOrder]: { icon: mdiArrowDownThin, title: $t('forward') },
};
const navigationOptions = [
{ value: SlideshowNavigation.Shuffle, label: $t('shuffle') },
{ value: SlideshowNavigation.AscendingOrder, label: $t('backward') },
{ value: SlideshowNavigation.DescendingOrder, label: $t('forward') },
];
const lookOptions: Record<SlideshowLook, RenderedOption> = {
[SlideshowLook.Contain]: { icon: mdiFitToScreenOutline, title: $t('contain') },
[SlideshowLook.Cover]: { icon: mdiFitToPageOutline, title: $t('cover') },
[SlideshowLook.BlurredBackground]: { icon: mdiPanorama, title: $t('blurred_background') },
};
const lookOptions = [
{ value: SlideshowLook.Contain, label: $t('contain') },
{ value: SlideshowLook.Cover, label: $t('cover') },
{ value: SlideshowLook.BlurredBackground, label: $t('blurred_background') },
];
const metadataOverlayModeOptions: Record<SlideshowMetadataOverlayMode, RenderedOption> = {
[SlideshowMetadataOverlayMode.DescriptionOnly]: {
title: $t('slideshow_metadata_overlay_mode_description_only'),
const metadataOverlayModeOptions = [
{
value: SlideshowMetadataOverlayMode.DescriptionOnly,
label: $t('slideshow_metadata_overlay_mode_description_only'),
},
[SlideshowMetadataOverlayMode.Full]: {
title: $t('slideshow_metadata_overlay_mode_full'),
{
value: SlideshowMetadataOverlayMode.Full,
label: $t('slideshow_metadata_overlay_mode_full'),
},
};
const handleToggle = <Type extends SlideshowNavigation | SlideshowLook | SlideshowMetadataOverlayMode>(
record: RenderedOption,
options: Record<Type, RenderedOption>,
): undefined | Type => {
for (const [key, option] of Object.entries(options)) {
if (option === record) {
return key as Type;
}
}
};
];
const onSubmit = () => {
$slideshowDelay = tempSlideshowDelay;
@@ -98,23 +79,13 @@
<FormModal size="small" title={$t('slideshow_settings')} {onClose} {onSubmit}>
<div class="flex flex-col gap-4">
<SettingDropdown
title={$t('direction')}
options={Object.values(navigationOptions)}
selectedOption={navigationOptions[tempSlideshowNavigation]}
onToggle={(option) => {
tempSlideshowNavigation = handleToggle(option, navigationOptions) || tempSlideshowNavigation;
}}
/>
<Field label={$t('direction')}>
<Select bind:value={tempSlideshowNavigation} options={navigationOptions} />
</Field>
<SettingDropdown
title={$t('look')}
options={Object.values(lookOptions)}
selectedOption={lookOptions[tempSlideshowLook]}
onToggle={(option) => {
tempSlideshowLook = handleToggle(option, lookOptions) || tempSlideshowLook;
}}
/>
<Field label={$t('look')}>
<Select bind:value={tempSlideshowLook} options={lookOptions} />
</Field>
<Field label={$t('autoplay_slideshow')}>
<Switch bind:checked={tempSlideshowAutoplay} />
@@ -136,16 +107,9 @@
<Switch bind:checked={tempSlideshowShowMetadataOverlay} />
</Field>
<SettingDropdown
title={$t('slideshow_metadata_overlay_mode')}
options={Object.values(metadataOverlayModeOptions)}
selectedOption={metadataOverlayModeOptions[tempSlideshowMetadataOverlayMode]}
disabled={!tempSlideshowShowMetadataOverlay}
onToggle={(option) => {
tempSlideshowMetadataOverlayMode =
handleToggle(option, metadataOverlayModeOptions) || tempSlideshowMetadataOverlayMode;
}}
/>
<Field label={$t('slideshow_metadata_overlay_mode')} disabled={!tempSlideshowShowMetadataOverlay}>
<Select bind:value={tempSlideshowMetadataOverlayMode} options={metadataOverlayModeOptions} />
</Field>
<Field label={$t('duration')}>
<NumberInput min={1} bind:value={tempSlideshowDelay} />