Skip to content

Commit

Permalink
Add a reduced motion mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Dlurak committed Jun 29, 2024
1 parent 8947e10 commit c1bbeaa
Show file tree
Hide file tree
Showing 23 changed files with 112 additions and 45 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"svelte-confetti": "^1.4.0",
"svelte-dnd-action": "^0.9.49",
"svelte-floating-ui": "^1.5.8",
"svelte-media-queries": "^1.6.2",
"svocal": "^0.2.2",
"zod": "^3.23.5"
}
Expand Down
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion src/lib/components/i18n/LangSelect.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import { createFloatingActions } from 'svelte-floating-ui';
import { abbrevations } from '$lib/i18n/i18n';
import { fly } from 'svelte/transition';
import { animationLength } from '$lib/utils/store/animation';
const lang = svocal('i18n.currentlang');
Expand Down Expand Up @@ -38,7 +39,7 @@
<div
class="absolute h-fit w-[--w] px-2"
use:floatingContent
transition:fly={{ y: 50 }}
transition:fly={{ y: 50, duration: $animationLength }}
style:--w={`min(${width * 1.7}px, 100%)`}
>
<div class="flex flex-col overflow-hidden rounded bg-neutral-200 shadow-lg dark:bg-neutral-700">
Expand Down
10 changes: 10 additions & 0 deletions src/lib/components/layout/Style.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<script>
import { browser } from '$app/environment';
import { animationLength } from '$lib/utils/store/animation';
animationLength.subscribe((le) => {
if (!browser) return;
document.documentElement.style.setProperty('--transition-duration', `${le}ms`);
});
</script>
3 changes: 3 additions & 0 deletions src/lib/components/layout/Token.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@
import { sendToast } from './toasts';
import { i } from '$lib/i18n/store';
import { onMount } from 'svelte';
import { network } from 'nutzlich';
const accessTokenExpires = svocal('auth.access.expires');
const refreshToken = svocal('auth.refresh.token');
const net = network();
onMount(async () => {
accessTokenExpires.subscribe((val) => {
if (val === null) return;
if (!$refreshToken) return;
if ($net.isOffline) return;
const msLeft = val - currentMs();
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/layout/launcher/LauncherPopup.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
</div>

<div class="max-h-96 overflow-y-scroll">
{#each $filteredAndSortedOptions as item, index}
{#each $filteredAndSortedOptions as item, index (item.index)}
<LauncherItem
{item}
{index}
Expand Down
39 changes: 9 additions & 30 deletions src/lib/components/layout/launcher/hook.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { browser } from '$app/environment';
import {
launcherItems,
type LauncherItem,
launcherItems,
type LauncherSelectableItem
} from '$lib/constants/launcher';
import { enableScrolling } from '$lib/utils/dom/scroll';
Expand All @@ -11,11 +11,7 @@ import { get, writable } from 'svelte/store';

const getBaseSelectableItems = (launcherItems: LauncherItem[]) => {
return launcherItems
.map((item) => ({
...item,
matchedBy: null,
coefficient: 0
}))
.map((item, index) => ({ ...item, matchedBy: null, coefficient: 0, index }))
.filter(({ enabled }) => enabled === undefined || get(enabled));
};

Expand All @@ -26,9 +22,7 @@ const isdetailed = writable(true);
const filteredAndSortedOptions = writable<LauncherSelectableItem[]>(
getBaseSelectableItems(launcherItems)
);
const focusedIndex = useCycle({
max: () => get(filteredAndSortedOptions).length - 1
});
const focusedIndex = useCycle({ max: () => get(filteredAndSortedOptions).length - 1 });

isOpen.subscribe((isOpen) => {
if (!browser) return;
Expand All @@ -55,6 +49,7 @@ search.subscribe((searchTermRaw) => {
if (!searchTerm) return filteredAndSortedOptions.set(getBaseSelectableItems(get(allOptions)));

const mapped = get(allOptions)
.map((data, index) => ({ ...data, index }))
.filter(({ enabled }) => {
if (enabled === undefined) {
return true;
Expand All @@ -69,18 +64,10 @@ search.subscribe((searchTermRaw) => {
.at(0);

if (matching === undefined) {
return {
...opt,
matchedBy: null,
coefficient: 0
};
return { ...opt, matchedBy: null, coefficient: 0 };
}

return {
...opt,
matchedBy: matching[0],
coefficient: matching[1]
};
return { ...opt, matchedBy: matching[0], coefficient: matching[1] };
});

const sorted = mapped
Expand All @@ -105,22 +92,14 @@ export function useLauncher() {
subscribe: isOpen.subscribe
},
focusedIndex: { ...focusedIndex },
search: {
subscribe: search.subscribe,
set: search.set
},
search: { subscribe: search.subscribe, set: search.set },
detailed: {
setDetailed: () => isdetailed.set(true),
setUndetailed: () => isdetailed.set(false),
subscribe: isdetailed.subscribe
},
allOptions: {
set: allOptions.set,
subscribe: allOptions.subscribe
},
filteredAndSortedOptions: {
subscribe: filteredAndSortedOptions.subscribe
}
allOptions: { set: allOptions.set, subscribe: allOptions.subscribe },
filteredAndSortedOptions: { subscribe: filteredAndSortedOptions.subscribe }
};
}

Expand Down
10 changes: 8 additions & 2 deletions src/lib/components/layout/navigation/Navbar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { svocal } from '$lib/utils/store/svocal';
import { flip } from 'svelte/animate';
import NavigationButton from './NavigationButton.svelte';
import { animationLength } from '$lib/utils/store/animation';
const navEntries = svocal('settings.nav.entries');
</script>
Expand All @@ -12,7 +13,12 @@
bind:clientHeight={$navHeight}
>
<nav
class="flex items-center justify-between gap-2 rounded-md bg-neutral-400 bg-opacity-50 px-4 py-2 shadow-md backdrop-blur-lg sm:rounded-none sm:bg-neutral-100 sm:shadow-none dark:bg-neutral-800 dark:bg-opacity-50 sm:dark:bg-neutral-900"
class="
flex items-center justify-between gap-2 rounded-md
bg-neutral-400 bg-opacity-50 px-4 py-2 shadow-md backdrop-blur-lg
sm:rounded-none sm:bg-neutral-100 sm:bg-opacity-50 sm:shadow-none
dark:bg-neutral-800 dark:bg-opacity-50 sm:dark:bg-neutral-900 sm:dark:bg-opacity-50
"
>
<div class="hidden h-12 w-full sm:inline-block">
<a class="aspect-square h-12 w-12" href="/">
Expand All @@ -22,7 +28,7 @@

<div class="flex w-full items-center justify-evenly sm:w-fit">
{#each $navEntries as navTarget (navTarget)}
<span class="flex-1" animate:flip={{ duration: 300 }}>
<span class="flex-1" animate:flip={{ duration: $animationLength }}>
<NavigationButton target={navTarget} />
</span>
{/each}
Expand Down
3 changes: 2 additions & 1 deletion src/lib/components/settings/BoolSetting.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import QuickAction from '../buttons/QuickAction.svelte';
import { QuestionMarkCircle } from 'svelte-hero-icons';
import { slide } from 'svelte/transition';
import { animationLength } from '$lib/utils/store/animation';
export let label: Readable<string>;
export let value: boolean;
Expand All @@ -29,7 +30,7 @@
<Switch bind:checked={value} />
</div>
{#if description && showDescription}
<div transition:slide class="text-gray-500 dark:text-gray-400">
<div transition:slide={{ duration: $animationLength }} class="text-gray-500 dark:text-gray-400">
<Store store={description} />
</div>
{/if}
Expand Down
3 changes: 2 additions & 1 deletion src/lib/components/settings/SelectSetting.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script lang="ts" generics="V">
import { animationLength } from '$lib/utils/store/animation';
import { QuestionMarkCircle } from 'svelte-hero-icons';
import { slide } from 'svelte/transition';
import QuickAction from '../buttons/QuickAction.svelte';
Expand Down Expand Up @@ -43,7 +44,7 @@
{/if}
</div>
{#if description && showDescription}
<div transition:slide class="text-gray-500 dark:text-gray-400">
<div transition:slide={{ duration: $animationLength }} class="text-gray-500 dark:text-gray-400">
<Store store={description} />
</div>
{/if}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
<script lang="ts" context="module">
const FLIP_DURATION = 300;
type ItemPool = {
name: NavigationTarget;
id: number;
Expand All @@ -24,6 +22,7 @@
import { i } from '$lib/i18n/store';
import { navbarEntries } from '$lib/constants/navbar';
import { keys } from '$lib/utils/objects/entries';
import { animationLength } from '$lib/utils/store/animation';
const selectedSvocal = svocal('settings.nav.entries');
Expand All @@ -34,7 +33,7 @@
<div class="flex flex-col gap-2 rounded">
<DropArea
block={1}
flipDurationMs={FLIP_DURATION}
flipDurationMs={$animationLength}
bind:items={selectedPreview}
on:final={({ detail }) => {
selectedSvocal.set(detail.map(({ name }) => name));
Expand All @@ -43,7 +42,7 @@
<h4 slot="pre-content"><Store store={i('settings.general.nav.composer.your')} /></h4>
</DropArea>

<DropArea flipDurationMs={FLIP_DURATION} bind:items={notSelectedPreview}>
<DropArea flipDurationMs={$animationLength} bind:items={notSelectedPreview}>
<h4 slot="pre-content"><Store store={i('settings.general.nav.composer.available')} /></h4>
<span class="text-gray-500" slot="empty">
<Store store={i('settings.general.nav.composer.empty')} />
Expand Down
3 changes: 2 additions & 1 deletion src/lib/components/utils/Collapseable.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script lang="ts">
import { animationLength } from '$lib/utils/store/animation';
import { Icon, ChevronDown } from 'svelte-hero-icons';
import { slide } from 'svelte/transition';
import { localstorage } from 'svocal';
Expand All @@ -21,7 +22,7 @@
</div>

{#if $isExpanded}
<div transition:slide class="p-0.5">
<div transition:slide={{ duration: $animationLength }} class="p-0.5">
<slot name="content" />
</div>
{/if}
13 changes: 10 additions & 3 deletions src/lib/components/utils/Updates.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,17 @@
import QuickAction from '../buttons/QuickAction.svelte';
import { ChevronDown, ChevronUp } from 'svelte-hero-icons';
import { slide } from 'svelte/transition';
import { animationLength } from '$lib/utils/store/animation';
export let updates: Update[];
const showAllEdits = useToggle(false);
</script>

<div class="flex flex-col">
<span class="flex w-fit items-center justify-center gap-1" transition:slide>
<span
class="flex w-fit items-center justify-center gap-1"
transition:slide={{ duration: $animationLength }}
>
<UpdatedAt
type={updates.length === 1 ? 'created' : 'edited'}
timestamp={updates[updates.length - 1].time}
Expand All @@ -36,14 +40,17 @@
</span>

{#if $showAllEdits}
<div transition:slide>
<div transition:slide={{ duration: $animationLength }}>
{#each updates
.map((data, ind) => ({ ...data, isFirst: ind === 0 }))
.reverse()
.slice(1) as update}
{@const type = update.isFirst ? 'created' : 'edited'}

<span class="flex w-fit justify-center gap-1" transition:slide>
<span
class="flex w-fit justify-center gap-1"
transition:slide={{ duration: $animationLength }}
>
<UpdatedAt {type} timestamp={update.time} displayname={update.user.displayname} />
</span>
{/each}
Expand Down
1 change: 1 addition & 0 deletions src/lib/constants/launcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export type LauncherSelectableItem = {
searchTerms: Readable<string[]>;
matchedBy: string | null;
coefficient: number;
index: number;
enabled?: Readable<boolean>;
};

Expand Down
2 changes: 2 additions & 0 deletions src/lib/locales/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,8 @@ const de = {
'settings.deleteAccount.success': 'Den Account $name erfolgreich gelöscht',

'settings.general': 'Allgemein',
'settings.general.general': 'Allgemein',
'settings.general.general.animations': 'Bewegung reduzieren',
'settings.general.nav': 'Navigation',
'settings.general.nav.description':
"Hier kannst du Deine Navigationsleiste anpassen. Bewege die Boxen einfach via Drag'n Drop.",
Expand Down
2 changes: 2 additions & 0 deletions src/lib/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,8 @@ const en = {
'settings.deleteAccount.success': 'Successfully deleted the account $name',

'settings.general': 'General',
'settings.general.general': 'General',
'settings.general.general.animations': 'Reduce motion',
'settings.general.nav': 'Navigation',
'settings.general.nav.description':
"Here you can change your navigation bar.Simply move the boxes via Drag'n Drop.",
Expand Down
15 changes: 15 additions & 0 deletions src/lib/utils/store/animation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { svocal } from '$lib/utils/store/svocal';
import { createMediaStore } from 'svelte-media-queries';
import { derived } from 'svelte/store';

const manual = svocal('settings.reduceMotion');

export const animationLength = derived(
[manual, createMediaStore('(prefers-reduced-motion: reduce)')],
([reduced, manual]) => {
if (manual) return 0;
if (reduced) return 0;

return 300;
}
);
1 change: 1 addition & 0 deletions src/lib/utils/store/svocal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ const sv = {
() => ({}) as Record<string, string>
],
'settings.homework.smart-subjects': ['settings.homework.smart-subjects', () => true],
'settings.reduceMotion': ['settings.reduceMotion', () => false],
'dlool-version': ['dlool-version', () => '2']
} as const;

Expand Down
Loading

0 comments on commit c1bbeaa

Please sign in to comment.