alertdialog.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. """Alert dialog components."""
  2. from typing import Set
  3. from pynecone.components.component import Component
  4. from pynecone.components.libs.chakra import ChakraComponent
  5. from pynecone.components.media.icon import Icon
  6. from pynecone.var import Var
  7. class AlertDialog(ChakraComponent):
  8. """Provides context and state for the dialog."""
  9. tag = "AlertDialog"
  10. # If true, the modal will be open.
  11. is_open: Var[bool]
  12. # The least destructive element to focus when the dialog opens.
  13. least_destructive_ref: Var[str]
  14. # Handle zoom/pinch gestures on iOS devices when scroll locking is enabled. Defaults to false.
  15. allow_pinch_zoom: Var[bool]
  16. # If true, the modal will autofocus the first enabled and interactive element within the ModalContent
  17. auto_focus: Var[bool]
  18. # If true, scrolling will be disabled on the body when the modal opens.
  19. block_scroll_on_mount: Var[bool]
  20. # If true, the modal will close when the Esc key is pressed
  21. close_on_esc: Var[bool]
  22. # If true, the modal will close when the overlay is clicked
  23. close_on_overlay_click: Var[bool]
  24. # If true, the modal will be centered on screen.
  25. is_centered: Var[bool]
  26. # 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.
  27. lock_focus_across_frames: Var[bool]
  28. # 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
  29. preserve_scroll_bar_gap: Var[bool]
  30. # If true, the modal will return focus to the element that triggered it when it closes.
  31. return_focus_on_close: Var[bool]
  32. # "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl" | "5xl" | "6xl" | "full"
  33. size: Var[str]
  34. # 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**
  35. use_inert: Var[bool]
  36. @classmethod
  37. def get_triggers(cls) -> Set[str]:
  38. """Get the event triggers for the component.
  39. Returns:
  40. The event triggers.
  41. """
  42. return super().get_triggers() | {
  43. "on_close",
  44. "on_close_complete",
  45. "on_esc",
  46. "on_overlay_click",
  47. }
  48. @classmethod
  49. def create(
  50. cls, *children, header=None, body=None, footer=None, close_button=None, **props
  51. ) -> Component:
  52. """Create an alert dialog component.
  53. Args:
  54. children: The children of the alert dialog component.
  55. header: The header of the alert dialog.
  56. body: The body of the alert dialog.
  57. footer: The footer of the alert dialog.
  58. close_button: The close button of the alert dialog.
  59. props: The properties of the alert dialog component.
  60. Raises:
  61. AttributeError: if there is a conflict between the props used.
  62. Returns:
  63. The alert dialog component.
  64. """
  65. if len(children) == 0:
  66. contents = []
  67. if header:
  68. contents.append(AlertDialogHeader.create(header))
  69. if body:
  70. contents.append(AlertDialogBody.create(body))
  71. if footer:
  72. contents.append(AlertDialogFooter.create(footer))
  73. # add AlertDialogCloseButton if either a prop for one was passed, or if on_close callback is present
  74. if props.get("on_close"):
  75. # get user defined close button or use default one
  76. if not close_button:
  77. close_button = Icon.create(tag="CloseIcon")
  78. contents.append(AlertDialogCloseButton.create(close_button))
  79. elif close_button:
  80. raise AttributeError(
  81. "Close button can not be used if on_close event handler is not defined"
  82. )
  83. children = [
  84. AlertDialogOverlay.create(
  85. AlertDialogContent.create(*contents),
  86. )
  87. ]
  88. return super().create(*children, **props)
  89. class AlertDialogBody(ChakraComponent):
  90. """Should contain the description announced by screen readers."""
  91. tag = "AlertDialogBody"
  92. class AlertDialogHeader(ChakraComponent):
  93. """Should contain the title announced by screen readers."""
  94. tag = "AlertDialogHeader"
  95. class AlertDialogFooter(ChakraComponent):
  96. """Should contain the events of the dialog."""
  97. tag = "AlertDialogFooter"
  98. class AlertDialogContent(ChakraComponent):
  99. """The wrapper for the alert dialog's content."""
  100. tag = "AlertDialogContent"
  101. class AlertDialogOverlay(ChakraComponent):
  102. """The dimmed overlay behind the dialog."""
  103. tag = "AlertDialogOverlay"
  104. class AlertDialogCloseButton(ChakraComponent):
  105. """The button that closes the dialog."""
  106. tag = "AlertDialogCloseButton"