sidebar.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. """Sidebar component for the app."""
  2. from boppersbizza import styles
  3. import reflex as rx
  4. def sidebar_header() -> rx.Component:
  5. """Sidebar header.
  6. Returns:
  7. The sidebar header component.
  8. """
  9. return rx.hstack(
  10. # The logo.
  11. rx.color_mode_cond(
  12. rx.image(src="/reflex_black.svg", height="2em"),
  13. rx.image(src="/reflex_white.svg", height="2em"),
  14. ),
  15. rx.spacer(),
  16. # Link to Reflex GitHub repo.
  17. rx.link(
  18. rx.center(
  19. rx.image(
  20. src="/github.svg",
  21. height="3em",
  22. padding="0.5em",
  23. ),
  24. box_shadow=styles.box_shadow,
  25. bg="transparent",
  26. border_radius=styles.border_radius,
  27. _hover={
  28. "bg": styles.accent_color,
  29. },
  30. ),
  31. href="https://github.com/reflex-dev/reflex",
  32. ),
  33. align="center",
  34. width="100%",
  35. border_bottom=styles.border,
  36. padding="1em",
  37. )
  38. def sidebar_footer() -> rx.Component:
  39. """Sidebar footer.
  40. Returns:
  41. The sidebar footer component.
  42. """
  43. return rx.hstack(
  44. rx.spacer(),
  45. rx.link(
  46. rx.text("Docs"),
  47. href="https://reflex.dev/docs/getting-started/introduction/",
  48. style=styles.link_style,
  49. ),
  50. rx.link(
  51. rx.text("Blog"),
  52. href="https://reflex.dev/blog/",
  53. style=styles.link_style,
  54. ),
  55. width="100%",
  56. border_top=styles.border,
  57. padding="1em",
  58. )
  59. def sidebar_item(text: str, icon: str, url: str) -> rx.Component:
  60. """Sidebar item.
  61. Args:
  62. text: The text of the item.
  63. icon: The icon of the item.
  64. url: The URL of the item.
  65. Returns:
  66. rx.Component: The sidebar item component.
  67. """
  68. # Whether the item is active.
  69. active = (rx.State.router.page.path == f"/{text.lower()}") | (
  70. (rx.State.router.page.path == "/") & text == "Home"
  71. )
  72. return rx.link(
  73. rx.hstack(
  74. rx.image(
  75. src=icon,
  76. height="2.5em",
  77. padding="0.5em",
  78. ),
  79. rx.text(
  80. text,
  81. ),
  82. bg=rx.cond(
  83. active,
  84. styles.accent_color,
  85. "transparent",
  86. ),
  87. color=rx.cond(
  88. active,
  89. styles.accent_text_color,
  90. styles.text_color,
  91. ),
  92. align="center",
  93. border_radius=styles.border_radius,
  94. box_shadow=styles.box_shadow,
  95. width="100%",
  96. padding_x="1em",
  97. ),
  98. href=url,
  99. width="100%",
  100. )
  101. def sidebar() -> rx.Component:
  102. """The sidebar.
  103. Returns:
  104. The sidebar component.
  105. """
  106. # Get all the decorated pages and add them to the sidebar.
  107. from reflex.page import get_decorated_pages
  108. return rx.box(
  109. rx.vstack(
  110. sidebar_header(),
  111. rx.vstack(
  112. *[
  113. sidebar_item(
  114. text=page.get("title", page["route"].strip("/").capitalize()),
  115. icon=page.get("image", "/github.svg"),
  116. url=page["route"],
  117. )
  118. for page in get_decorated_pages()
  119. ],
  120. width="100%",
  121. overflow_y="auto",
  122. align_items="flex-start",
  123. padding="1em",
  124. ),
  125. rx.spacer(),
  126. sidebar_footer(),
  127. height="100dvh",
  128. ),
  129. display=["none", "none", "block"],
  130. min_width=styles.sidebar_width,
  131. height="100%",
  132. position="sticky",
  133. top="0px",
  134. border_right=styles.border,
  135. )