Skip to content

Commit

Permalink
feat(a11y): add no transparency setting detection (#2455)
Browse files Browse the repository at this point in the history
Also refactored styles to use UnoCSS and fixed some type issues

Signed-off-by: Fernando Fernández <[email protected]>
  • Loading branch information
ferferga committed Sep 8, 2024
1 parent 92c702c commit 3c592fd
Show file tree
Hide file tree
Showing 13 changed files with 70 additions and 76 deletions.
2 changes: 1 addition & 1 deletion frontend/src/assets/styles/splashscreen.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
align-items: center;
justify-content: center;
flex-direction: column;
background-color: var(--j-background-color);
background-color: var(--j-color-background);
}

.j-splash > img {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Item/Card/GenericItemCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ const hasClick = computed(() => !!attrs.onClick);
@media (hover: hover) and (pointer: fine) {
.card-box:hover .card-overlay-hover {
background: rgba(var(--v-theme-background), 0.5);
background: rgba(var(--j-color-background), 0.5);
}
.card-box:hover .card-overlay-hover .card-overlay-hover-hidden {
opacity: 1;
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/Layout/AppBar/AppBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@
<script setup lang="ts">
import { computed, inject, type Ref } from 'vue';
import { useRoute } from 'vue-router';
import { windowScroll, isConnectedToServer } from '@/store';
import { windowScroll, isConnectedToServer, prefersNoTransparency } from '@/store';
import { clientSettings } from '@/store/client-settings';
import { remote } from '@/plugins/remote';
const route = useRoute();
const { y } = windowScroll;
const transparentAppBar = computed(() => route.meta.layout.transparent && y.value < 10);
const transparentAppBar = computed(() => !prefersNoTransparency.value && route.meta.layout.transparent && y.value < 10);
/**
* Cycle between the different color schemas
Expand Down
33 changes: 9 additions & 24 deletions frontend/src/components/Layout/Backdrop.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,30 @@
<JTransition>
<div
v-if="blurhash"
:key="`backdrop-${blurhash}`"
class="backdrop sizing"
:key="blurhash"
class="uno-fixed uno-left-0 uno-top-0 uno-h-screen uno-w-screen uno-bg-cover uno-color-background"
:style="{
opacity,
}">
<BlurhashCanvas
:hash="blurhash"
:width="32"
:height="32"
class="sizing" />
class="uno-fixed uno-left-0 uno-top-0 uno-h-screen uno-w-screen uno-bg-cover" />
</div>
</JTransition>
</template>

<script lang="ts">
import { toRef, type MaybeRefOrGetter, shallowRef, onMounted, onBeforeUnmount } from 'vue';
import { toRef, type MaybeRefOrGetter, shallowRef, onMounted, onBeforeUnmount, computed } from 'vue';
import { watchImmediate } from '@vueuse/core';
import { isNil } from '@/utils/validation';
import { prefersNoTransparency } from '@/store';
const DEFAULT_OPACITY = 0.25;
const requested_opacity = shallowRef(DEFAULT_OPACITY);
const _blurhash = shallowRef<string>();
const _opacity = shallowRef(DEFAULT_OPACITY);
const _opacity = computed(() => prefersNoTransparency.value ? 0 : requested_opacity.value);
/**
* Reactively sets the backdrop properties. Can be used in 2 ways:
Expand All @@ -40,33 +42,16 @@ export function useBackdrop(hash?: MaybeRefOrGetter<string | undefined>, opacity
}
if (!isNil(opacity)) {
watchImmediate(toRef(opacity), val => _opacity.value = val ?? DEFAULT_OPACITY);
watchImmediate(toRef(opacity), val => requested_opacity.value = val ?? DEFAULT_OPACITY);
}
});
onBeforeUnmount(() => _blurhash.value = undefined);
onBeforeUnmount(() => _opacity.value = DEFAULT_OPACITY);
return { backdrop: _blurhash, opacity: _opacity.value };
onBeforeUnmount(() => requested_opacity.value = DEFAULT_OPACITY);
}
</script>

<script setup lang="ts">
const blurhash = _blurhash;
const opacity = _opacity;
</script>

<style scoped>
.backdrop {
background-color: rgb(var(--v-theme-background));
}
.sizing {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-size: cover;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import type { RouteNamedMap } from 'vue-router/auto-routes';
import type { getLibraryIcon } from '@/utils/items';
import { prefersNoTransparency } from '@/store';
export interface DrawerItem {
icon: ReturnType<typeof getLibraryIcon>;
Expand All @@ -59,7 +60,7 @@ const route = useRoute();
const { t } = useI18n();
const drawer = inject<Ref<boolean>>('NavigationDrawer');
const transparentLayout = computed(() => route.meta.layout.transparent);
const transparentLayout = computed(() => !prefersNoTransparency.value && route.meta.layout.transparent);
const items = [
{
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/lib/JApp.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<template v-if="isLoading">
cursor: wait;
</template>
--j-background-color: rgb(var(--v-theme-background));
--j-color-background: rgb(var(--v-theme-background));
}
</component>
<!-- eslint-enable @intlify/vue-i18n/no-raw-text vue/require-component-is -->
Expand Down
9 changes: 6 additions & 3 deletions frontend/src/components/lib/JTransition.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
:is="group ? TransitionGroup : Transition"
class="j-transition"
v-bind="$attrs"
:name="prefersNoMotion || disabled || isSlow ? undefined : `j-transition-${name}`"
:name="forcedDisable || disabled ? undefined : `j-transition-${name}`"
@before-leave="leaving = true"
@after-leave="onNoLeave"
@leave-cancelled="onNoLeave">
<slot />
</component>
</template>

<script setup lang="ts">
import { Transition, TransitionGroup, type TransitionProps, shallowRef } from 'vue';
<script lang="ts">
import { Transition, TransitionGroup, type TransitionProps, shallowRef, computed } from 'vue';
import { prefersNoMotion, isSlow } from '@/store';
import { usePausableEffect } from '@/composables/use-pausable-effect';
Expand All @@ -29,7 +29,10 @@ interface Props {
}
export type JTransitionProps = TransitionProps & Props;
const forcedDisable = computed(() => prefersNoMotion.value || isSlow.value);
</script>

<script setup lang="ts">
const { name = 'fade', group, disabled } = defineProps<Props>();
const leaving = shallowRef(false);
const onNoLeave = () => leaving.value = false;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/composables/backdrop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { getBlurhash } from '@/utils/images';
/**
* Same as useBackdrop, but is a shorthand for items only.
*/
export function useItemBackdrop(item: MaybeRefOrGetter<Nullish<BaseItemDto>>, ...args: ExcludeFromTuple<Parameters<typeof useBackdrop>, 0>) {
export function useItemBackdrop(item: MaybeRefOrGetter<Nullish<BaseItemDto>>, ...args: Tail<Parameters<typeof useBackdrop>>) {
useBackdrop(() => getBlurhash(toValue(item) ?? {}, ImageType.Primary), ...args);
}

Expand Down
66 changes: 33 additions & 33 deletions frontend/src/pages/playback/video.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
width="100%"
height="100%">
<div
class="d-flex flex-column justify-space-between align-center player-overlay">
class="d-flex flex-column align-center justify-space-between player-overlay">
<div class="osd-top pt-s pl-s pr-s">
<div class="d-flex align-center py-2 px-4">
<div class="d-flex">
Expand Down Expand Up @@ -214,45 +214,45 @@ watch(staticOverlay, (val) => {
padding-bottom: 5em;
background: linear-gradient(
to bottom,
rgb(var(--v-theme-background), 0.75) 0%,
rgb(var(--v-theme-background), 0.74) 8.1%,
rgb(var(--v-theme-background), 0.714) 15.5%,
rgb(var(--v-theme-background), 0.672) 22.5%,
rgb(var(--v-theme-background), 0.618) 29%,
rgb(var(--v-theme-background), 0.556) 35.3%,
rgb(var(--v-theme-background), 0.486) 41.2%,
rgb(var(--v-theme-background), 0.412) 47.1%,
rgb(var(--v-theme-background), 0.338) 52.9%,
rgb(var(--v-theme-background), 0.264) 58.8%,
rgb(var(--v-theme-background), 0.194) 64.7%,
rgb(var(--v-theme-background), 0.132) 71%,
rgb(var(--v-theme-background), 0.078) 77.5%,
rgb(var(--v-theme-background), 0.036) 84.5%,
rgb(var(--v-theme-background), 0.01) 91.9%,
rgb(var(--v-theme-background), 0) 100%
rgb(var(--j-color-background), 0.75) 0%,
rgb(var(--j-color-background), 0.74) 8.1%,
rgb(var(--j-color-background), 0.714) 15.5%,
rgb(var(--j-color-background), 0.672) 22.5%,
rgb(var(--j-color-background), 0.618) 29%,
rgb(var(--j-color-background), 0.556) 35.3%,
rgb(var(--j-color-background), 0.486) 41.2%,
rgb(var(--j-color-background), 0.412) 47.1%,
rgb(var(--j-color-background), 0.338) 52.9%,
rgb(var(--j-color-background), 0.264) 58.8%,
rgb(var(--j-color-background), 0.194) 64.7%,
rgb(var(--j-color-background), 0.132) 71%,
rgb(var(--j-color-background), 0.078) 77.5%,
rgb(var(--j-color-background), 0.036) 84.5%,
rgb(var(--j-color-background), 0.01) 91.9%,
rgb(var(--j-color-background), 0) 100%
);
}

.osd-bottom {
padding-top: 6em;
background: linear-gradient(
to top,
rgb(var(--v-theme-background), 0.75) 0%,
rgb(var(--v-theme-background), 0.74) 8.1%,
rgb(var(--v-theme-background), 0.714) 15.5%,
rgb(var(--v-theme-background), 0.672) 22.5%,
rgb(var(--v-theme-background), 0.618) 29%,
rgb(var(--v-theme-background), 0.556) 35.3%,
rgb(var(--v-theme-background), 0.486) 41.2%,
rgb(var(--v-theme-background), 0.412) 47.1%,
rgb(var(--v-theme-background), 0.338) 52.9%,
rgb(var(--v-theme-background), 0.264) 58.8%,
rgb(var(--v-theme-background), 0.194) 64.7%,
rgb(var(--v-theme-background), 0.132) 71%,
rgb(var(--v-theme-background), 0.078) 77.5%,
rgb(var(--v-theme-background), 0.036) 84.5%,
rgb(var(--v-theme-background), 0.01) 91.9%,
rgb(var(--v-theme-background), 0) 100%
rgb(var(--j-color-background), 0.75) 0%,
rgb(var(--j-color-background), 0.74) 8.1%,
rgb(var(--j-color-background), 0.714) 15.5%,
rgb(var(--j-color-background), 0.672) 22.5%,
rgb(var(--j-color-background), 0.618) 29%,
rgb(var(--j-color-background), 0.556) 35.3%,
rgb(var(--j-color-background), 0.486) 41.2%,
rgb(var(--j-color-background), 0.412) 47.1%,
rgb(var(--j-color-background), 0.338) 52.9%,
rgb(var(--j-color-background), 0.264) 58.8%,
rgb(var(--j-color-background), 0.194) 64.7%,
rgb(var(--j-color-background), 0.132) 71%,
rgb(var(--j-color-background), 0.078) 77.5%,
rgb(var(--j-color-background), 0.036) 84.5%,
rgb(var(--j-color-background), 0.01) 91.9%,
rgb(var(--j-color-background), 0) 100%
);
}

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/splashscreen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ if ('darkMode' in parsedStore) {
}
}

document.body.style.setProperty('--j-background-color', colorToApply);
document.body.style.setProperty('--j-color-background', colorToApply);
6 changes: 5 additions & 1 deletion frontend/src/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,12 @@ export const mediaWebAudio = {
/**
* Reactively tracks if the user wants animations (false) or not (true).
*/
export const prefersNoMotion = useMediaQuery('(prefers-reduced-motion)');
export const prefersNoMotion = useMediaQuery('(prefers-reduced-motion:reduce)');

/**
* Reactively tracks if the user wants transparency effects (true) or not (false).
*/
export const prefersNoTransparency = useMediaQuery('(prefers-reduced-transparency:reduce)');
/**
* IWhether the user is using a pointer with high precision (like a mouse)
*/
Expand Down
8 changes: 2 additions & 6 deletions frontend/types/global/util.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,9 @@ type Mutable<T> = {
};

/**
* Omits an specific element from a tuple.
* Gets the last item of a tuple
*/
type ExcludeFromTuple<T, K extends number, I extends unknown[] = []> = T extends [infer F, ...infer R]
? I['length'] extends K
? [...ExcludeFromTuple<R, K, [F, ...I]>]
: [F, ...ExcludeFromTuple<R, K, [F, ...I]>]
: [];
type Tail<L> = L extends readonly [] ? L : L extends readonly [unknown?, ...infer LTail] ? LTail : L;

/**
* Sets a type as nullish
Expand Down
7 changes: 6 additions & 1 deletion frontend/uno.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,10 @@ export default defineConfig({
prefix: 'uno-',
preflight: false
})
]
],
theme: {
colors: {
background: 'rgb(var(--j-color-background))'
}
}
});

0 comments on commit 3c592fd

Please sign in to comment.