From 1c05791f70a3655efc61ad8817e7c7091eeacb80 Mon Sep 17 00:00:00 2001 From: LynithDev <61880709+LynithDev@users.noreply.github.com> Date: Sat, 21 Dec 2024 14:42:00 +0100 Subject: [PATCH] fix: Theming adjustments and incorrect color fixes --- apps/frontend/src/assets/logos/curseforge.svg | 4 +- apps/frontend/src/index.tsx | 2 +- apps/frontend/src/styles/globals.scss | 4 + .../{themes.scss => themes/_OneLauncher.scss} | 14 +-- apps/frontend/src/styles/themes/_helpers.scss | 14 +++ apps/frontend/src/styles/themes/index.scss | 1 + .../ui/components/base/SelectList.module.scss | 2 +- .../ui/components/content/LauncherIcon.tsx | 2 +- .../src/ui/components/game/LoaderIcon.tsx | 12 ++- .../overlay/cluster/ClusterCreationModal.tsx | 8 +- apps/frontend/src/ui/hooks/useSettings.tsx | 5 +- apps/frontend/src/ui/pages/Home.tsx | 8 +- .../settings/launcher/SettingsAppearance.tsx | 32 ++++--- apps/frontend/src/utils/theming.ts | 96 ++++++++++--------- 14 files changed, 122 insertions(+), 82 deletions(-) rename apps/frontend/src/styles/{themes.scss => themes/_OneLauncher.scss} (93%) create mode 100644 apps/frontend/src/styles/themes/_helpers.scss create mode 100644 apps/frontend/src/styles/themes/index.scss diff --git a/apps/frontend/src/assets/logos/curseforge.svg b/apps/frontend/src/assets/logos/curseforge.svg index aace1835..7d2e9bd9 100644 --- a/apps/frontend/src/assets/logos/curseforge.svg +++ b/apps/frontend/src/assets/logos/curseforge.svg @@ -1,3 +1,3 @@ - - \ No newline at end of file + + diff --git a/apps/frontend/src/index.tsx b/apps/frontend/src/index.tsx index c3431115..bc6c3260 100644 --- a/apps/frontend/src/index.tsx +++ b/apps/frontend/src/index.tsx @@ -10,7 +10,7 @@ import '@fontsource/poppins/600.css'; import 'virtual:uno.css'; import '@unocss/reset/tailwind.css'; import 'overlayscrollbars/overlayscrollbars.css'; -import '~styles/themes.scss'; +import '~styles/themes/index.scss'; import '~styles/globals.scss'; import '~styles/highlightjs.css'; diff --git a/apps/frontend/src/styles/globals.scss b/apps/frontend/src/styles/globals.scss index 21a43bb3..39dbf65d 100644 --- a/apps/frontend/src/styles/globals.scss +++ b/apps/frontend/src/styles/globals.scss @@ -1,3 +1,7 @@ +html, body, :root { + @apply bg-page; +} + body { @apply font-sans text-fg-primary text-md; } diff --git a/apps/frontend/src/styles/themes.scss b/apps/frontend/src/styles/themes/_OneLauncher.scss similarity index 93% rename from apps/frontend/src/styles/themes.scss rename to apps/frontend/src/styles/themes/_OneLauncher.scss index bc83c016..e308fb8e 100644 --- a/apps/frontend/src/styles/themes.scss +++ b/apps/frontend/src/styles/themes/_OneLauncher.scss @@ -1,12 +1,9 @@ -@mixin define-theme($name, $selectors: "") { - $selector: "#{$selectors} [data-theme="#{$name}"], .theme-#{$name}"; +@use "_helpers.scss" as * with ( + $name: "OneLauncher" +); - #{$selector} { - @content; - } -} +@include variant("Dark", ":root,") { -@include define-theme("dark", ":root,") { --clr-white: 255, 255, 255; --clr-black: 0, 0, 0; @@ -65,7 +62,7 @@ --clr-secondary: 25, 32, 38; } -@include define-theme("light") { +@include variant("Light") { --clr-white: 255, 255, 255; --clr-black: 0, 0, 0; @@ -122,5 +119,4 @@ --clr-page-pressed: 230, 230, 230; --clr-secondary: 220, 220, 220; - } diff --git a/apps/frontend/src/styles/themes/_helpers.scss b/apps/frontend/src/styles/themes/_helpers.scss new file mode 100644 index 00000000..95c153ee --- /dev/null +++ b/apps/frontend/src/styles/themes/_helpers.scss @@ -0,0 +1,14 @@ +$name: "UNSET" !default; + +@mixin variant($variant, $selectors: "") { + #{$selectors} [data-theme="#{$name}-#{$variant}"], .theme-#{$name}-#{$variant} { + @content; + } +} + +@mixin extends-variant($variant, $extends, $selectors: "") { + #{$selectors} [data-theme="#{$name}-#{$variant}"], .theme-#{$name}-#{$variant} { + @extend [data-theme="#{$name}-#{$extends}"], .theme-#{$name}-#{$extends}; + @content; + } +} diff --git a/apps/frontend/src/styles/themes/index.scss b/apps/frontend/src/styles/themes/index.scss new file mode 100644 index 00000000..8381c093 --- /dev/null +++ b/apps/frontend/src/styles/themes/index.scss @@ -0,0 +1 @@ +@use "OneLauncher"; diff --git a/apps/frontend/src/ui/components/base/SelectList.module.scss b/apps/frontend/src/ui/components/base/SelectList.module.scss index 6cfe4197..99847c3e 100644 --- a/apps/frontend/src/ui/components/base/SelectList.module.scss +++ b/apps/frontend/src/ui/components/base/SelectList.module.scss @@ -6,7 +6,7 @@ @apply [&:nth-child(even)]:bg-white/01 hover:bg-component-bg-hover active:bg-component-bg-pressed; &.selected { - @apply bg-white/10; + @apply bg-border/10; } } } diff --git a/apps/frontend/src/ui/components/content/LauncherIcon.tsx b/apps/frontend/src/ui/components/content/LauncherIcon.tsx index c78f77ce..d30bbacb 100644 --- a/apps/frontend/src/ui/components/content/LauncherIcon.tsx +++ b/apps/frontend/src/ui/components/content/LauncherIcon.tsx @@ -7,8 +7,8 @@ import MultiMCImage from '~assets/logos/launchers/multimc.png'; import PrismIcon from '~assets/logos/launchers/prismlauncher.svg?component-solid'; import TechnicImage from '~assets/logos/launchers/technic.png'; import TLauncherImage from '~assets/logos/launchers/tlauncher.png'; -import ModrinthIcon from '~assets/logos/modrinth.svg?component-solid'; import UnknownImage from '~assets/logos/minecraft.png'; +import ModrinthIcon from '~assets/logos/modrinth.svg?component-solid'; import { type JSX, type JSXElement, Show, splitProps } from 'solid-js'; type ElementType = (props: any) => JSXElement; diff --git a/apps/frontend/src/ui/components/game/LoaderIcon.tsx b/apps/frontend/src/ui/components/game/LoaderIcon.tsx index acb2f7af..77c7a3f1 100644 --- a/apps/frontend/src/ui/components/game/LoaderIcon.tsx +++ b/apps/frontend/src/ui/components/game/LoaderIcon.tsx @@ -27,8 +27,18 @@ type LoaderIconProp = JSX.HTMLAttributes & { function LoaderIcon(props: LoaderIconProp) { const [{ loader = 'vanilla' }, rest] = splitProps(props, ['loader']); + + const isMonochrome = () => loader === 'forge'; + return ( - + ); } diff --git a/apps/frontend/src/ui/components/overlay/cluster/ClusterCreationModal.tsx b/apps/frontend/src/ui/components/overlay/cluster/ClusterCreationModal.tsx index 66ed658d..4d0c54c8 100644 --- a/apps/frontend/src/ui/components/overlay/cluster/ClusterCreationModal.tsx +++ b/apps/frontend/src/ui/components/overlay/cluster/ClusterCreationModal.tsx @@ -167,17 +167,17 @@ export function createClusterStep(props: CreateClusterStepType): () => JSX.Eleme return ( - + - + - New Cluster - {props.message} + New Cluster + {props.message} diff --git a/apps/frontend/src/ui/hooks/useSettings.tsx b/apps/frontend/src/ui/hooks/useSettings.tsx index 633af419..bf50136b 100644 --- a/apps/frontend/src/ui/hooks/useSettings.tsx +++ b/apps/frontend/src/ui/hooks/useSettings.tsx @@ -2,6 +2,7 @@ import type { Settings } from '@onelauncher/client/bindings'; import { getProgramInfo } from '@onelauncher/client'; import { useBeforeLeave } from '@solidjs/router'; import { bridge } from '~imports'; +import { DEFAULT_THEME, setAppTheme, splitMergedTheme } from '~utils/theming'; import { type Context, createContext, createEffect, type ParentProps, Show, useContext } from 'solid-js'; import useCommand from './useCommand'; @@ -10,7 +11,9 @@ import useCommand from './useCommand'; */ export function syncSettings(settings: Settings) { document.body.classList.toggle('reduce-motion', settings.disable_animations); - document.body.setAttribute('data-theme', settings.theme ?? 'dark'); + + const split = splitMergedTheme(settings.theme || DEFAULT_THEME); + setAppTheme(split.theme, split.variant); } interface SettingsControllerType { diff --git a/apps/frontend/src/ui/pages/Home.tsx b/apps/frontend/src/ui/pages/Home.tsx index f2db3f61..affe94d8 100644 --- a/apps/frontend/src/ui/pages/Home.tsx +++ b/apps/frontend/src/ui/pages/Home.tsx @@ -108,7 +108,7 @@ function Banner() { const navigate = useNavigate(); return ( - + - - + + {cluster()?.meta.name || 'Create a cluster'} @@ -152,7 +152,7 @@ function Banner() { } - class="bg-op-10!" + class="theme-OneLauncher-Dark bg-op-10!" onClick={() => ClusterRoot.open(navigate, cluster()!.uuid)} /> diff --git a/apps/frontend/src/ui/pages/settings/launcher/SettingsAppearance.tsx b/apps/frontend/src/ui/pages/settings/launcher/SettingsAppearance.tsx index 20734bae..8b34a603 100644 --- a/apps/frontend/src/ui/pages/settings/launcher/SettingsAppearance.tsx +++ b/apps/frontend/src/ui/pages/settings/launcher/SettingsAppearance.tsx @@ -9,18 +9,19 @@ import Sidebar from '~ui/components/Sidebar'; import useSettings from '~ui/hooks/useSettings'; import { upperFirst } from '~utils'; import { BROWSER_VIEWS } from '~utils/browser'; -import { THEMES } from '~utils/theming'; +import { DEFAULT_THEME, setAppTheme, splitMergedTheme, THEMES } from '~utils/theming'; import { createEffect, createSignal, For } from 'solid-js'; import SettingsRow from '../../../components/SettingsRow'; function SettingsAppearance() { const { settings, saveOnLeave } = useSettings(); const [shouldReload, setShouldReload] = createSignal(false); - const [theme, setTheme] = createSignal(settings().theme); + const [theme, setTheme] = createSignal(settings().theme ?? DEFAULT_THEME); createEffect(() => { document.body.classList.add('theme-transition'); - document.body.setAttribute('data-theme', theme() ?? 'dark'); + const split = splitMergedTheme(theme()); + setAppTheme(split.theme, split.variant); setTimeout(() => document.body.classList.remove('theme-transition'), 300); }); @@ -39,7 +40,7 @@ function SettingsAppearance() { saveOnLeave(() => ({ disable_animations: settings().disable_animations!, custom_frame: settings().custom_frame!, - theme: theme() ?? 'dark', + theme: theme(), })); return ( @@ -47,11 +48,18 @@ function SettingsAppearance() { Appearance - + - + {theme => ( - + + {variant => ( + + )} + )} @@ -118,13 +126,13 @@ function SettingsAppearance() { export default SettingsAppearance; interface ThemeCardProps { - theme: string; - setTheme: (theme: string) => void; + themeSelector: string; + setTheme: (merged: string) => void; }; function ThemeCard(props: ThemeCardProps) { return ( - props.setTheme(props.theme)}> + props.setTheme(props.themeSelector)}> @@ -139,12 +147,12 @@ function ThemeCard(props: ThemeCardProps) { } interface PrimaryThemeCardProps { - theme: string | undefined; + merged: string; } function PrimaryThemeCard(props: PrimaryThemeCardProps) { return ( - + diff --git a/apps/frontend/src/utils/theming.ts b/apps/frontend/src/utils/theming.ts index 0ec7b4cd..86ea63ee 100644 --- a/apps/frontend/src/utils/theming.ts +++ b/apps/frontend/src/utils/theming.ts @@ -1,48 +1,52 @@ // When adding a theme, make sure to add the theme here and define the colors in the CSS file! -export const THEMES = ['dark', 'light'] as const; +export const DEFAULT_THEME = 'OneLauncher-Dark'; +export const THEMES = { + OneLauncher: { + variants: [ + { + name: 'Dark', + type: 'dark', + }, + { + name: 'Light', + type: 'light', + }, + ], + }, +} as const satisfies Record; -export const THEMABLE_PROPERTIES = [ - 'clr-white', - 'clr-black', - 'clr-fg-primary', - 'clr-fg-primary-hover', - 'clr-fg-primary-pressed', - 'clr-fg-primary-disabled', - 'clr-fg-secondary', - 'clr-fg-secondary-hover', - 'clr-fg-secondary-pressed', - 'clr-fg-secondary-disabled', - 'clr-brand', - 'clr-brand-hover', - 'clr-brand-pressed', - 'clr-brand-disabled', - 'clr-onbrand', - 'clr-onbrand-hover', - 'clr-onbrand-pressed', - 'clr-onbrand-disabled', - 'clr-danger', - 'clr-danger-hover', - 'clr-danger-pressed', - 'clr-danger-disabled', - 'clr-success', - 'clr-success-hover', - 'clr-success-pressed', - 'clr-success-disabled', - 'clr-component-bg', - 'clr-component-bg-hover', - 'clr-component-bg-pressed', - 'clr-component-bg-disabled', - 'clr-code-info', - 'clr-code-warn', - 'clr-code-error', - 'clr-code-debug', - 'clr-code-trace', - 'clr-link', - 'clr-link-hover', - 'clr-link-pressed', - 'clr-link-disabled', - 'clr-page', - 'clr-page-elevated', - 'clr-page-pressed', - 'clr-secondary', -] as const; +export function setAppTheme(name: string, variant: ThemeVariant) { + document.body.setAttribute('data-theme', `${name}-${variant.name}`); + document.body.setAttribute('data-theme-type', variant.type); +} + +export function splitMergedTheme(merged: string): { + theme: keyof typeof THEMES; + variant: ThemeVariant; +} { + const [name, ...variants] = merged.split('-'); + + const foundVariant = THEMES[name as keyof typeof THEMES].variants.find(variant => variant.name === variants.join('-')); + + if (!name || !foundVariant) + return { + theme: 'OneLauncher', + variant: THEMES.OneLauncher.variants[0], + }; + + return { + theme: name as keyof typeof THEMES, + variant: foundVariant, + }; +} + +export interface Theme { + variants: ThemeVariant[]; +} + +export type ThemeTypes = 'dark' | 'light'; + +export interface ThemeVariant { + type: ThemeTypes; + name: string; +};
@@ -152,7 +152,7 @@ function Banner() { } - class="bg-op-10!" + class="theme-OneLauncher-Dark bg-op-10!" onClick={() => ClusterRoot.open(navigate, cluster()!.uuid)} />