fix: Theming adjustments and incorrect color fixes

This commit is contained in:
LynithDev 2024-12-21 14:42:00 +01:00
parent 334885af77
commit 1c05791f70
14 changed files with 122 additions and 82 deletions

View file

@ -1,3 +1,3 @@
<svg width="252" height="161" viewBox="0 0 252 161" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M192.422 50.7705C192.422 50.7705 243.874 42.6221 252 18.8572H173.181V0H0L21.3339 24.8619V50.3349C21.3339 50.3349 75.1642 47.5237 95.9867 63.3816C124.489 89.9139 63.9294 125.779 63.9294 125.779L53.5449 160.291C69.7837 144.762 100.733 124.673 157.478 125.641C135.884 132.495 114.171 143.201 97.2667 160.291H211.977L201.175 125.779C201.175 125.779 118.036 76.5444 192.422 50.7736V50.7705Z" fill="white"/>
</svg>
<path d="M192.422 50.7705C192.422 50.7705 243.874 42.6221 252 18.8572H173.181V0H0L21.3339 24.8619V50.3349C21.3339 50.3349 75.1642 47.5237 95.9867 63.3816C124.489 89.9139 63.9294 125.779 63.9294 125.779L53.5449 160.291C69.7837 144.762 100.733 124.673 157.478 125.641C135.884 132.495 114.171 143.201 97.2667 160.291H211.977L201.175 125.779C201.175 125.779 118.036 76.5444 192.422 50.7736V50.7705Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 521 B

After

Width:  |  Height:  |  Size: 529 B

View file

@ -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';

View file

@ -1,3 +1,7 @@
html, body, :root {
@apply bg-page;
}
body {
@apply font-sans text-fg-primary text-md;
}

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -0,0 +1 @@
@use "OneLauncher";

View file

@ -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;
}
}
}

View file

@ -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;

View file

@ -27,8 +27,18 @@ type LoaderIconProp = JSX.HTMLAttributes<HTMLImageElement> & {
function LoaderIcon(props: LoaderIconProp) {
const [{ loader = 'vanilla' }, rest] = splitProps(props, ['loader']);
const isMonochrome = () => loader === 'forge';
return (
<img {...rest} alt={`${loader}'s logo`} src={getLoaderLogoSrc(loader)} />
<img
{...rest}
alt={`${loader}'s logo`}
classList={{
'filter-brightness-0': isMonochrome() && document.body.getAttribute('data-theme-type') === 'light',
}}
src={getLoaderLogoSrc(loader)}
/>
);
}

View file

@ -167,17 +167,17 @@ export function createClusterStep(props: CreateClusterStepType): () => JSX.Eleme
return (
<div class="min-w-sm flex flex-col rounded-lg bg-page text-center">
<div class="relative h-25 flex">
<div class="theme-OneLauncher-Dark relative h-25 flex">
<div class="absolute left-0 top-0 h-full w-full">
<img alt="Header Image" class="h-full w-full rounded-t-lg" src={HeaderImage} />
</div>
<div
class="absolute left-0 top-0 h-full flex flex-row items-center justify-start gap-x-4 bg-[radial-gradient(at_center,#00000077,transparent)] px-10"
>
<Server01Icon class="h-8 w-8" />
<Server01Icon class="h-8 w-8 text-fg-primary" />
<div class="flex flex-col items-start justify-center">
<h1 class="h-10 -mt-2">New Cluster</h1>
<span>{props.message}</span>
<h1 class="h-10 text-fg-primary -mt-2">New Cluster</h1>
<span class="text-fg-primary">{props.message}</span>
</div>
</div>
</div>

View file

@ -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 {

View file

@ -108,7 +108,7 @@ function Banner() {
const navigate = useNavigate();
return (
<div class="theme-dark relative h-52 min-h-52 w-full overflow-hidden rounded-xl">
<div class="relative h-52 min-h-52 w-full overflow-hidden rounded-xl">
<ClusterCover
class="absolute h-52 w-full rounded-xl object-cover"
cluster={cluster()}
@ -120,8 +120,8 @@ function Banner() {
}}
/>
<div class="relative z-10 h-full flex flex-col items-start justify-between px-8 py-6 text-fg-primary">
<div class="flex flex-col gap-y-2">
<div class="relative z-10 h-full flex flex-col items-start justify-between px-8 py-6">
<div class="theme-OneLauncher-Dark flex flex-col gap-y-2 text-fg-primary">
<h1>{cluster()?.meta.name || 'Create a cluster'}</h1>
<Show when={cluster() !== undefined}>
<p>
@ -152,7 +152,7 @@ function Banner() {
<Button
buttonStyle="iconSecondary"
children={<Settings01Icon />}
class="bg-op-10!"
class="theme-OneLauncher-Dark bg-op-10!"
onClick={() => ClusterRoot.open(navigate, cluster()!.uuid)}
/>
</Show>

View file

@ -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() {
<h1>Appearance</h1>
<ScrollableContainer>
<div class="flex flex-row items-center gap-4">
<PrimaryThemeCard theme={theme()} />
<PrimaryThemeCard merged={theme()} />
<div class="grid grid-cols-3 h-full gap-4">
<For each={THEMES}>
<For each={Object.keys(THEMES) as (keyof typeof THEMES)[]}>
{theme => (
<ThemeCard setTheme={setTheme} theme={theme} />
<For each={THEMES[theme].variants}>
{variant => (
<ThemeCard
setTheme={setTheme}
themeSelector={`${theme}-${variant.name}`}
/>
)}
</For>
)}
</For>
</div>
@ -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 (
<div class={`theme-${props.theme}`} onClick={() => props.setTheme(props.theme)}>
<div class={`theme-${props.themeSelector}`} onClick={() => props.setTheme(props.themeSelector)}>
<svg fill="none" height="78" viewBox="0 0 126 78" width="126" xmlns="http://www.w3.org/2000/svg">
<rect fill="rgb(var(--clr-page))" height="78" rx="8" width="126" />
<rect height="77" rx="7.5" stroke="rgb(var(--clr-border))" stroke-opacity="0.1" width="125" x="0.5" y="0.5" />
@ -139,12 +147,12 @@ function ThemeCard(props: ThemeCardProps) {
}
interface PrimaryThemeCardProps {
theme: string | undefined;
merged: string;
}
function PrimaryThemeCard(props: PrimaryThemeCardProps) {
return (
<div class={`theme-${props.theme ?? 'dark'}`}>
<div class={`theme-${props.merged}`}>
<svg fill="none" height="183" viewBox="0 0 296 183" width="296" xmlns="http://www.w3.org/2000/svg">
<rect fill="rgb(var(--clr-page))" height="183" rx="16" width="296" />
<rect height="180" rx="14.5" stroke="rgb(var(--clr-border))" stroke-opacity="0.1" stroke-width="1.5" width="293" x="1.5" y="1.5" />

View file

@ -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<string, Theme>;
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;
};