drawer.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. """Container to stack elements with spacing."""
  2. from __future__ import annotations
  3. from typing import Any, Optional, Union
  4. from reflex.components.chakra import (
  5. ChakraComponent,
  6. LiteralColorScheme,
  7. LiteralDrawerSize,
  8. )
  9. from reflex.components.chakra.media.icon import Icon
  10. from reflex.components.component import Component
  11. from reflex.vars import Var
  12. class Drawer(ChakraComponent):
  13. """A drawer component."""
  14. tag = "Drawer"
  15. # If true, the modal will be open.
  16. is_open: Optional[Var[bool]] = None
  17. # Handle zoom/pinch gestures on iOS devices when scroll locking is enabled. Defaults to false.
  18. allow_pinch_zoom: Optional[Var[bool]] = None
  19. # If true, the modal will autofocus the first enabled and interactive element within the ModalContent
  20. auto_focus: Optional[Var[bool]] = None
  21. # If true, scrolling will be disabled on the body when the modal opens.
  22. block_scroll_on_mount: Optional[Var[bool]] = None
  23. # If true, the modal will close when the Esc key is pressed
  24. close_on_esc: Optional[Var[bool]] = None
  25. # If true, the modal will close when the overlay is clicked
  26. close_on_overlay_click: Optional[Var[bool]] = None
  27. # If true, the modal will be centered on screen.
  28. is_centered: Optional[Var[bool]] = None
  29. # If true and drawer's placement is top or bottom, the drawer will occupy the viewport height (100vh)
  30. is_full_height: Optional[Var[bool]] = None
  31. # Enables aggressive focus capturing within iframes. - If true: keep focus in the lock, no matter where lock is active - If false: allows focus to move outside of iframe
  32. lock_focus_across_frames: Optional[Var[bool]] = None
  33. # The placement of the drawer
  34. placement: Optional[Var[str]] = None
  35. # If true, a `padding-right` will be applied to the body element that's equal to the width of the scrollbar. This can help prevent some unpleasant flickering effect and content adjustment when the modal opens
  36. preserve_scroll_bar_gap: Optional[Var[bool]] = None
  37. # If true, the modal will return focus to the element that triggered it when it closes.
  38. return_focus_on_close: Optional[Var[bool]] = None
  39. # "xs" | "sm" | "md" | "lg" | "xl" | "full"
  40. size: Optional[Var[LiteralDrawerSize]] = None
  41. # A11y: If true, the siblings of the modal will have `aria-hidden` set to true so that screen readers can only see the modal. This is commonly known as making the other elements **inert**
  42. use_inert: Optional[Var[bool]] = None
  43. # Variant of drawer
  44. variant: Optional[Var[str]] = None
  45. # Color scheme of the Drawer
  46. # Options:
  47. # "whiteAlpha" | "blackAlpha" | "gray" | "red" | "orange" | "yellow" | "green" | "teal" | "blue" | "cyan"
  48. # | "purple" | "pink" | "linkedin" | "facebook" | "messenger" | "whatsapp" | "twitter" | "telegram"
  49. color_scheme: Optional[Var[LiteralColorScheme]] = None
  50. def get_event_triggers(self) -> dict[str, Union[Var, Any]]:
  51. """Get the event triggers for the component.
  52. Returns:
  53. The event triggers.
  54. """
  55. return {
  56. **super().get_event_triggers(),
  57. "on_close": lambda: [],
  58. "on_close_complete": lambda: [],
  59. "on_esc": lambda: [],
  60. "on_overlay_click": lambda: [],
  61. }
  62. @classmethod
  63. def create(
  64. cls, *children, header=None, body=None, footer=None, close_button=None, **props
  65. ) -> Component:
  66. """Create a drawer component.
  67. Args:
  68. *children: The children of the drawer component.
  69. header: The header of the drawer.
  70. body: The body of the drawer.
  71. footer: The footer of the drawer.
  72. close_button: The close button of the drawer.
  73. **props: The properties of the drawer component.
  74. Raises:
  75. AttributeError: error that occurs if conflicting props are passed
  76. Returns:
  77. The drawer component.
  78. """
  79. if len(children) == 0:
  80. contents = []
  81. if header:
  82. contents.append(DrawerHeader.create(header))
  83. if body:
  84. contents.append(DrawerBody.create(body))
  85. if footer:
  86. contents.append(DrawerFooter.create(footer))
  87. if props.get("on_close"):
  88. # use default close button if undefined
  89. if not close_button:
  90. close_button = Icon.create(tag="close")
  91. contents.append(DrawerCloseButton.create(close_button))
  92. elif close_button:
  93. raise AttributeError(
  94. "Close button can not be used if on_close event handler is not defined"
  95. )
  96. children = [
  97. DrawerOverlay.create(
  98. DrawerContent.create(*contents),
  99. )
  100. ]
  101. return super().create(*children, **props)
  102. class DrawerBody(ChakraComponent):
  103. """Drawer body."""
  104. tag = "DrawerBody"
  105. class DrawerHeader(ChakraComponent):
  106. """Drawer header."""
  107. tag = "DrawerHeader"
  108. class DrawerFooter(ChakraComponent):
  109. """Drawer footer."""
  110. tag = "DrawerFooter"
  111. class DrawerOverlay(ChakraComponent):
  112. """Drawer overlay."""
  113. tag = "DrawerOverlay"
  114. class DrawerContent(ChakraComponent):
  115. """Drawer content."""
  116. tag = "DrawerContent"
  117. class DrawerCloseButton(ChakraComponent):
  118. """Drawer close button."""
  119. tag = "DrawerCloseButton"