feat: Launcher reduced motion
This commit is contained in:
parent
dfb4c09be7
commit
46a5606ade
11 changed files with 91 additions and 18 deletions
|
|
@ -57,3 +57,8 @@ h4 { @apply text-lg font-medium; }
|
|||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
body.reduce-motion * {
|
||||
transition-duration: 0.0001ms !important;
|
||||
animation-duration: 0.0001ms !important;
|
||||
}
|
||||
|
|
|
|||
30
desktop/src/ui/components/base/Toggle.tsx
Normal file
30
desktop/src/ui/components/base/Toggle.tsx
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import { type JSX, createSignal, splitProps } from 'solid-js';
|
||||
|
||||
type ToggleProps = JSX.HTMLAttributes<HTMLDivElement> & {
|
||||
defaultChecked?: boolean;
|
||||
onChecked?: (checked: boolean) => void;
|
||||
showText?: 'left' | 'right';
|
||||
};
|
||||
|
||||
function Toggle(props: ToggleProps) {
|
||||
const [checked, setChecked] = createSignal(props.defaultChecked || false);
|
||||
const [split, rest] = splitProps(props, ['class', 'defaultChecked', 'onChecked', 'text']);
|
||||
|
||||
function toggle() {
|
||||
const newValue = !checked();
|
||||
setChecked(newValue);
|
||||
props.onChecked?.(newValue);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
onClick={() => toggle()}
|
||||
class={`w-[40px] h-[22px] p-3 flex flex-row relative rounded-full transition-colors overflow-hidden ${checked() ? 'bg-brand' : 'bg-gray-10'}${` ${split.class}` ?? ''}`}
|
||||
{...rest}
|
||||
>
|
||||
<div class={`w-[16px] h-[16px] rounded-full mx-1 left-0 top-1/2 -translate-y-1/2 transition-transform bg-white absolute ${checked() ? 'translate-x-full' : 'translate-x-0'}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Toggle;
|
||||
|
|
@ -36,7 +36,7 @@ function ContextMenu(props: ContextMenuProps) {
|
|||
visible={props.visible}
|
||||
setVisible={props.setVisible}
|
||||
>
|
||||
<div ref={setRef} class="bg-secondary rounded-xl border border-gray-10 p-1 shadow-lg shadow-black/50">
|
||||
<div ref={setRef} class="bg-secondary rounded-xl border border-gray-05 p-1 shadow-md shadow-black/30">
|
||||
<div class="flex flex-col gap-y-1 text-fg-primary">
|
||||
{props.children}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ import { EyeIcon, File06Icon, Globe04Icon, Image03Icon, PackagePlusIcon, Setting
|
|||
import Sidebar from '../../components/Sidebar';
|
||||
import AnimatedRoutes from '../../components/AnimatedRoutes';
|
||||
import ErrorBoundary from '../../components/ErrorBoundary';
|
||||
import ClusterOverview from './ClusterOverview';
|
||||
import ClusterLogs from './ClusterLogs';
|
||||
import ClusterMods from './ClusterMods';
|
||||
import ClusterScreenshots from './ClusterScreenshots';
|
||||
import ClusterOverview from './cluster/ClusterOverview';
|
||||
import ClusterLogs from './cluster/ClusterLogs';
|
||||
import ClusterMods from './cluster/ClusterMods';
|
||||
import ClusterScreenshots from './cluster/ClusterScreenshots';
|
||||
|
||||
function ClusterRoutes() {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useSearchParams } from '@solidjs/router';
|
||||
import { For, Show, createEffect, createResource, createSignal } from 'solid-js';
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-solid';
|
||||
import { getClusterLog, getClusterLogs } from '../../../bridge/game';
|
||||
import { getClusterLog, getClusterLogs } from '../../../../bridge/game';
|
||||
|
||||
function ClusterLogs() {
|
||||
const [params] = useSearchParams();
|
||||
|
|
@ -50,8 +50,8 @@ function ModEntry(props: ModEntryProps) {
|
|||
<div class="flex flex-row justify-between items-center">
|
||||
<div class="flex flex-col items-start justify-center">
|
||||
<div class="flex flex-row items-center">
|
||||
<h3>{props.name}</h3>
|
||||
<span class="flex flex-row items-center text-sm font-600 text-fg-secondary/50 ml-2">
|
||||
<h4>{props.name}</h4>
|
||||
<span class="flex flex-row items-center text-xs font-600 text-fg-secondary/50 ml-2">
|
||||
{props.version}
|
||||
{/* TODO: Add version checker */}
|
||||
{/* <Show when={props.version.includes()}> */}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
import { useSearchParams } from '@solidjs/router';
|
||||
import { Show } from 'solid-js';
|
||||
import { PlayIcon, Share07Icon } from '@untitled-theme/icons-solid';
|
||||
import useCluster from '../../hooks/useCluster';
|
||||
import ClusterCover from '../../components/game/ClusterCover';
|
||||
import LoaderIcon from '../../components/game/LoaderIcon';
|
||||
import Button from '../../components/base/Button';
|
||||
import { launchCluster } from '../../../bridge/game';
|
||||
import useCluster from '../../../hooks/useCluster';
|
||||
import ClusterCover from '../../../components/game/ClusterCover';
|
||||
import LoaderIcon from '../../../components/game/LoaderIcon';
|
||||
import Button from '../../../components/base/Button';
|
||||
import { launchCluster } from '../../../../bridge/game';
|
||||
import ScrollableContainer from '~ui/components/ScrollableContainer';
|
||||
|
||||
function ClusterOverview() {
|
||||
|
|
@ -11,14 +11,14 @@ function SettingsRow(props: SettingsRowProps) {
|
|||
const interactableClass = createEffect(() => props.clickable ? 'hover:bg-component-bg-hover active:bg-component-bg-pressed' : '');
|
||||
|
||||
return (
|
||||
<div class={`flex flex-row bg-component-bg rounded-xl gap-4 px-5 p-4 ${interactableClass} items-center`}>
|
||||
<div class={`flex flex-row bg-component-bg rounded-xl gap-3.5 p-4 ${interactableClass} items-center`}>
|
||||
<div class="flex justify-center items-center h-8 w-8">
|
||||
{props.icon}
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-2 flex-1">
|
||||
<h3>{props.title}</h3>
|
||||
<p class="text-wrap">{props.description}</p>
|
||||
<h3 class="text-lg">{props.title}</h3>
|
||||
<p class="text-wrap text-sm">{props.description}</p>
|
||||
</div>
|
||||
|
||||
<div class="">
|
||||
|
|
|
|||
|
|
@ -1,21 +1,39 @@
|
|||
import { ColorsIcon, PaintPourIcon } from '@untitled-theme/icons-solid';
|
||||
import { ColorsIcon, PaintPourIcon, Speedometer04Icon } from '@untitled-theme/icons-solid';
|
||||
import SettingsRow from '../components';
|
||||
import ScrollableContainer from '~ui/components/ScrollableContainer';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import Toggle from '~ui/components/base/Toggle';
|
||||
import reducedMotionTracker from '~ui/state/reducedMotionTracker';
|
||||
|
||||
function SettingsAppearance() {
|
||||
const { reducedMotion, setReducedMotion } = reducedMotionTracker;
|
||||
|
||||
return (
|
||||
<ScrollableContainer title="Appearance">
|
||||
<div class="flex flex-row items-center flex-1">
|
||||
<p>theme placeholder</p>
|
||||
</div>
|
||||
|
||||
<SettingsRow
|
||||
title="Accent Color"
|
||||
description="The main color used across the launcher. This doesn’t edit your theme."
|
||||
description="The main color used across the launcher. This doesn't edit your theme."
|
||||
icon={<PaintPourIcon />}
|
||||
>
|
||||
<Button iconLeft={<ColorsIcon />}>#ff0000</Button>
|
||||
</SettingsRow>
|
||||
|
||||
<SettingsRow
|
||||
title="Animations"
|
||||
description="Toggle all animations in the launcher."
|
||||
icon={<Speedometer04Icon />}
|
||||
>
|
||||
<Toggle
|
||||
defaultChecked={reducedMotion()}
|
||||
onChecked={(checked) => {
|
||||
setReducedMotion(checked);
|
||||
}}
|
||||
/>
|
||||
</SettingsRow>
|
||||
</ScrollableContainer>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
20
desktop/src/ui/state/reducedMotionTracker.ts
Normal file
20
desktop/src/ui/state/reducedMotionTracker.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import { createEffect, createRoot, createSignal, onMount } from 'solid-js';
|
||||
|
||||
function createReducedMotionTracker() {
|
||||
const [reducedMotion, setReducedMotion] = createSignal(false);
|
||||
|
||||
onMount(() => {
|
||||
const enabled = window.localStorage.getItem('reduced-motion') === 'true';
|
||||
setReducedMotion(enabled);
|
||||
});
|
||||
|
||||
createEffect(() => {
|
||||
const enabled = reducedMotion();
|
||||
document.body.classList.toggle('reduce-motion', enabled);
|
||||
window.localStorage.setItem('reduced-motion', enabled.toString());
|
||||
});
|
||||
|
||||
return { reducedMotion, setReducedMotion };
|
||||
}
|
||||
|
||||
export default createRoot(createReducedMotionTracker);
|
||||
Loading…
Add table
Reference in a new issue