summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrynn Crowley <littlehill723@gmail.com>2025-02-26 21:46:37 -0800
committerGitHub <noreply@github.com>2025-02-27 16:46:37 +1100
commite02a2db3d3e523d88b352ac253dc664799939ae3 (patch)
tree68d1cc6a6d239b2313005c7b8e43c49e6cd80647
parent1cffac1d70a3eedbf7964060d6b689712b80be02 (diff)
feat(web): add new oled theme (#8838)
This adds an OLED tuned dark mode theme to the web frontend.
-rw-r--r--internal/configuration/schema/configuration.go2
-rw-r--r--internal/configuration/validator/const.go2
-rw-r--r--internal/configuration/validator/theme_test.go2
-rw-r--r--web/src/contexts/ThemeContext.tsx2
-rw-r--r--web/src/themes/Oled.ts87
-rw-r--r--web/src/themes/index.ts2
6 files changed, 94 insertions, 3 deletions
diff --git a/internal/configuration/schema/configuration.go b/internal/configuration/schema/configuration.go
index 607dbf64b..25cd85c1a 100644
--- a/internal/configuration/schema/configuration.go
+++ b/internal/configuration/schema/configuration.go
@@ -6,7 +6,7 @@ import (
// Configuration object extracted from YAML configuration file.
type Configuration struct {
- Theme string `koanf:"theme" json:"theme" jsonschema:"default=light,enum=auto,enum=light,enum=dark,enum=grey,title=Theme Name" jsonschema_description:"The name of the theme to apply to the web UI."`
+ Theme string `koanf:"theme" json:"theme" jsonschema:"default=light,enum=auto,enum=light,enum=dark,enum=grey,enum=oled,title=Theme Name" jsonschema_description:"The name of the theme to apply to the web UI."`
CertificatesDirectory string `koanf:"certificates_directory" json:"certificates_directory" jsonschema:"title=Certificates Directory Path" jsonschema_description:"The path to a directory which is used to determine the certificates that are trusted."`
Default2FAMethod string `koanf:"default_2fa_method" json:"default_2fa_method" jsonschema:"enum=totp,enum=webauthn,enum=mobile_push,title=Default 2FA method" jsonschema_description:"When a user logs in for the first time this is the 2FA method configured for them."`
diff --git a/internal/configuration/validator/const.go b/internal/configuration/validator/const.go
index 588c9d30b..7d3340d68 100644
--- a/internal/configuration/validator/const.go
+++ b/internal/configuration/validator/const.go
@@ -519,7 +519,7 @@ var (
var (
validStoragePostgreSQLSSLModes = []string{"disable", "require", "verify-ca", "verify-full"}
- validThemeNames = []string{"light", "dark", "grey", auto}
+ validThemeNames = []string{"light", "dark", "grey", "oled", auto}
validSessionSameSiteValues = []string{"none", "lax", "strict"}
validLogLevels = []string{logging.LevelTrace, logging.LevelDebug, logging.LevelInfo, logging.LevelWarn, logging.LevelError}
validLogFormats = []string{logging.FormatText, logging.FormatJSON}
diff --git a/internal/configuration/validator/theme_test.go b/internal/configuration/validator/theme_test.go
index b1c8b89bc..95cb355f9 100644
--- a/internal/configuration/validator/theme_test.go
+++ b/internal/configuration/validator/theme_test.go
@@ -36,7 +36,7 @@ func (suite *Theme) TestShouldRaiseErrorWhenInvalidThemeProvided() {
suite.Assert().Len(suite.validator.Warnings(), 0)
suite.Require().Len(suite.validator.Errors(), 1)
- suite.Assert().EqualError(suite.validator.Errors()[0], "option 'theme' must be one of 'light', 'dark', 'grey', or 'auto' but it's configured as 'invalid'")
+ suite.Assert().EqualError(suite.validator.Errors()[0], "option 'theme' must be one of 'light', 'dark', 'grey', 'oled', or 'auto' but it's configured as 'invalid'")
}
func TestThemes(t *testing.T) {
diff --git a/web/src/contexts/ThemeContext.tsx b/web/src/contexts/ThemeContext.tsx
index 5841a6b6a..862ded0c2 100644
--- a/web/src/contexts/ThemeContext.tsx
+++ b/web/src/contexts/ThemeContext.tsx
@@ -128,6 +128,8 @@ function ThemeFromName(name: string) {
return themes.Dark;
case themes.ThemeNameGrey:
return themes.Grey;
+ case themes.ThemeNameOled:
+ return themes.Oled;
case themes.ThemeNameAuto:
return window.matchMedia(MediaQueryDarkMode).matches ? themes.Dark : themes.Light;
default:
diff --git a/web/src/themes/Oled.ts b/web/src/themes/Oled.ts
new file mode 100644
index 000000000..6fec57b2b
--- /dev/null
+++ b/web/src/themes/Oled.ts
@@ -0,0 +1,87 @@
+import { createTheme } from "@mui/material/styles";
+
+const Oled = createTheme({
+ custom: {
+ icon: "#fff",
+ loadingBar: "#fff",
+ },
+ palette: {
+ mode: "dark",
+ primary: {
+ main: "#1976d2",
+ },
+ secondary: {
+ light: "#ff4081",
+ main: "#f50057",
+ dark: "#c51162",
+ contrastText: "#ffffff",
+ },
+ error: {
+ light: "#e57373",
+ main: "#f44336",
+ dark: "#d32f2f",
+ contrastText: "#ffffff",
+ },
+ warning: {
+ light: "#ffb74d",
+ main: "#ff9800",
+ dark: "#f57c00",
+ contrastText: "rgba(255, 255, 255, 0.87)",
+ },
+ info: {
+ light: "#64b5f6",
+ main: "#2196f3",
+ dark: "#1976d2",
+ contrastText: "#ffffff",
+ },
+ success: {
+ light: "#81c784",
+ main: "#4caf50",
+ dark: "#388e3c",
+ contrastText: "rgba(255, 255, 255, 0.87)",
+ },
+ grey: {
+ "50": "#fafafa",
+ "100": "#f5f5f5",
+ "200": "#eeeeee",
+ "300": "#e0e0e0",
+ "400": "#bdbdbd",
+ "500": "#9e9e9e",
+ "600": "#757575",
+ "700": "#616161",
+ "800": "#424242",
+ "900": "#212121",
+ A100: "#d5d5d5",
+ A200: "#aaaaaa",
+ A400: "#303030",
+ A700: "#616161",
+ },
+ contrastThreshold: 3,
+ tonalOffset: 0.2,
+ text: {
+ primary: "#ffffff",
+ secondary: "rgba(255, 255, 255, 0.7)",
+ disabled: "rgba(255, 255, 255, 0.5)",
+ },
+ divider: "rgba(255, 255, 255, 0.12)",
+ background: {
+ paper: "#000000",
+ default: "#000000",
+ },
+ action: {
+ active: "#ffffff",
+ hover: "rgba(255, 255, 255, 0.08)",
+ hoverOpacity: 0.08,
+ selected: "rgba(255, 255, 255, 0.16)",
+ selectedOpacity: 0.16,
+ disabled: "rgba(255, 255, 255, 0.3)",
+ disabledBackground: "rgba(255, 255, 255, 0.12)",
+ disabledOpacity: 0.38,
+ focus: "rgba(255, 255, 255, 0.12)",
+ focusOpacity: 0.12,
+ activatedOpacity: 0.24,
+ },
+ },
+});
+
+export default Oled;
diff --git a/web/src/themes/index.ts b/web/src/themes/index.ts
index d44ee18f0..4aa8644a9 100644
--- a/web/src/themes/index.ts
+++ b/web/src/themes/index.ts
@@ -27,7 +27,9 @@ export const ThemeNameAuto = "auto";
export const ThemeNameLight = "light";
export const ThemeNameDark = "dark";
export const ThemeNameGrey = "grey";
+export const ThemeNameOled = "oled";
export { default as Light } from "@themes/Light";
export { default as Dark } from "@themes/Dark";
export { default as Grey } from "@themes/Grey";
+export { default as Oled } from "@themes/Oled";