123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- """Drawer components based on Radix primitives."""
- # Based on Vaul: https://github.com/emilkowalski/vaul
- # Style based on https://ui.shadcn.com/docs/components/drawer
- from __future__ import annotations
- from collections.abc import Sequence
- from typing import Any, Literal
- from reflex.components.component import Component, ComponentNamespace
- from reflex.components.radix.primitives.base import RadixPrimitiveComponent
- from reflex.components.radix.themes.base import Theme
- from reflex.components.radix.themes.layout.flex import Flex
- from reflex.constants.compiler import MemoizationMode
- from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
- from reflex.vars.base import Var
- class DrawerComponent(RadixPrimitiveComponent):
- """A Drawer component."""
- library = "vaul@1.1.2"
- lib_dependencies: list[str] = ["@radix-ui/react-dialog@1.1.13"]
- LiteralDirectionType = Literal["top", "bottom", "left", "right"]
- class DrawerRoot(DrawerComponent):
- """The Root component of a Drawer, contains all parts of a drawer."""
- tag = "Drawer.Root"
- alias = "Vaul" + tag
- # The open state of the drawer when it is initially rendered. Use when you do not need to control its open state.
- default_open: Var[bool]
- # Whether the drawer is open or not.
- open: Var[bool]
- # Fires when the drawer is opened or closed.
- on_open_change: EventHandler[passthrough_event_spec(bool)]
- # When `False`, it allows interaction with elements outside of the drawer without closing it. Defaults to `True`.
- modal: Var[bool]
- # Direction of the drawer. This adjusts the animations and the drag direction. Defaults to `"bottom"`
- direction: Var[LiteralDirectionType]
- # Gets triggered after the open or close animation ends, it receives an open argument with the open state of the drawer by the time the function was triggered.
- on_animation_end: EventHandler[passthrough_event_spec(bool)]
- # When `False`, dragging, clicking outside, pressing esc, etc. will not close the drawer. Use this in combination with the open prop, otherwise you won't be able to open/close the drawer.
- dismissible: Var[bool]
- # When `True`, dragging will only be possible by the handle.
- handle_only: Var[bool]
- # Array of numbers from 0 to 100 that corresponds to % of the screen a given snap point should take up. Should go from least visible. Also Accept px values, which doesn't take screen height into account.
- snap_points: Sequence[str | float] | None
- # Index of a snapPoint from which the overlay fade should be applied. Defaults to the last snap point.
- fade_from_index: Var[int]
- # Duration for which the drawer is not draggable after scrolling content inside of the drawer. Defaults to 500ms
- scroll_lock_timeout: Var[int]
- # When `True`, it prevents scroll restoration. Defaults to `True`.
- prevent_scroll_restoration: Var[bool]
- # Enable background scaling, it requires container element with `vaul-drawer-wrapper` attribute to scale its background.
- should_scale_background: Var[bool]
- # Number between 0 and 1 that determines when the drawer should be closed.
- close_threshold: Var[float]
- class DrawerTrigger(DrawerComponent):
- """The button that opens the dialog."""
- tag = "Drawer.Trigger"
- alias = "Vaul" + tag
- # Defaults to true, if the first child acts as the trigger.
- as_child: Var[bool] = Var.create(True)
- _memoization_mode = MemoizationMode(recursive=False)
- @classmethod
- def create(cls, *children: Any, **props: Any) -> Component:
- """Create a new DrawerTrigger instance.
- Args:
- *children: The children of the element.
- **props: The properties of the element.
- Returns:
- The new DrawerTrigger instance.
- """
- for child in children:
- if "on_click" in getattr(child, "event_triggers", {}):
- children = (Flex.create(*children),)
- break
- return super().create(*children, **props)
- class DrawerPortal(DrawerComponent):
- """Portals your drawer into the body."""
- tag = "Drawer.Portal"
- alias = "Vaul" + tag
- # Based on https://www.radix-ui.com/primitives/docs/components/dialog#content
- class DrawerContent(DrawerComponent):
- """Content that should be rendered in the drawer."""
- tag = "Drawer.Content"
- alias = "Vaul" + tag
- # Style set partially based on the source code at https://ui.shadcn.com/docs/components/drawer
- def _get_style(self) -> dict:
- """Get the style for the component.
- Returns:
- The dictionary of the component style as value and the style notation as key.
- """
- base_style = {
- "left": "0",
- "right": "0",
- "bottom": "0",
- "top": "0",
- "position": "fixed",
- "z_index": 50,
- "display": "flex",
- }
- style = self.style or {}
- base_style.update(style)
- return {"css": base_style}
- # Fired when the drawer content is opened.
- on_open_auto_focus: EventHandler[no_args_event_spec]
- # Fired when the drawer content is closed.
- on_close_auto_focus: EventHandler[no_args_event_spec]
- # Fired when the escape key is pressed.
- on_escape_key_down: EventHandler[no_args_event_spec]
- # Fired when the pointer is down outside the drawer content.
- on_pointer_down_outside: EventHandler[no_args_event_spec]
- # Fired when interacting outside the drawer content.
- on_interact_outside: EventHandler[no_args_event_spec]
- @classmethod
- def create(cls, *children, **props):
- """Create a Drawer Content.
- We wrap the Drawer content in an `rx.theme` to make radix themes definitions available to
- rendered div in the DOM. This is because Vaul Drawer injects the Drawer overlay content in a sibling
- div to the root div rendered by radix which contains styling definitions. Wrapping in `rx.theme`
- makes the styling available to the overlay.
- Args:
- *children: The list of children to use.
- **props: Additional properties to apply to the drawer content.
- Returns:
- The drawer content.
- """
- comp = super().create(*children, **props)
- return Theme.create(comp)
- class DrawerOverlay(DrawerComponent):
- """A layer that covers the inert portion of the view when the dialog is open."""
- tag = "Drawer.Overlay"
- alias = "Vaul" + tag
- # Style set based on the source code at https://ui.shadcn.com/docs/components/drawer
- def _get_style(self) -> dict:
- """Get the style for the component.
- Returns:
- The dictionary of the component style as value and the style notation as key.
- """
- base_style = {
- "position": "fixed",
- "left": "0",
- "right": "0",
- "bottom": "0",
- "top": "0",
- "z_index": 50,
- "background": "rgba(0, 0, 0, 0.5)",
- }
- style = self.style or {}
- base_style.update(style)
- return {"css": base_style}
- class DrawerClose(DrawerTrigger):
- """A button that closes the drawer."""
- tag = "Drawer.Close"
- alias = "Vaul" + tag
- class DrawerTitle(DrawerComponent):
- """A title for the drawer."""
- tag = "Drawer.Title"
- alias = "Vaul" + tag
- # Style set based on the source code at https://ui.shadcn.com/docs/components/drawer
- def _get_style(self) -> dict:
- """Get the style for the component.
- Returns:
- The dictionary of the component style as value and the style notation as key.
- """
- base_style = {
- "font-size": "1.125rem",
- "font-weight": "600",
- "line-weight": "1",
- "letter-spacing": "-0.05em",
- }
- style = self.style or {}
- base_style.update(style)
- return {"css": base_style}
- class DrawerDescription(DrawerComponent):
- """A description for the drawer."""
- tag = "Drawer.Description"
- alias = "Vaul" + tag
- # Style set based on the source code at https://ui.shadcn.com/docs/components/drawer
- def _get_style(self) -> dict:
- """Get the style for the component.
- Returns:
- The dictionary of the component style as value and the style notation as key.
- """
- base_style = {
- "font-size": "0.875rem",
- }
- style = self.style or {}
- base_style.update(style)
- return {"css": base_style}
- class DrawerHandle(DrawerComponent):
- """A description for the drawer."""
- tag = "Drawer.Handle"
- alias = "Vaul" + tag
- class Drawer(ComponentNamespace):
- """A namespace for Drawer components."""
- root = __call__ = staticmethod(DrawerRoot.create)
- trigger = staticmethod(DrawerTrigger.create)
- portal = staticmethod(DrawerPortal.create)
- content = staticmethod(DrawerContent.create)
- overlay = staticmethod(DrawerOverlay.create)
- close = staticmethod(DrawerClose.create)
- title = staticmethod(DrawerTitle.create)
- description = staticmethod(DrawerDescription.create)
- handle = staticmethod(DrawerHandle.create)
- drawer = Drawer()
|