diff --git a/Caddyfile.dev b/Caddyfile.dev index 7f50e52..12b1d1c 100644 --- a/Caddyfile.dev +++ b/Caddyfile.dev @@ -1,7 +1,7 @@ timmypidashev.localhost { encode gzip - reverse_proxy landing:3000 + reverse_proxy web:3000 @backend_routes { path /_event/* diff --git a/src/web/web/components/navbar.py b/src/web/web/components/navbar.py index 578cd39..66b74bf 100644 --- a/src/web/web/components/navbar.py +++ b/src/web/web/components/navbar.py @@ -6,32 +6,27 @@ def navbar(): rx.center( rx.flex( rx.link( - rx.text("About", color=color["white"]), - href="http://about.timmypidashev.localhost" + rx.text("About", color=color["white"]), href="/about" ) ), rx.flex( rx.link( - rx.text("Projects", color=color["white"]), - href="http://projects.timmypidashev.localhost" + rx.text("Projects", color=color["white"]), href="/projects" ) ), rx.flex( rx.link( - rx.text("Resume", color=color["white"]), - href="http://resume.timmypidashev.localhost" + rx.text("Resume", color=color["white"]), href="/resume" ) ), rx.flex( rx.link( - rx.text("Blog", color=color["white"]), - href="http://blog.timmypidashev.localhost" + rx.text("Blog", color=color["white"]), href="/blog" ) ), rx.flex( rx.link( - rx.text("Shop", color=color["white"]), - href="http://shop.timmypidashev.localhost" + rx.text("Shop", color=color["white"]), href="shop" ) ), spacing="7", diff --git a/src/web/web/motion/__init__.py b/src/web/web/motion/__init__.py new file mode 100644 index 0000000..62c3358 --- /dev/null +++ b/src/web/web/motion/__init__.py @@ -0,0 +1 @@ +from .motion import * diff --git a/src/web/web/motion/motion.py b/src/web/web/motion/motion.py new file mode 100644 index 0000000..319db0c --- /dev/null +++ b/src/web/web/motion/motion.py @@ -0,0 +1,44 @@ +"""Reflex custom component Motion.""" + +import reflex as rx +from typing import Any, Dict, List, Optional, Set, Union + +class Motion(rx.Component): + """Motion component.""" + + # The React library to wrap. + library = "framer-motion" + + # The React component tag. + tag = "motion.div" + + # The initial state of the component. + initial: rx.Var[Dict[str, Union[float, str]]] + + # The animate state of the component. + animate: rx.Var[Dict[str, Union[float, str]]] + + # The transition + transition: rx.Var[Dict[str, Union[float, str]]] + + # What the component does when it's hovered. + while_hover: rx.Var[Dict[str, Union[float, str]]] + + # What the component does when it's tapped. + while_tap: rx.Var[Dict[str, Union[float, str]]] + + # What the component does when it's in view. + while_in_view: rx.Var[Dict[str, Union[float, str]]] + + # What the component does when its focused. + while_focus: rx.Var[Dict[str, Union[float, str]]] + + # What the component does when it's out of view. + viewport: rx.Var[Union[str, List[str]]] + + def _get_custom_code(self) -> str: + return """ + import { useIsPresent } from "framer-motion"; + """ + +motion = Motion.create diff --git a/src/web/web/pages/page404.py b/src/web/web/pages/page404.py index 2c18b77..0c65a96 100644 --- a/src/web/web/pages/page404.py +++ b/src/web/web/pages/page404.py @@ -1,15 +1,24 @@ import reflex as rx from web.templates import webpage +from web.motion import motion # TODO: Add a go back here link @webpage(path="/404", title="Page Not Found") def page404(): - return rx.center( - rx.vstack( - rx.heading("Whoops, this page doesn't exist...", size="9"), - rx.spacer(), + return rx.box( + rx.center( + rx.vstack( + motion( + rx.heading( + "Whoops, this page doesn't exist...", size="9" + ), + initial={"opacity": 0, "y": -50}, # Initial state: transparent and above the screen + animate={"opacity": 1, "y": 0, "transition": {"duration": 0.5, "ease": "easeInOut"}}, # Animate opacity to 1 and move down into view + while_hover={"scale": 1.1}, # Enlarge on hover + ) + ), + height="100vh", + width="100%", ), - height="100vh", - width="100%", ) diff --git a/src/web/web/templates/webpage.py b/src/web/web/templates/webpage.py index 575e846..02a3122 100644 --- a/src/web/web/templates/webpage.py +++ b/src/web/web/templates/webpage.py @@ -1,6 +1,7 @@ from typing import Callable import reflex as rx from web.route import Route +from web.motion import motion def webpage(path: str, title: str = "Timothy Pidashev", props=None) -> Callable: """This template wraps the webpage with the navbar and footer. @@ -39,12 +40,18 @@ def webpage(path: str, title: str = "Timothy Pidashev", props=None) -> Callable: from web.components.navbar import navbar from web.components.footer import footer - # Wrap the component in the template. + # Declare the entire page content return rx.box( - navbar(), - contents(*children, **props), - footer(), - **props, + motion( + rx.box( + navbar(), + contents(*children, **props), + footer(), + **props + ), + initial={"opacity": 0, "y": -50}, # Initial state: transparent and above the screen + animate={"opacity": 1, "y": 0, "transition": {"duration": 0.5, "ease": "easeInOut"}}, # Animate opacity to 1 and move down into view + ) ) return Route(