accordion.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. """Container to stack elements with spacing."""
  2. from typing import List, Optional, Union
  3. from reflex.components.chakra import ChakraComponent
  4. from reflex.components.component import Component
  5. from reflex.vars import Var
  6. class BaseAccordion(ChakraComponent):
  7. """The base accordion component."""
  8. library = "@chakra-ui/accordion@2.3.1"
  9. class Accordion(BaseAccordion):
  10. """The wrapper that uses cloneElement to pass props to AccordionItem children."""
  11. tag = "Accordion"
  12. # If true, multiple accordion items can be expanded at once.
  13. allow_multiple: Var[bool]
  14. # If true, any expanded accordion item can be collapsed again.
  15. allow_toggle: Var[bool]
  16. # The initial index(es) of the expanded accordion item(s).
  17. default_index: Var[Optional[List[int]]]
  18. # The index(es) of the expanded accordion item
  19. index: Var[Union[int, List[int]]]
  20. # If true, height animation and transitions will be disabled.
  21. reduce_motion: Var[bool]
  22. @classmethod
  23. def create(
  24. cls,
  25. *children,
  26. items=None,
  27. icon_pos="right",
  28. allow_multiple: Optional[Var[bool]] = None,
  29. allow_toggle: Optional[Var[bool]] = None,
  30. **props
  31. ) -> Component:
  32. """Create an accordion component.
  33. Args:
  34. *children: The children of the component.
  35. items: The items of the accordion component: list of tuples (label,panel)
  36. icon_pos: The position of the arrow icon of the accordion. "right", "left" or None
  37. allow_multiple: The allow_multiple property of the accordion. (True or False)
  38. allow_toggle: The allow_toggle property of the accordion. (True or False)
  39. **props: The properties of the component.
  40. Returns:
  41. The accordion component
  42. """
  43. if len(children) == 0:
  44. children = []
  45. if not items:
  46. items = []
  47. for label, panel in items:
  48. if icon_pos == "right":
  49. button = AccordionButton.create(label, AccordionIcon.create())
  50. elif icon_pos == "left":
  51. button = AccordionButton.create(AccordionIcon.create(), label)
  52. else:
  53. button = AccordionButton.create(label)
  54. children.append(
  55. AccordionItem.create(
  56. button,
  57. AccordionPanel.create(panel),
  58. )
  59. )
  60. # if allow_multiple is True, allow_toggle is implicitely used and does not need to be defined
  61. if allow_multiple:
  62. props.update({"allow_multiple": allow_multiple})
  63. elif allow_toggle:
  64. props.update({"allow_toggle": allow_toggle})
  65. return super().create(*children, **props)
  66. class AccordionItem(BaseAccordion):
  67. """A single accordion item."""
  68. tag = "AccordionItem"
  69. # A unique id for the accordion item.
  70. id_: Var[str]
  71. # If true, the accordion item will be disabled.
  72. is_disabled: Var[bool]
  73. # If true, the accordion item will be focusable.
  74. is_focusable: Var[bool]
  75. class AccordionButton(BaseAccordion):
  76. """The button that toggles the expand/collapse state of the accordion item. This button must be wrapped in an element with role heading."""
  77. tag = "AccordionButton"
  78. class AccordionPanel(BaseAccordion):
  79. """The container for the details to be revealed."""
  80. tag = "AccordionPanel"
  81. class AccordionIcon(BaseAccordion):
  82. """A chevron-down icon that rotates based on the expanded/collapsed state."""
  83. tag = "AccordionIcon"