Simplify theme settings to a single dropdown with System, Light, and Dark options.
This commit is contained in:
parent
6fadff26c2
commit
0466e78233
7 changed files with 62 additions and 372 deletions
|
|
@ -92,12 +92,10 @@
|
||||||
|
|
||||||
"general_title": "General",
|
"general_title": "General",
|
||||||
"appearance": "Appearance",
|
"appearance": "Appearance",
|
||||||
"system_theme": "System Theme",
|
"system_theme": "System",
|
||||||
"system_theme_desc": "Choose between light and dark theme based on system preference.",
|
"theme_light": "Light",
|
||||||
"light_theme": "Light Theme:",
|
"theme_dark": "Dark",
|
||||||
"dark_theme": "Dark Theme:",
|
|
||||||
"theme": "Theme",
|
"theme": "Theme",
|
||||||
"theme_desc": "Theme to use when system theme is not enabled.",
|
|
||||||
"monochrome_mode": "Monochrome Mode",
|
"monochrome_mode": "Monochrome Mode",
|
||||||
"twitter_emoji": "Twitter Emoji",
|
"twitter_emoji": "Twitter Emoji",
|
||||||
"page_zoom": "Page Zoom",
|
"page_zoom": "Page Zoom",
|
||||||
|
|
|
||||||
|
|
@ -92,12 +92,10 @@
|
||||||
|
|
||||||
"general_title": "Общие",
|
"general_title": "Общие",
|
||||||
"appearance": "Внешний вид",
|
"appearance": "Внешний вид",
|
||||||
"system_theme": "Системная тема",
|
"system_theme": "Системная",
|
||||||
"system_theme_desc": "Выбор между светлой и тёмной темой на основе системных настроек.",
|
"theme_light": "Светлая",
|
||||||
"light_theme": "Светлая тема:",
|
"theme_dark": "Тёмная",
|
||||||
"dark_theme": "Тёмная тема:",
|
|
||||||
"theme": "Тема",
|
"theme": "Тема",
|
||||||
"theme_desc": "Тема при отключённой системной теме.",
|
|
||||||
"monochrome_mode": "Монохромный режим",
|
"monochrome_mode": "Монохромный режим",
|
||||||
"twitter_emoji": "Эмодзи Twitter",
|
"twitter_emoji": "Эмодзи Twitter",
|
||||||
"page_zoom": "Масштаб страницы",
|
"page_zoom": "Масштаб страницы",
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ import {
|
||||||
as,
|
as,
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
Chip,
|
|
||||||
config,
|
config,
|
||||||
Header,
|
Header,
|
||||||
Icon,
|
Icon,
|
||||||
|
|
@ -40,10 +39,6 @@ import { isMacOS } from '../../../utils/user-agent';
|
||||||
import {
|
import {
|
||||||
DarkTheme,
|
DarkTheme,
|
||||||
LightTheme,
|
LightTheme,
|
||||||
Theme,
|
|
||||||
ThemeKind,
|
|
||||||
useSystemThemeKind,
|
|
||||||
useThemeNames,
|
|
||||||
useThemes,
|
useThemes,
|
||||||
} from '../../../hooks/useTheme';
|
} from '../../../hooks/useTheme';
|
||||||
import { stopPropagation } from '../../../utils/keyboard';
|
import { stopPropagation } from '../../../utils/keyboard';
|
||||||
|
|
@ -52,48 +47,42 @@ import { useMessageSpacingItems } from '../../../hooks/useMessageSpacing';
|
||||||
import { useDateFormatItems } from '../../../hooks/useDateFormat';
|
import { useDateFormatItems } from '../../../hooks/useDateFormat';
|
||||||
import { SequenceCardStyle } from '../styles.css';
|
import { SequenceCardStyle } from '../styles.css';
|
||||||
|
|
||||||
type ThemeSelectorProps = {
|
const SYSTEM_THEME_ID = 'system';
|
||||||
themeNames: Record<string, string>;
|
|
||||||
themes: Theme[];
|
|
||||||
selected: Theme;
|
|
||||||
onSelect: (theme: Theme) => void;
|
|
||||||
};
|
|
||||||
const ThemeSelector = as<'div', ThemeSelectorProps>(
|
|
||||||
({ themeNames, themes, selected, onSelect, ...props }, ref) => (
|
|
||||||
<Menu {...props} ref={ref}>
|
|
||||||
<Box direction="Column" gap="100" style={{ padding: config.space.S100 }}>
|
|
||||||
{themes.map((theme) => (
|
|
||||||
<MenuItem
|
|
||||||
key={theme.id}
|
|
||||||
size="300"
|
|
||||||
variant={theme.id === selected.id ? 'Primary' : 'Surface'}
|
|
||||||
radii="300"
|
|
||||||
onClick={() => onSelect(theme)}
|
|
||||||
>
|
|
||||||
<Text size="T300">{themeNames[theme.id] ?? theme.id}</Text>
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</Box>
|
|
||||||
</Menu>
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
function SelectTheme({ disabled }: { disabled?: boolean }) {
|
const THEME_I18N_KEYS: Record<string, string> = {
|
||||||
|
[LightTheme.id]: 'Settings.theme_light',
|
||||||
|
[DarkTheme.id]: 'Settings.theme_dark',
|
||||||
|
};
|
||||||
|
|
||||||
|
function ThemeSelect() {
|
||||||
|
const { t } = useTranslation();
|
||||||
const themes = useThemes();
|
const themes = useThemes();
|
||||||
const themeNames = useThemeNames();
|
const [systemTheme, setSystemTheme] = useSetting(settingsAtom, 'useSystemTheme');
|
||||||
const [themeId, setThemeId] = useSetting(settingsAtom, 'themeId');
|
const [themeId, setThemeId] = useSetting(settingsAtom, 'themeId');
|
||||||
const [menuCords, setMenuCords] = useState<RectCords>();
|
const [menuCords, setMenuCords] = useState<RectCords>();
|
||||||
const selectedTheme = themes.find((theme) => theme.id === themeId) ?? LightTheme;
|
|
||||||
|
|
||||||
const handleThemeMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
|
const themeName = (id: string) => t(THEME_I18N_KEYS[id] ?? id);
|
||||||
|
|
||||||
|
const currentLabel = systemTheme
|
||||||
|
? t('Settings.system_theme')
|
||||||
|
: themeName(themeId ?? LightTheme.id);
|
||||||
|
|
||||||
|
const handleOpenMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
|
||||||
setMenuCords(evt.currentTarget.getBoundingClientRect());
|
setMenuCords(evt.currentTarget.getBoundingClientRect());
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleThemeSelect = (theme: Theme) => {
|
const handleSelect = (id: string) => {
|
||||||
setThemeId(theme.id);
|
if (id === SYSTEM_THEME_ID) {
|
||||||
|
setSystemTheme(true);
|
||||||
|
} else {
|
||||||
|
setSystemTheme(false);
|
||||||
|
setThemeId(id);
|
||||||
|
}
|
||||||
setMenuCords(undefined);
|
setMenuCords(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const selectedId = systemTheme ? SYSTEM_THEME_ID : (themeId ?? LightTheme.id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
|
|
@ -103,10 +92,9 @@ function SelectTheme({ disabled }: { disabled?: boolean }) {
|
||||||
fill="Soft"
|
fill="Soft"
|
||||||
radii="300"
|
radii="300"
|
||||||
after={<Icon size="300" src={Icons.ChevronBottom} />}
|
after={<Icon size="300" src={Icons.ChevronBottom} />}
|
||||||
onClick={disabled ? undefined : handleThemeMenu}
|
onClick={handleOpenMenu}
|
||||||
aria-disabled={disabled}
|
|
||||||
>
|
>
|
||||||
<Text size="T300">{themeNames[selectedTheme.id] ?? selectedTheme.id}</Text>
|
<Text size="T300">{currentLabel}</Text>
|
||||||
</Button>
|
</Button>
|
||||||
<PopOut
|
<PopOut
|
||||||
anchor={menuCords}
|
anchor={menuCords}
|
||||||
|
|
@ -126,12 +114,29 @@ function SelectTheme({ disabled }: { disabled?: boolean }) {
|
||||||
escapeDeactivates: stopPropagation,
|
escapeDeactivates: stopPropagation,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ThemeSelector
|
<Menu>
|
||||||
themeNames={themeNames}
|
<Box direction="Column" gap="100" style={{ padding: config.space.S100 }}>
|
||||||
themes={themes}
|
<MenuItem
|
||||||
selected={selectedTheme}
|
size="300"
|
||||||
onSelect={handleThemeSelect}
|
variant={selectedId === SYSTEM_THEME_ID ? 'Primary' : 'Surface'}
|
||||||
/>
|
radii="300"
|
||||||
|
onClick={() => handleSelect(SYSTEM_THEME_ID)}
|
||||||
|
>
|
||||||
|
<Text size="T300">{t('Settings.system_theme')}</Text>
|
||||||
|
</MenuItem>
|
||||||
|
{themes.map((theme) => (
|
||||||
|
<MenuItem
|
||||||
|
key={theme.id}
|
||||||
|
size="300"
|
||||||
|
variant={selectedId === theme.id ? 'Primary' : 'Surface'}
|
||||||
|
radii="300"
|
||||||
|
onClick={() => handleSelect(theme.id)}
|
||||||
|
>
|
||||||
|
<Text size="T300">{themeName(theme.id)}</Text>
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
</Menu>
|
||||||
</FocusTrap>
|
</FocusTrap>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
@ -139,128 +144,6 @@ function SelectTheme({ disabled }: { disabled?: boolean }) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SystemThemePreferences() {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const themeKind = useSystemThemeKind();
|
|
||||||
const themeNames = useThemeNames();
|
|
||||||
const themes = useThemes();
|
|
||||||
const [lightThemeId, setLightThemeId] = useSetting(settingsAtom, 'lightThemeId');
|
|
||||||
const [darkThemeId, setDarkThemeId] = useSetting(settingsAtom, 'darkThemeId');
|
|
||||||
|
|
||||||
const lightThemes = themes.filter((theme) => theme.kind === ThemeKind.Light);
|
|
||||||
const darkThemes = themes.filter((theme) => theme.kind === ThemeKind.Dark);
|
|
||||||
|
|
||||||
const selectedLightTheme = lightThemes.find((theme) => theme.id === lightThemeId) ?? LightTheme;
|
|
||||||
const selectedDarkTheme = darkThemes.find((theme) => theme.id === darkThemeId) ?? DarkTheme;
|
|
||||||
|
|
||||||
const [ltCords, setLTCords] = useState<RectCords>();
|
|
||||||
const [dtCords, setDTCords] = useState<RectCords>();
|
|
||||||
|
|
||||||
const handleLightThemeMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
|
|
||||||
setLTCords(evt.currentTarget.getBoundingClientRect());
|
|
||||||
};
|
|
||||||
const handleDarkThemeMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
|
|
||||||
setDTCords(evt.currentTarget.getBoundingClientRect());
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleLightThemeSelect = (theme: Theme) => {
|
|
||||||
setLightThemeId(theme.id);
|
|
||||||
setLTCords(undefined);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDarkThemeSelect = (theme: Theme) => {
|
|
||||||
setDarkThemeId(theme.id);
|
|
||||||
setDTCords(undefined);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box wrap="Wrap" gap="400">
|
|
||||||
<SettingTile
|
|
||||||
title={t('Settings.light_theme')}
|
|
||||||
after={
|
|
||||||
<Chip
|
|
||||||
variant={themeKind === ThemeKind.Light ? 'Primary' : 'Secondary'}
|
|
||||||
outlined={themeKind === ThemeKind.Light}
|
|
||||||
radii="Pill"
|
|
||||||
after={<Icon size="200" src={Icons.ChevronBottom} />}
|
|
||||||
onClick={handleLightThemeMenu}
|
|
||||||
>
|
|
||||||
<Text size="B300">{themeNames[selectedLightTheme.id] ?? selectedLightTheme.id}</Text>
|
|
||||||
</Chip>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<PopOut
|
|
||||||
anchor={ltCords}
|
|
||||||
offset={5}
|
|
||||||
position="Bottom"
|
|
||||||
align="End"
|
|
||||||
content={
|
|
||||||
<FocusTrap
|
|
||||||
focusTrapOptions={{
|
|
||||||
initialFocus: false,
|
|
||||||
onDeactivate: () => setLTCords(undefined),
|
|
||||||
clickOutsideDeactivates: true,
|
|
||||||
isKeyForward: (evt: KeyboardEvent) =>
|
|
||||||
evt.key === 'ArrowDown' || evt.key === 'ArrowRight',
|
|
||||||
isKeyBackward: (evt: KeyboardEvent) =>
|
|
||||||
evt.key === 'ArrowUp' || evt.key === 'ArrowLeft',
|
|
||||||
escapeDeactivates: stopPropagation,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ThemeSelector
|
|
||||||
themeNames={themeNames}
|
|
||||||
themes={lightThemes}
|
|
||||||
selected={selectedLightTheme}
|
|
||||||
onSelect={handleLightThemeSelect}
|
|
||||||
/>
|
|
||||||
</FocusTrap>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<SettingTile
|
|
||||||
title={t('Settings.dark_theme')}
|
|
||||||
after={
|
|
||||||
<Chip
|
|
||||||
variant={themeKind === ThemeKind.Dark ? 'Primary' : 'Secondary'}
|
|
||||||
outlined={themeKind === ThemeKind.Dark}
|
|
||||||
radii="Pill"
|
|
||||||
after={<Icon size="200" src={Icons.ChevronBottom} />}
|
|
||||||
onClick={handleDarkThemeMenu}
|
|
||||||
>
|
|
||||||
<Text size="B300">{themeNames[selectedDarkTheme.id] ?? selectedDarkTheme.id}</Text>
|
|
||||||
</Chip>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<PopOut
|
|
||||||
anchor={dtCords}
|
|
||||||
offset={5}
|
|
||||||
position="Bottom"
|
|
||||||
align="End"
|
|
||||||
content={
|
|
||||||
<FocusTrap
|
|
||||||
focusTrapOptions={{
|
|
||||||
initialFocus: false,
|
|
||||||
onDeactivate: () => setDTCords(undefined),
|
|
||||||
clickOutsideDeactivates: true,
|
|
||||||
isKeyForward: (evt: KeyboardEvent) =>
|
|
||||||
evt.key === 'ArrowDown' || evt.key === 'ArrowRight',
|
|
||||||
isKeyBackward: (evt: KeyboardEvent) =>
|
|
||||||
evt.key === 'ArrowUp' || evt.key === 'ArrowLeft',
|
|
||||||
escapeDeactivates: stopPropagation,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ThemeSelector
|
|
||||||
themeNames={themeNames}
|
|
||||||
themes={darkThemes}
|
|
||||||
selected={selectedDarkTheme}
|
|
||||||
onSelect={handleDarkThemeSelect}
|
|
||||||
/>
|
|
||||||
</FocusTrap>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function PageZoomInput() {
|
function PageZoomInput() {
|
||||||
const [pageZoom, setPageZoom] = useSetting(settingsAtom, 'pageZoom');
|
const [pageZoom, setPageZoom] = useSetting(settingsAtom, 'pageZoom');
|
||||||
const [currentZoom, setCurrentZoom] = useState(`${pageZoom}`);
|
const [currentZoom, setCurrentZoom] = useState(`${pageZoom}`);
|
||||||
|
|
@ -307,32 +190,16 @@ function PageZoomInput() {
|
||||||
|
|
||||||
function Appearance() {
|
function Appearance() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [systemTheme, setSystemTheme] = useSetting(settingsAtom, 'useSystemTheme');
|
|
||||||
const [monochromeMode, setMonochromeMode] = useSetting(settingsAtom, 'monochromeMode');
|
const [monochromeMode, setMonochromeMode] = useSetting(settingsAtom, 'monochromeMode');
|
||||||
const [twitterEmoji, setTwitterEmoji] = useSetting(settingsAtom, 'twitterEmoji');
|
const [twitterEmoji, setTwitterEmoji] = useSetting(settingsAtom, 'twitterEmoji');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box direction="Column" gap="100">
|
<Box direction="Column" gap="100">
|
||||||
<Text size="L400">{t('Settings.appearance')}</Text>
|
<Text size="L400">{t('Settings.appearance')}</Text>
|
||||||
<SequenceCard
|
|
||||||
className={SequenceCardStyle}
|
|
||||||
variant="SurfaceVariant"
|
|
||||||
direction="Column"
|
|
||||||
gap="400"
|
|
||||||
>
|
|
||||||
<SettingTile
|
|
||||||
title={t('Settings.system_theme')}
|
|
||||||
description={t('Settings.system_theme_desc')}
|
|
||||||
after={<Switch variant="Primary" value={systemTheme} onChange={setSystemTheme} />}
|
|
||||||
/>
|
|
||||||
{systemTheme && <SystemThemePreferences />}
|
|
||||||
</SequenceCard>
|
|
||||||
|
|
||||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||||
<SettingTile
|
<SettingTile
|
||||||
title={t('Settings.theme')}
|
title={t('Settings.theme')}
|
||||||
description={t('Settings.theme_desc')}
|
after={<ThemeSelect />}
|
||||||
after={<SelectTheme disabled={systemTheme} />}
|
|
||||||
/>
|
/>
|
||||||
</SequenceCard>
|
</SequenceCard>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { lightTheme } from 'folds';
|
import { lightTheme } from 'folds';
|
||||||
import { createContext, useContext, useEffect, useMemo, useState } from 'react';
|
import { createContext, useContext, useEffect, useMemo, useState } from 'react';
|
||||||
import { onDarkFontWeight, onLightFontWeight } from '../../config.css';
|
import { onDarkFontWeight, onLightFontWeight } from '../../config.css';
|
||||||
import { butterTheme, darkTheme, silverTheme } from '../../colors.css';
|
import { darkTheme } from '../../colors.css';
|
||||||
import { settingsAtom } from '../state/settings';
|
import { settingsAtom } from '../state/settings';
|
||||||
import { useSetting } from '../state/hooks/settings';
|
import { useSetting } from '../state/hooks/settings';
|
||||||
|
|
||||||
|
|
@ -22,39 +22,18 @@ export const LightTheme: Theme = {
|
||||||
classNames: [lightTheme, onLightFontWeight, 'prism-light'],
|
classNames: [lightTheme, onLightFontWeight, 'prism-light'],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SilverTheme: Theme = {
|
|
||||||
id: 'silver-theme',
|
|
||||||
kind: ThemeKind.Light,
|
|
||||||
classNames: ['silver-theme', silverTheme, onLightFontWeight, 'prism-light'],
|
|
||||||
};
|
|
||||||
export const DarkTheme: Theme = {
|
export const DarkTheme: Theme = {
|
||||||
id: 'dark-theme',
|
id: 'dark-theme',
|
||||||
kind: ThemeKind.Dark,
|
kind: ThemeKind.Dark,
|
||||||
classNames: ['dark-theme', darkTheme, onDarkFontWeight, 'prism-dark'],
|
classNames: ['dark-theme', darkTheme, onDarkFontWeight, 'prism-dark'],
|
||||||
};
|
};
|
||||||
export const ButterTheme: Theme = {
|
|
||||||
id: 'butter-theme',
|
|
||||||
kind: ThemeKind.Dark,
|
|
||||||
classNames: ['butter-theme', butterTheme, onDarkFontWeight, 'prism-dark'],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useThemes = (): Theme[] => {
|
export const useThemes = (): Theme[] => {
|
||||||
const themes: Theme[] = useMemo(() => [LightTheme, SilverTheme, DarkTheme, ButterTheme], []);
|
const themes: Theme[] = useMemo(() => [LightTheme, DarkTheme], []);
|
||||||
|
|
||||||
return themes;
|
return themes;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useThemeNames = (): Record<string, string> =>
|
|
||||||
useMemo(
|
|
||||||
() => ({
|
|
||||||
[LightTheme.id]: 'Light',
|
|
||||||
[SilverTheme.id]: 'Silver',
|
|
||||||
[DarkTheme.id]: 'Dark',
|
|
||||||
[ButterTheme.id]: 'Butter',
|
|
||||||
}),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
export const useSystemThemeKind = (): ThemeKind => {
|
export const useSystemThemeKind = (): ThemeKind => {
|
||||||
const darkModeQueryList = useMemo(() => window.matchMedia('(prefers-color-scheme: dark)'), []);
|
const darkModeQueryList = useMemo(() => window.matchMedia('(prefers-color-scheme: dark)'), []);
|
||||||
const [themeKind, setThemeKind] = useState<ThemeKind>(
|
const [themeKind, setThemeKind] = useState<ThemeKind>(
|
||||||
|
|
@ -77,24 +56,14 @@ export const useSystemThemeKind = (): ThemeKind => {
|
||||||
|
|
||||||
export const useActiveTheme = (): Theme => {
|
export const useActiveTheme = (): Theme => {
|
||||||
const systemThemeKind = useSystemThemeKind();
|
const systemThemeKind = useSystemThemeKind();
|
||||||
const themes = useThemes();
|
|
||||||
const [systemTheme] = useSetting(settingsAtom, 'useSystemTheme');
|
const [systemTheme] = useSetting(settingsAtom, 'useSystemTheme');
|
||||||
const [themeId] = useSetting(settingsAtom, 'themeId');
|
const [themeId] = useSetting(settingsAtom, 'themeId');
|
||||||
const [lightThemeId] = useSetting(settingsAtom, 'lightThemeId');
|
|
||||||
const [darkThemeId] = useSetting(settingsAtom, 'darkThemeId');
|
|
||||||
|
|
||||||
if (!systemTheme) {
|
if (!systemTheme) {
|
||||||
const selectedTheme = themes.find((theme) => theme.id === themeId) ?? LightTheme;
|
return themeId === DarkTheme.id ? DarkTheme : LightTheme;
|
||||||
|
|
||||||
return selectedTheme;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedTheme =
|
return systemThemeKind === ThemeKind.Dark ? DarkTheme : LightTheme;
|
||||||
systemThemeKind === ThemeKind.Dark
|
|
||||||
? themes.find((theme) => theme.id === darkThemeId) ?? DarkTheme
|
|
||||||
: themes.find((theme) => theme.id === lightThemeId) ?? LightTheme;
|
|
||||||
|
|
||||||
return selectedTheme;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const ThemeContext = createContext<Theme | null>(null);
|
const ThemeContext = createContext<Theme | null>(null);
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,6 @@ export enum MessageLayout {
|
||||||
export interface Settings {
|
export interface Settings {
|
||||||
themeId?: string;
|
themeId?: string;
|
||||||
useSystemTheme: boolean;
|
useSystemTheme: boolean;
|
||||||
lightThemeId?: string;
|
|
||||||
darkThemeId?: string;
|
|
||||||
monochromeMode?: boolean;
|
monochromeMode?: boolean;
|
||||||
isMarkdown: boolean;
|
isMarkdown: boolean;
|
||||||
editorToolbar: boolean;
|
editorToolbar: boolean;
|
||||||
|
|
@ -51,8 +49,6 @@ export interface Settings {
|
||||||
const defaultSettings: Settings = {
|
const defaultSettings: Settings = {
|
||||||
themeId: undefined,
|
themeId: undefined,
|
||||||
useSystemTheme: true,
|
useSystemTheme: true,
|
||||||
lightThemeId: undefined,
|
|
||||||
darkThemeId: undefined,
|
|
||||||
monochromeMode: false,
|
monochromeMode: false,
|
||||||
isMarkdown: true,
|
isMarkdown: true,
|
||||||
editorToolbar: false,
|
editorToolbar: false,
|
||||||
|
|
|
||||||
|
|
@ -5,103 +5,6 @@ import { color } from 'folds';
|
||||||
const navDark = '#121314'; // левая панель (навигация)
|
const navDark = '#121314'; // левая панель (навигация)
|
||||||
const contentDark = '#0d0d0e'; // правая часть (контент/чат)
|
const contentDark = '#0d0d0e'; // правая часть (контент/чат)
|
||||||
|
|
||||||
export const silverTheme = createTheme(color, {
|
|
||||||
Background: {
|
|
||||||
Container: '#DEDEDE',
|
|
||||||
ContainerHover: '#D3D3D3',
|
|
||||||
ContainerActive: '#C7C7C7',
|
|
||||||
ContainerLine: '#BBBBBB',
|
|
||||||
OnContainer: '#000000',
|
|
||||||
},
|
|
||||||
|
|
||||||
Surface: {
|
|
||||||
Container: '#EAEAEA',
|
|
||||||
ContainerHover: '#DEDEDE',
|
|
||||||
ContainerActive: '#D3D3D3',
|
|
||||||
ContainerLine: '#C7C7C7',
|
|
||||||
OnContainer: '#000000',
|
|
||||||
},
|
|
||||||
|
|
||||||
SurfaceVariant: {
|
|
||||||
Container: '#DEDEDE',
|
|
||||||
ContainerHover: '#D3D3D3',
|
|
||||||
ContainerActive: '#C7C7C7',
|
|
||||||
ContainerLine: '#BBBBBB',
|
|
||||||
OnContainer: '#000000',
|
|
||||||
},
|
|
||||||
|
|
||||||
Primary: {
|
|
||||||
Main: '#1245A8',
|
|
||||||
MainHover: '#103E97',
|
|
||||||
MainActive: '#0F3B8F',
|
|
||||||
MainLine: '#0E3786',
|
|
||||||
OnMain: '#FFFFFF',
|
|
||||||
Container: '#C4D0E9',
|
|
||||||
ContainerHover: '#B8C7E5',
|
|
||||||
ContainerActive: '#ACBEE1',
|
|
||||||
ContainerLine: '#A0B5DC',
|
|
||||||
OnContainer: '#0D3076',
|
|
||||||
},
|
|
||||||
|
|
||||||
Secondary: {
|
|
||||||
Main: '#000000',
|
|
||||||
MainHover: '#171717',
|
|
||||||
MainActive: '#232323',
|
|
||||||
MainLine: '#2F2F2F',
|
|
||||||
OnMain: '#EAEAEA',
|
|
||||||
Container: '#C7C7C7',
|
|
||||||
ContainerHover: '#BBBBBB',
|
|
||||||
ContainerActive: '#AFAFAF',
|
|
||||||
ContainerLine: '#A4A4A4',
|
|
||||||
OnContainer: '#0C0C0C',
|
|
||||||
},
|
|
||||||
|
|
||||||
Success: {
|
|
||||||
Main: '#017343',
|
|
||||||
MainHover: '#01683C',
|
|
||||||
MainActive: '#016239',
|
|
||||||
MainLine: '#015C36',
|
|
||||||
OnMain: '#FFFFFF',
|
|
||||||
Container: '#BFDCD0',
|
|
||||||
ContainerHover: '#B3D5C7',
|
|
||||||
ContainerActive: '#A6CEBD',
|
|
||||||
ContainerLine: '#99C7B4',
|
|
||||||
OnContainer: '#01512F',
|
|
||||||
},
|
|
||||||
|
|
||||||
Warning: {
|
|
||||||
Main: '#864300',
|
|
||||||
MainHover: '#793C00',
|
|
||||||
MainActive: '#723900',
|
|
||||||
MainLine: '#6B3600',
|
|
||||||
OnMain: '#FFFFFF',
|
|
||||||
Container: '#E1D0BF',
|
|
||||||
ContainerHover: '#DBC7B2',
|
|
||||||
ContainerActive: '#D5BDA6',
|
|
||||||
ContainerLine: '#CFB499',
|
|
||||||
OnContainer: '#5E2F00',
|
|
||||||
},
|
|
||||||
|
|
||||||
Critical: {
|
|
||||||
Main: '#9D0F0F',
|
|
||||||
MainHover: '#8D0E0E',
|
|
||||||
MainActive: '#850D0D',
|
|
||||||
MainLine: '#7E0C0C',
|
|
||||||
OnMain: '#FFFFFF',
|
|
||||||
Container: '#E7C3C3',
|
|
||||||
ContainerHover: '#E2B7B7',
|
|
||||||
ContainerActive: '#DDABAB',
|
|
||||||
ContainerLine: '#D89F9F',
|
|
||||||
OnContainer: '#6E0B0B',
|
|
||||||
},
|
|
||||||
|
|
||||||
Other: {
|
|
||||||
FocusRing: 'rgba(0 0 0 / 50%)',
|
|
||||||
Shadow: 'rgba(0 0 0 / 20%)',
|
|
||||||
Overlay: 'rgba(0 0 0 / 50%)',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const darkThemeData = {
|
const darkThemeData = {
|
||||||
Background: {
|
Background: {
|
||||||
Container: navDark,
|
Container: navDark,
|
||||||
|
|
@ -200,43 +103,3 @@ const darkThemeData = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const darkTheme = createTheme(color, darkThemeData);
|
export const darkTheme = createTheme(color, darkThemeData);
|
||||||
|
|
||||||
export const butterTheme = createTheme(color, {
|
|
||||||
...darkThemeData,
|
|
||||||
Background: {
|
|
||||||
Container: '#1A1916',
|
|
||||||
ContainerHover: '#262621',
|
|
||||||
ContainerActive: '#33322C',
|
|
||||||
ContainerLine: '#403F38',
|
|
||||||
OnContainer: '#FFFBDE',
|
|
||||||
},
|
|
||||||
|
|
||||||
Surface: {
|
|
||||||
Container: '#262621',
|
|
||||||
ContainerHover: '#33322C',
|
|
||||||
ContainerActive: '#403F38',
|
|
||||||
ContainerLine: '#4D4B43',
|
|
||||||
OnContainer: '#FFFBDE',
|
|
||||||
},
|
|
||||||
|
|
||||||
SurfaceVariant: {
|
|
||||||
Container: '#33322C',
|
|
||||||
ContainerHover: '#403F38',
|
|
||||||
ContainerActive: '#4D4B43',
|
|
||||||
ContainerLine: '#59584E',
|
|
||||||
OnContainer: '#FFFBDE',
|
|
||||||
},
|
|
||||||
|
|
||||||
Secondary: {
|
|
||||||
Main: '#FFFBDE',
|
|
||||||
MainHover: '#E5E2C8',
|
|
||||||
MainActive: '#D9D5BD',
|
|
||||||
MainLine: '#CCC9B2',
|
|
||||||
OnMain: '#1A1916',
|
|
||||||
Container: '#403F38',
|
|
||||||
ContainerHover: '#4D4B43',
|
|
||||||
ContainerActive: '#59584E',
|
|
||||||
ContainerLine: '#666459',
|
|
||||||
OnContainer: '#F2EED3',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,7 @@
|
||||||
--font-secondary: 'InterVariable', var(--font-emoji), sans-serif;
|
--font-secondary: 'InterVariable', var(--font-emoji), sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-theme,
|
.dark-theme {
|
||||||
.butter-theme {
|
|
||||||
--tc-link: hsl(213deg 100% 80%);
|
--tc-link: hsl(213deg 100% 80%);
|
||||||
|
|
||||||
--mx-uc-1: hsl(208, 100%, 75%);
|
--mx-uc-1: hsl(208, 100%, 75%);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue