Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions gui/public/i18n/en/translation.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,8 @@ settings-interface-appearance-decorations = Use the system native decorations
settings-interface-appearance-decorations-description = This will not render the top bar of the interface and will use the operating system's instead.
settings-interface-appearance-decorations-label = Use native decorations

settings-interface-appearance-hue = Hue

## Notification settings
settings-interface-notifications = Notifications
settings-general-interface-serial_detection = Serial device detection
Expand Down
2 changes: 2 additions & 0 deletions gui/src/AppLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useLayoutEffect } from 'react';
import { useConfig } from './hooks/config';
import { Outlet, useNavigate } from 'react-router-dom';
import { applyColors } from './components/commons/CustomThemeColors';

export function AppLayout() {
const { config } = useConfig();
Expand All @@ -10,6 +11,7 @@ export function AppLayout() {
if (!config) return;
if (config.theme !== undefined) {
document.documentElement.dataset.theme = config.theme;
applyColors(config.theme, config.customHue);
}

if (config.fonts !== undefined) {
Expand Down
117 changes: 117 additions & 0 deletions gui/src/components/commons/CustomThemeColors.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
function hsvToRGB(h: number, s: number, v: number): [number, number, number] {
let r = 0,
g = 0,
b = 0;
const i = Math.floor(h * 6);
const f = h * 6 - i;
const p = v * (1 - s);
const q = v * (1 - f * s);
const t = v * (1 - (1 - f) * s);
switch (i % 6) {
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}

export function applyColors(theme: string, hue: number) {
if (theme == 'custom-bright') {
document.documentElement.style.setProperty(
'--background-20',
hsvToRGB(hue, 0.06, 0.91).join(',')
);
document.documentElement.style.setProperty(
'--background-30',
hsvToRGB(hue, 0.06, 0.83).join(',')
);
document.documentElement.style.setProperty(
'--background-40',
hsvToRGB(hue, 0.1, 0.61).join(',')
);
document.documentElement.style.setProperty(
'--background-50',
hsvToRGB(hue, 0.21, 0.38).join(',')
);
document.documentElement.style.setProperty(
'--background-60',
hsvToRGB(hue, 0.25, 0.28).join(',')
);
document.documentElement.style.setProperty(
'--background-70',
hsvToRGB(hue, 0.27, 0.22).join(',')
);
document.documentElement.style.setProperty(
'--background-80',
hsvToRGB(hue, 0.29, 0.15).join(',')
);
} else {
document.documentElement.style.setProperty('--background-20', null);
document.documentElement.style.setProperty('--background-30', null);
document.documentElement.style.setProperty('--background-40', null);
document.documentElement.style.setProperty('--background-50', null);
document.documentElement.style.setProperty('--background-60', null);
document.documentElement.style.setProperty('--background-70', null);
document.documentElement.style.setProperty('--background-80', null);
}
if (theme == 'custom-bright' || theme == 'custom-dark') {
document.documentElement.style.setProperty(
'--accent-background-10',
hsvToRGB(hue, 0.2, 1).join(',')
);
document.documentElement.style.setProperty(
'--accent-background-20',
hsvToRGB(hue, 0.51, 0.92).join(',')
);
document.documentElement.style.setProperty(
'--accent-background-30',
hsvToRGB(hue, 0.62, 0.72).join(',')
);
document.documentElement.style.setProperty(
'--accent-background-40',
hsvToRGB(hue, 0.62, 0.56).join(',')
);
document.documentElement.style.setProperty(
'--accent-background-50',
hsvToRGB(hue, 0.7, 0.36).join(',')
);
document.documentElement.style.setProperty(
'--window-icon-stroke',
hsvToRGB(hue, 0.43, 0.92).join(',')
);
} else {
document.documentElement.style.setProperty('--accent-background-10', null);
document.documentElement.style.setProperty('--accent-background-20', null);
document.documentElement.style.setProperty('--accent-background-30', null);
document.documentElement.style.setProperty('--accent-background-40', null);
document.documentElement.style.setProperty('--accent-background-50', null);
document.documentElement.style.setProperty('--window-icon-stroke', null);
}
}
39 changes: 39 additions & 0 deletions gui/src/components/settings/pages/InterfaceSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ interface InterfaceSettingsForm {
textSize: number;
fonts: string;
decorations: boolean;
customHue: number;
};
behavior: {
devmode: boolean;
Expand Down Expand Up @@ -55,6 +56,7 @@ export function InterfaceSettings() {
textSize: config?.textSize ?? defaultConfig.textSize,
fonts: config?.fonts.join(',') ?? defaultConfig.fonts.join(','),
decorations: config?.decorations ?? defaultConfig.decorations,
customHue: config?.customHue ?? defaultConfig.customHue,
},
notifications: {
watchNewDevices:
Expand Down Expand Up @@ -112,6 +114,7 @@ export function InterfaceSettings() {
fonts: values.appearance.fonts.split(','),
textSize: values.appearance.textSize,
decorations: values.appearance.decorations,
customHue: values.appearance.customHue,

useTray: values.behavior.useTray,
discordPresence: values.behavior.discordPresence,
Expand Down Expand Up @@ -470,9 +473,45 @@ export function InterfaceSettings() {
value={'snep'}
colors="!bg-snep"
/>
<ThemeSelector
control={control}
name="appearance.theme"
value={'custom-bright'}
colors="!bg-custom-bright"
/>
<ThemeSelector
control={control}
name="appearance.theme"
value={'custom-dark'}
colors="!bg-custom-dark"
/>
</div>
</div>

<div className="pb-4">
<Typography variant="section-title">
{l10n.getString('settings-interface-appearance-hue')}
</Typography>
</div>
<div className="grid sm:grid-cols-2 pb-4">
<Range
control={control}
name="appearance.customHue"
min={0}
max={1}
step={0.01}
values={[
{ value: 0, label: '0°' },
{ value: 0.5, label: '180°' },
{ value: 1, label: '360°' },
]}
disabled={
config?.theme != 'custom-bright' &&
config?.theme != 'custom-dark'
}
/>
</div>

<Typography variant="section-title">
{l10n.getString('settings-interface-appearance-font')}
</Typography>
Expand Down
2 changes: 2 additions & 0 deletions gui/src/hooks/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export interface Config {
homeLayout: 'default' | 'table';
skeletonPreview: boolean;
lastUsedProportions: 'manual' | 'autobone' | 'scaled' | null;
customHue: number;
}

export interface ConfigContext {
Expand Down Expand Up @@ -82,6 +83,7 @@ export const defaultConfig: Config = {
homeLayout: 'default',
skeletonPreview: true,
lastUsedProportions: null,
customHue: 0.8,
};

interface CrossStorage {
Expand Down
31 changes: 31 additions & 0 deletions gui/src/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,37 @@ body {
--default-color: 255, 255, 255;
}

:root[data-theme='custom-bright'] {
--background-10: 255, 255, 255;
--background-90: 0, 0, 0;

--success: 139, 223, 35;
--warning: 255, 187, 62;
--critical: 223, 54, 84;
--special: 230, 0, 230;

--default-color: 255, 255, 255;
}

:root[data-theme='custom-dark'] {
--background-10: 255, 255, 255;
--background-20: 230, 230, 230;
--background-30: 200, 200, 200;
--background-40: 120, 120, 120;
--background-50: 90, 90, 90;
--background-60: 60, 60, 60;
--background-70: 30, 30, 30;
--background-80: 15, 15, 15;
--background-90: 0, 0, 0;

--success: 139, 223, 35;
--warning: 255, 187, 62;
--critical: 223, 54, 84;
--special: 230, 0, 230;

--default-color: 255, 255, 255;
}

#root {
height: 100%;
}
Expand Down
2 changes: 2 additions & 0 deletions gui/tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,8 @@ const config = {
'trans-flag': `linear-gradient(135deg, ${colors['trans-blue'][800]} 40%, ${colors['trans-blue'][700]} 40% 70%, ${colors['trans-blue'][600]} 70% 100%)`,
'asexual-flag': `linear-gradient(135deg, ${colors['asexual'][100]} 30%, ${colors['asexual'][200]} 30% 50%, ${colors['asexual'][300]} 50% 70%, ${colors['asexual'][400]} 70% 100%)`,
'snep': `linear-gradient(135deg, ${colors['snep'][100]} 40%, ${colors['snep'][200]} 40% 70%, ${colors['snep'][300]} 70% 100%)`,
'custom-bright': `linear-gradient(135deg, ${colors['red-accent'][100]} 30%, ${colors['orange-accent'][100]} 30% 43.3%, ${colors['yellow-accent'][100]} 43.3% 56.7%, ${colors['green-accent'][100]} 56.7% 70%, ${colors['blue-gray'][300]} 70% 100%)`,
'custom-dark': `linear-gradient(135deg, ${colors['red-accent'][700]} 30%, ${colors['orange-accent'][700]} 30% 43.3%, ${colors['yellow-accent'][700]} 43.3% 56.7%, ${colors['green-accent'][700]} 56.7% 70%, ${colors['blue-gray'][700]} 70% 100%)`,
},
animation: {
'spin-ccw': 'spin-ccw 1s linear infinite',
Expand Down