reflex/reflex/.templates/apps/sidebar/code/templates/template.py
2024-04-02 11:48:34 -07:00

145 lines
3.8 KiB
Python

"""Common templates used between pages in the app."""
from __future__ import annotations
from code import styles
from code.components.sidebar import sidebar
from typing import Callable
import reflex as rx
# Meta tags for the app.
default_meta = [
{
"name": "viewport",
"content": "width=device-width, shrink-to-fit=no, initial-scale=1",
},
]
def menu_item_link(text, href):
return rx.menu.item(
rx.link(
text,
href=href,
width="100%",
color="inherit",
),
_hover={
"color": styles.accent_color,
"background_color": styles.accent_text_color,
},
)
def menu_button() -> rx.Component:
"""The menu button on the top right of the page.
Returns:
The menu button component.
"""
from reflex.page import get_decorated_pages
return rx.box(
rx.menu.root(
rx.menu.trigger(
rx.button(
rx.icon("menu"),
variant="soft",
)
),
rx.menu.content(
*[
menu_item_link(page["title"], page["route"])
for page in get_decorated_pages()
],
rx.menu.separator(),
menu_item_link("About", "https://github.com/reflex-dev"),
menu_item_link("Contact", "mailto:founders@=reflex.dev"),
),
),
position="fixed",
right="2em",
top="2em",
z_index="500",
)
class ThemeState(rx.State):
"""The state for the theme of the app."""
accent_color: str = "crimson"
gray_color: str = "gray"
def template(
route: str | None = None,
title: str | None = None,
description: str | None = None,
meta: str | None = None,
script_tags: list[rx.Component] | None = None,
on_load: rx.event.EventHandler | list[rx.event.EventHandler] | None = None,
) -> Callable[[Callable[[], rx.Component]], rx.Component]:
"""The template for each page of the app.
Args:
route: The route to reach the page.
title: The title of the page.
description: The description of the page.
meta: Additionnal meta to add to the page.
on_load: The event handler(s) called when the page load.
script_tags: Scripts to attach to the page.
Returns:
The template with the page content.
"""
def decorator(page_content: Callable[[], rx.Component]) -> rx.Component:
"""The template for each page of the app.
Args:
page_content: The content of the page.
Returns:
The template with the page content.
"""
# Get the meta tags for the page.
all_meta = [*default_meta, *(meta or [])]
def templated_page():
return rx.hstack(
sidebar(),
rx.box(
rx.box(
page_content(),
**styles.template_content_style,
),
**styles.template_page_style,
),
menu_button(),
align="start",
background=f"radial-gradient(circle at top right, {rx.color('accent', 2)}, {rx.color('mauve', 1)});",
position="relative",
)
@rx.page(
route=route,
title=title,
description=description,
meta=all_meta,
script_tags=script_tags,
on_load=on_load,
)
def theme_wrap():
return rx.theme(
templated_page(),
has_background=True,
accent_color=ThemeState.accent_color,
gray_color=ThemeState.gray_color,
)
return theme_wrap
return decorator