implement theme setting

This commit is contained in:
marlon-erler
2026-04-09 18:09:26 +00:00
parent 2f0082708e
commit 5e8c609268
12 changed files with 380 additions and 182 deletions
+21
View File
@@ -0,0 +1,21 @@
import * as React from "bloatless-react";
export function OptionButton<T>(
text: string,
value: T,
selection: React.State<T>,
) {
function select() {
selection.value = value;
}
const isSelected = React.createProxyState(
[selection],
() => selection.value == value,
);
return (
<button class="standard" toggle:selected={isSelected} on:click={select}>
{text}
</button>
);
}
+19
View File
@@ -0,0 +1,19 @@
import * as React from "bloatless-react";
import { OptionButton } from "./optionButton";
export function OptionButtonList<T>(
options: React.ListState<[string, T]>,
selection: React.State<T>,
) {
function OptionToView(option: [string, T]) {
const [text, value] = option;
return OptionButton(text, value, selection);
}
return (
<div
class="flex-column gap"
children:append={[options, OptionToView]}
></div>
);
}
+37 -4
View File
@@ -8,7 +8,9 @@ import { SplitModal } from "../Components/splitModal";
import { InfoTile } from "../Components/infoTile";
import { Option } from "../Components/option";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { Languages } from "../../Model/Global/settingsModel";
import { Languages, ThemeSettings } from "../../Model/Global/settingsModel";
import { OptionButtonList } from "../Components/optionButtonList";
import { stringify } from "../../Model/Utility/utility";
export function SettingsModal(
coreViewModel: CoreViewModel,
@@ -19,7 +21,10 @@ export function SettingsModal(
() => {
switch (settingsViewModel.selectedModalPage.value) {
case SettingsModalPages.Appearance:
return <div>Appearance</div>;
return SettingsAppearancePane(
coreViewModel,
settingsViewModel,
);
case SettingsModalPages.Regional:
return SettingsRegionalPane(
coreViewModel,
@@ -161,8 +166,7 @@ function SettingsRegionalPane(
Option(
languageNames[language],
language,
language ==
settingsViewModel.language.value,
language == settingsViewModel.language.value,
),
)}
</select>
@@ -172,3 +176,32 @@ function SettingsRegionalPane(
</div>
);
}
function SettingsAppearancePane(
coreViewModel: CoreViewModel,
settingsViewModel: SettingsViewModel,
) {
return (
<div class="slide-up">
<h2>{coreViewModel.translations.settings.pages.appearance}</h2>
<hr></hr>
{OptionButtonList(
new React.ListState<[string, ThemeSettings]>([
[
coreViewModel.translations.settings.themes.dark,
ThemeSettings.Dark,
],
[
coreViewModel.translations.settings.themes.light,
ThemeSettings.Light,
],
[
coreViewModel.translations.settings.themes.system,
ThemeSettings.System,
],
]),
settingsViewModel.theme,
)}
</div>
);
}
+17 -2
View File
@@ -80,6 +80,11 @@ const englishTranslations = {
regional: "Language & Region",
info: "About Comms",
},
themes: {
dark: "Dark",
light: "Light",
system: "Device theme",
},
version: "Version",
language: "Language",
@@ -375,6 +380,11 @@ export const allTranslations: {
regional: "Sprache & Region",
info: "Über Comms",
},
themes: {
dark: "Dunkel",
light: "Hell",
system: "Geräteeinstellung",
},
version: "Version",
language: "Sprache",
@@ -639,6 +649,11 @@ export const allTranslations: {
regional: "Idioma y Región",
info: "Sobre Comms",
},
themes: {
dark: "Oscuro",
light: "Claro",
system: "Según dispositivo",
},
version: "Versión",
language: "Idioma",
@@ -832,6 +847,6 @@ export const languageNames = {
en: "English",
de: "Deutsch",
es: "Español",
}
};
export type Translations = typeof englishTranslations;
export type Translations = typeof englishTranslations;