From bf50fe73985485d302d58f90cd063771103452fd Mon Sep 17 00:00:00 2001 From: Miodec Date: Thu, 8 Jan 2026 17:49:55 +0100 Subject: [PATCH] export hook --- .../src/ts/hooks/useVisibilityAnimation.ts | 41 +++++++++++++++++++ frontend/src/ts/test/live-counter.tsx | 41 ++++--------------- 2 files changed, 48 insertions(+), 34 deletions(-) create mode 100644 frontend/src/ts/hooks/useVisibilityAnimation.ts diff --git a/frontend/src/ts/hooks/useVisibilityAnimation.ts b/frontend/src/ts/hooks/useVisibilityAnimation.ts new file mode 100644 index 000000000..8bdf13741 --- /dev/null +++ b/frontend/src/ts/hooks/useVisibilityAnimation.ts @@ -0,0 +1,41 @@ +import { Accessor, createEffect } from "solid-js"; +import { ElementWithUtils } from "../utils/dom"; + +export function useVisibilityAnimation( + element: () => ElementWithUtils | undefined, + visible: Accessor<{ + value: boolean; + withAnimation: boolean; + }>, + additionalCondition?: Accessor, +): void { + createEffect(() => { + const el = element(); + if (!el) return; + + const visibleState = visible(); + const shouldShow = additionalCondition + ? visibleState.value && additionalCondition() + : visibleState.value; + + if (shouldShow) { + if (visibleState.withAnimation) { + el.animate({ + opacity: [0, 1], + duration: 125, + }); + } else { + el.setStyle({ opacity: "1" }); + } + } else { + if (visibleState.withAnimation) { + el.animate({ + opacity: [1, 0], + duration: 125, + }); + } else { + el.setStyle({ opacity: "0" }); + } + } + }); +} diff --git a/frontend/src/ts/test/live-counter.tsx b/frontend/src/ts/test/live-counter.tsx index 0e17aa130..c605790a9 100644 --- a/frontend/src/ts/test/live-counter.tsx +++ b/frontend/src/ts/test/live-counter.tsx @@ -1,6 +1,7 @@ -import { Accessor, createEffect, JSXElement, onMount } from "solid-js"; +import { Accessor, JSXElement } from "solid-js"; import { ElementWithUtils } from "../utils/dom"; import { isFocused } from "./focus"; +import { useVisibilityAnimation } from "../hooks/useVisibilityAnimation"; export function LiveCounter(props: { value: Accessor; @@ -10,43 +11,15 @@ export function LiveCounter(props: { }>; class?: string; }): JSXElement { - // oxlint-disable-next-line no-unassigned-vars - let divRef: HTMLDivElement | undefined; let divUtil: ElementWithUtils | undefined; - onMount(() => { - if (divRef) { - divUtil = new ElementWithUtils(divRef); - } - }); - - createEffect(() => { - if (divUtil === undefined) return; - const visibleState = props.visible(); - const focusState = isFocused(); - if (visibleState.value && focusState) { - if (visibleState.withAnimation) { - divUtil.animate({ - opacity: [0, 1], - duration: 125, - }); - } else { - divUtil.setStyle({ opacity: "1" }); - } - } else { - if (visibleState.withAnimation) { - divUtil.animate({ - opacity: [1, 0], - duration: 125, - }); - } else { - divUtil.setStyle({ opacity: "0" }); - } - } - }); + useVisibilityAnimation(() => divUtil, props.visible, isFocused); return ( -
+
(divUtil = new ElementWithUtils(el))} + class={`${props.class}`} + > {props.value()}
);