From e56e5fb8e93297e8d634df9dbd81b67bdb3d2205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Schr=C3=B6tler?= <niklas@allround.digital> Date: Sun, 10 Dec 2023 13:06:51 +0100 Subject: [PATCH] FahrplanPanel: Added Animations --- src/panels/Fahrplan/FahrplanPanel.tsx | 5 +- .../Fahrplan/components/PlanElement.tsx | 63 ++++++++++++++++--- 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/src/panels/Fahrplan/FahrplanPanel.tsx b/src/panels/Fahrplan/FahrplanPanel.tsx index e33a20c..e687e8c 100644 --- a/src/panels/Fahrplan/FahrplanPanel.tsx +++ b/src/panels/Fahrplan/FahrplanPanel.tsx @@ -5,6 +5,7 @@ import PanelTitle from "../../meta/PanelTitle"; import PanelContent from "../../meta/PanelContent"; import {StationResponse} from "./types/vrrfAPI"; import {Warning} from "@phosphor-icons/react"; +import {AnimatePresence, motion} from 'framer-motion'; export type FahrplanPanelDefinition = { stops: string[], @@ -106,7 +107,7 @@ const FahrplanPanel = (props: {definition: FahrplanPanelDefinition}) => { <PanelWrapper> <PanelTitle title={"ÖPNV Monitor"}/> <PanelContent className={"flex flex-col"}> - <div className={"flex-1 flex flex-col gap-3"}> + <motion.div layout transition={{duration: .3, ease: "easeOut"}} className={"flex-1 flex flex-col gap-3"}> {routes.map((route) => ( <PlanElement key={route.uid} @@ -127,7 +128,7 @@ const FahrplanPanel = (props: {definition: FahrplanPanelDefinition}) => { </div> </div> )} - </div> + </motion.div> </PanelContent> </PanelWrapper> diff --git a/src/panels/Fahrplan/components/PlanElement.tsx b/src/panels/Fahrplan/components/PlanElement.tsx index 0f34b18..c938618 100644 --- a/src/panels/Fahrplan/components/PlanElement.tsx +++ b/src/panels/Fahrplan/components/PlanElement.tsx @@ -1,5 +1,5 @@ -import { motion } from 'framer-motion'; -import React from 'react'; +import {motion} from 'framer-motion'; +import React, {useEffect, useState} from 'react'; import ProgressIndicator from "./ProgressIndicator"; import classNames from "../../../util/classNames"; @@ -13,8 +13,55 @@ const PlanElement = (props: { delay?: number }[] }) => { + const [shown, setShown] = useState<boolean>(true); + + useEffect(() => { + const update = () => { + const latestStop = props.stops.reduce((accu, curr) => { + if (curr.arrival >= accu) { + return curr.arrival; + } + return accu; + }, new Date(0)); + + if ((new Date()).getTime() <= latestStop.getTime()) { + setShown(true); + } else { + setShown(false); + } + }; + + update(); + const updateInterval = setInterval(update, 1000); + + return () => { + clearInterval(updateInterval); + } + }, []); + return ( - <div> + <motion.div + className={"overflow-hidden"} + initial={{ + opacity: 0, + translateX: "-100%" + }} + animate={shown ? { + opacity: 1, + translateX: "0%", + marginTop: "0rem" + } : { + opacity: 0, + translateX: "100%", + height: 0, + marginTop: "-0.75rem" + }} + transition={{ + duration: .5, + ease: "easeOut", + staggerChildren: .3 + }} + > <div className={"flex flex-row gap-4 items-center font-semibold"}> <div className={classNames( "flex justify-center items-center text-lg h-10 w-20 leading-none", @@ -41,7 +88,7 @@ const PlanElement = (props: { )) } </motion.ol> - </div> + </motion.div> ); }; @@ -49,16 +96,16 @@ export default PlanElement; const trainIdentifierToColor = (identifier: string): string => { - if(identifier.startsWith("S")) { + if (identifier.startsWith("S")) { return "bg-green-700"; } - if(identifier.startsWith("X")) { + if (identifier.startsWith("X")) { return "bg-pink-700"; } // Fixme: This should just be "if first is number" - if(identifier.startsWith("4")) { + if (identifier.startsWith("4")) { return "bg-sky-700"; } @@ -67,7 +114,7 @@ const trainIdentifierToColor = (identifier: string): string => { const deDortmund = (input: string): string => { // Don't remove the city from central station location - if(input.toLowerCase().includes("HBf")) { + if (input.toLowerCase().includes("HBf")) { return input; } -- GitLab