web/settings: convert LanguageDropdown to universal SettingsDropdown

This commit is contained in:
wukko 2024-10-28 21:42:07 +06:00
parent 17c020fe22
commit 3a0b0fed8b
No known key found for this signature in database
GPG key ID: 3E30B3F26C7B4AA2
3 changed files with 69 additions and 39 deletions

View file

@ -39,16 +39,14 @@
updateSetting({ updateSetting({
[settingContext]: { [settingContext]: {
[settingId]: !isEnabled, [settingId]: !isEnabled,
}, }
})} })
}
> >
<h4 class="toggle-title">{title}</h4> <h4 class="toggle-title">{title}</h4>
<Toggle enabled={isEnabled} /> <Toggle enabled={isEnabled} />
</button> </button>
<!--
description is repeated here because there may be several toggles per settings category,
and each of them needs its own description. this is intended. don't "clean it up".
-->
{#if description} {#if description}
<div class="subtext toggle-description">{description}</div> <div class="subtext toggle-description">{description}</div>
{/if} {/if}

View file

@ -1,57 +1,69 @@
<script lang="ts"> <script
import languages from "$i18n/languages.json"; lang="ts"
generics="
import { t, locales } from "$lib/i18n/translations"; Context extends Exclude<keyof CobaltSettings, 'schemaVersion'>,
import settings, { updateSetting } from "$lib/state/settings"; Id extends keyof CobaltSettings[Context]
"
>
import { updateSetting } from "$lib/state/settings";
import type { CobaltSettings } from "$lib/types/settings";
import IconSelector from "@tabler/icons-svelte/IconSelector.svelte"; import IconSelector from "@tabler/icons-svelte/IconSelector.svelte";
$: currentSetting = $settings.appearance.language; export let title: string;
$: disabled = $settings.appearance.autoLanguage; export let description: string = "";
export let items: Record<string, string>;
const updateLocale = (event: Event) => { export let settingId: Id;
const target = event.target as HTMLSelectElement; export let settingContext: Context;
export let selectedOption: string;
export let selectedTitle: string;
export let disabled = false;
const onChange = (event: Event) => {
const target = event.target as HTMLSelectElement;
updateSetting({ updateSetting({
appearance: { [settingContext]: {
language: target.value as keyof typeof languages, [settingId]: target.value,
}, },
}); });
}; };
</script> </script>
<div class="language-selector-parent" class:disabled aria-hidden={disabled}> <div class="selector-parent" class:disabled aria-hidden={disabled}>
<div id="language-selector" class="selector button"> <div id="selector" class="selector button">
<div class="selector-info"> <div class="selector-info">
<h4 class="selector-title"> <h4 class="selector-title">
{$t("settings.language.preferred.title")} {title}
</h4> </h4>
<div class="right-side"> <div class="right-side">
<span class="selector-current" aria-hidden="true"> <span class="selector-current" aria-hidden="true">
{$t(`languages.${currentSetting}`)} {selectedTitle}
</span> </span>
<IconSelector /> <IconSelector />
</div> </div>
</div> </div>
<select
id="setting-dropdown-appearance-language" <select on:change={e => onChange(e)} {disabled}>
on:change={updateLocale} {#each Object.keys(items) as value}
{disabled} <option {value} selected={selectedOption === value}>
> {items[value]}
{#each $locales as value}
<option {value} selected={currentSetting === value}>
{$t(`languages.${value}`)}
</option> </option>
{/each} {/each}
</select> </select>
</div> </div>
<div class="subtext toggle-description">
{$t("settings.language.preferred.description")} {#if description}
</div> <div class="subtext">
{description}
</div>
{/if}
</div> </div>
<style> <style>
.language-selector-parent { .selector-parent {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 10px; gap: 10px;
@ -59,11 +71,11 @@
transition: opacity 0.2s; transition: opacity 0.2s;
} }
.language-selector-parent.disabled { .selector-parent.disabled {
opacity: 0.5; opacity: 0.5;
} }
#language-selector { #selector {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
@ -76,7 +88,7 @@
overflow: scroll; overflow: scroll;
} }
.disabled #language-selector { .disabled #selector {
pointer-events: none; pointer-events: none;
} }

View file

@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import { t } from "$lib/i18n/translations"; import { t, locales } from "$lib/i18n/translations";
import settings from "$lib/state/settings";
import { themeOptions } from "$lib/types/settings"; import { themeOptions } from "$lib/types/settings";
@ -7,7 +8,16 @@
import SettingsButton from "$components/buttons/SettingsButton.svelte"; import SettingsButton from "$components/buttons/SettingsButton.svelte";
import SettingsToggle from "$components/buttons/SettingsToggle.svelte"; import SettingsToggle from "$components/buttons/SettingsToggle.svelte";
import SettingsCategory from "$components/settings/SettingsCategory.svelte"; import SettingsCategory from "$components/settings/SettingsCategory.svelte";
import LanguageDropdown from "$components/settings/LanguageDropdown.svelte"; import SettingsDropdown from "$components/settings/SettingsDropdown.svelte";
const dropdownItems = () => {
return $locales.reduce((obj, lang) => {
return {
...obj,
[lang]: $t(`languages.${lang}`),
};
}, {});
};
</script> </script>
<SettingsCategory sectionId="theme" title={$t("settings.theme")}> <SettingsCategory sectionId="theme" title={$t("settings.theme")}>
@ -31,7 +41,17 @@
title={$t("settings.language.auto.title")} title={$t("settings.language.auto.title")}
description={$t("settings.language.auto.description")} description={$t("settings.language.auto.description")}
/> />
<LanguageDropdown />
<SettingsDropdown
title={$t("settings.language.preferred.title")}
description={$t("settings.language.preferred.description")}
items={dropdownItems()}
settingContext="appearance"
settingId="language"
selectedOption={$settings.appearance.language}
selectedTitle={$t(`languages.${$settings.appearance.language}`)}
disabled={$settings.appearance.autoLanguage}
/>
</SettingsCategory> </SettingsCategory>
<SettingsCategory <SettingsCategory