feat: scroll the new timer into view

This commit is contained in:
MAZE 2024-06-16 22:22:32 +03:30
parent 28abc16b9c
commit f4c66e3092
4 changed files with 36 additions and 5 deletions

View File

@ -3,6 +3,7 @@ import { useState, useMemo } from 'react';
import { Field } from './field'; import { Field } from './field';
import { useCountdownTimers } from '@/stores/countdown-timers'; import { useCountdownTimers } from '@/stores/countdown-timers';
import { waitUntil } from '@/helpers/wait';
import styles from './form.module.css'; import styles from './form.module.css';
@ -19,17 +20,23 @@ export function Form() {
const add = useCountdownTimers(state => state.add); const add = useCountdownTimers(state => state.add);
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => { const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
if (totalSeconds === 0) return; if (totalSeconds === 0) return;
add({ const id = add({
name, name,
total: totalSeconds, total: totalSeconds,
}); });
setName(''); setName('');
await waitUntil(() => !!document.getElementById(`timer-${id}`), 50);
document
.getElementById(`timer-${id}`)
?.scrollIntoView({ behavior: 'smooth' });
}; };
return ( return (

View File

@ -139,7 +139,7 @@ export function Timer({ id }: TimerProps) {
}, [isRunning, tick, id, spent, total, left]); }, [isRunning, tick, id, spent, total, left]);
return ( return (
<div className={styles.timer}> <div className={styles.timer} id={`timer-${id}`}>
<header className={styles.header}> <header className={styles.header}>
<div className={styles.bar}> <div className={styles.bar}>
<div <div

20
src/helpers/wait.ts Normal file
View File

@ -0,0 +1,20 @@
export function waitUntil(
func: () => boolean,
interval: number,
): Promise<void> {
return new Promise((resolve, reject) => {
const intervalId = setInterval(() => {
try {
const result = func();
if (result) {
clearInterval(intervalId);
resolve();
}
} catch (error) {
clearInterval(intervalId);
reject(error);
}
}, interval);
});
}

View File

@ -16,7 +16,7 @@ interface State {
} }
interface Actions { interface Actions {
add: (timer: { name: string; total: number }) => void; add: (timer: { name: string; total: number }) => string;
delete: (id: string) => void; delete: (id: string) => void;
getTimer: (id: string) => Timer; getTimer: (id: string) => Timer;
rename: (id: string, newName: string) => void; rename: (id: string, newName: string) => void;
@ -28,10 +28,12 @@ export const useCountdownTimers = create<State & Actions>()(
persist( persist(
(set, get) => ({ (set, get) => ({
add({ name, total }) { add({ name, total }) {
const id = uuid();
set(state => ({ set(state => ({
timers: [ timers: [
{ {
id: uuid(), id,
name, name,
spent: 0, spent: 0,
total, total,
@ -39,6 +41,8 @@ export const useCountdownTimers = create<State & Actions>()(
...state.timers, ...state.timers,
], ],
})); }));
return id;
}, },
delete(id) { delete(id) {