popover.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. """Popover components."""
  2. from __future__ import annotations
  3. from typing import Any, Union
  4. from reflex.components.component import Component
  5. from reflex.components.libs.chakra import (
  6. ChakraComponent,
  7. LiteralChakraDirection,
  8. LiteralMenuStrategy,
  9. LiteralPopOverTrigger,
  10. )
  11. from reflex.vars import Var
  12. class Popover(ChakraComponent):
  13. """The wrapper that provides props, state, and context to its children."""
  14. tag = "Popover"
  15. # The padding required to prevent the arrow from reaching the very edge of the popper.
  16. arrow_padding: Var[int]
  17. # The `box-shadow` of the popover arrow
  18. arrow_shadow_color: Var[str]
  19. # The size of the popover arrow
  20. arrow_size: Var[int]
  21. # If true, focus will be transferred to the first interactive element when the popover opens
  22. auto_focus: Var[bool]
  23. # The boundary area for the popper. Used within the preventOverflow modifier
  24. boundary: Var[str]
  25. # If true, the popover will close when you blur out it by clicking outside or tabbing out
  26. close_on_blur: Var[bool]
  27. # If true, the popover will close when you hit the Esc key
  28. close_on_esc: Var[bool]
  29. # If true, the popover will be initially opened.
  30. default_is_open: Var[bool]
  31. # Theme direction ltr or rtl. Popper's placement will be set accordingly
  32. direction: Var[LiteralChakraDirection]
  33. # If true, the popper will change its placement and flip when it's about to overflow its boundary area.
  34. flip: Var[bool]
  35. # The distance or margin between the reference and popper. It is used internally to create an offset modifier. NB: If you define offset prop, it'll override the gutter.
  36. gutter: Var[int]
  37. # The html id attribute of the popover. If not provided, we generate a unique id. This id is also used to auto-generate the `aria-labelledby` and `aria-describedby` attributes that points to the PopoverHeader and PopoverBody
  38. id_: Var[str]
  39. # Performance 🚀: If true, the PopoverContent rendering will be deferred until the popover is open.
  40. is_lazy: Var[bool]
  41. # Performance 🚀: The lazy behavior of popover's content when not visible. Only works when `isLazy={true}` - "unmount": The popover's content is always unmounted when not open. - "keepMounted": The popover's content initially unmounted, but stays mounted when popover is open.
  42. lazy_behavior: Var[str]
  43. # If true, the popover will be opened in controlled mode.
  44. is_open: Var[bool]
  45. # If true, the popper will match the width of the reference at all times. It's useful for autocomplete, `date-picker` and select patterns.
  46. match_width: Var[bool]
  47. # The placement of the popover. It's used internally by Popper.js.
  48. placement: Var[str]
  49. # If true, will prevent the popper from being cut off and ensure it's visible within the boundary area.
  50. prevent_overflow: Var[bool]
  51. # If true, focus will be returned to the element that triggers the popover when it closes
  52. return_focus_on_close: Var[bool]
  53. # The CSS positioning strategy to use. ("fixed" | "absolute")
  54. strategy: Var[LiteralMenuStrategy]
  55. # The interaction that triggers the popover. hover - means the popover will open when you hover with mouse or focus with keyboard on the popover trigger click - means the popover will open on click or press Enter to Space on keyboard ("click" | "hover")
  56. trigger: Var[LiteralPopOverTrigger]
  57. def get_event_triggers(self) -> dict[str, Union[Var, Any]]:
  58. """Get the event triggers for the component.
  59. Returns:
  60. The event triggers.
  61. """
  62. return {
  63. **super().get_event_triggers(),
  64. "on_close": lambda: [],
  65. "on_open": lambda: [],
  66. }
  67. @classmethod
  68. def create(
  69. cls,
  70. *children,
  71. trigger=None,
  72. header=None,
  73. body=None,
  74. footer=None,
  75. use_close_button=False,
  76. **props,
  77. ) -> Component:
  78. """Create a popover component.
  79. Args:
  80. *children: The children of the component.
  81. trigger: The trigger that opens the popover.
  82. header: The header of the popover.
  83. body: The body of the popover.
  84. footer: The footer of the popover.
  85. use_close_button: Whether to add a close button on the popover.
  86. **props: The properties of the component.
  87. Returns:
  88. The popover component.
  89. """
  90. if len(children) == 0:
  91. contents = []
  92. trigger = PopoverTrigger.create(trigger)
  93. # add header if present in props
  94. if header:
  95. contents.append(PopoverHeader.create(header))
  96. if body:
  97. contents.append(PopoverBody.create(body))
  98. if footer:
  99. contents.append(PopoverFooter.create(footer))
  100. if use_close_button:
  101. contents.append(PopoverCloseButton.create())
  102. children = [trigger, PopoverContent.create(*contents)]
  103. return super().create(*children, **props)
  104. class PopoverContent(ChakraComponent):
  105. """The popover itself."""
  106. tag = "PopoverContent"
  107. class PopoverHeader(ChakraComponent):
  108. """The header of the popover."""
  109. tag = "PopoverHeader"
  110. class PopoverFooter(ChakraComponent):
  111. """Display a popover footer."""
  112. tag = "PopoverFooter"
  113. class PopoverBody(ChakraComponent):
  114. """The body of the popover."""
  115. tag = "PopoverBody"
  116. class PopoverArrow(ChakraComponent):
  117. """A visual arrow that points to the reference (or trigger)."""
  118. tag = "PopoverArrow"
  119. class PopoverCloseButton(ChakraComponent):
  120. """A button to close the popover."""
  121. tag = "PopoverCloseButton"
  122. class PopoverAnchor(ChakraComponent):
  123. """Used to wrap the position-reference element."""
  124. tag = "PopoverAnchor"
  125. class PopoverTrigger(ChakraComponent):
  126. """Used to wrap the reference (or trigger) element."""
  127. tag = "PopoverTrigger"