123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- """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 types import SimpleNamespace
- from typing import Any, Dict, List, Literal, Optional, Union
- from reflex.components.radix.primitives.base import RadixPrimitiveComponentWithClassName
- from reflex.constants import EventTriggers
- from reflex.vars import Var
- class DrawerComponent(RadixPrimitiveComponentWithClassName):
- """A Drawer component."""
- library = "vaul"
- lib_dependencies: List[str] = ["@radix-ui/react-dialog@^1.0.5"]
- LiteralDirectionType = Literal[
- "top",
- "bottom",
- "left",
- "right",
- ]
- class DrawerRoot(DrawerComponent):
- """The Root component of a Drawer, contains all parts of a drawer."""
- tag = "Drawer.Root"
- # Whether the drawer is open or not.
- open: Var[bool]
- # Enable background scaling,
- # it requires an element with [vaul-drawer-wrapper] data 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]
- # 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: Optional[List[Union[str, float]]]
- # Index of a snapPoint from which the overlay fade should be applied.
- # Defaults to the last snap point.
- # TODO: will it accept -1 then?
- 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 `False`, it allows to interact with elements outside of the drawer without closing it.
- # Defaults to `True`.
- modal: Var[bool]
- # Direction of the drawer. Defaults to `"bottom"`
- direction: Var[LiteralDirectionType]
- # When `True`, it prevents scroll restoration
- # when the drawer is closed after a navigation happens inside of it.
- # Defaults to `True`.
- preventScrollRestoration: Var[bool]
- def get_event_triggers(self) -> Dict[str, Any]:
- """Get the event triggers that pass the component's value to the handler.
- Returns:
- A dict mapping the event trigger to the var that is passed to the handler.
- """
- return {
- **super().get_event_triggers(),
- EventTriggers.ON_OPEN_CHANGE: lambda e0: [e0.target.value],
- }
- class DrawerTrigger(DrawerComponent):
- """The button that opens the dialog."""
- tag = "Drawer.Trigger"
- as_child: Var[bool]
- class DrawerPortal(DrawerComponent):
- """Portals your drawer into the body."""
- tag = "Drawer.Portal"
- # 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"
- # 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)
- self.style.update(
- {
- "css": base_style,
- }
- )
- return self.style
- def get_event_triggers(self) -> Dict[str, Any]:
- """Get the events triggers signatures for the component.
- Returns:
- The signatures of the event triggers.
- """
- return {
- **super().get_event_triggers(),
- # DrawerContent is based on Radix DialogContent
- # These are the same triggers as DialogContent
- EventTriggers.ON_OPEN_AUTO_FOCUS: lambda e0: [e0.target.value],
- EventTriggers.ON_CLOSE_AUTO_FOCUS: lambda e0: [e0.target.value],
- EventTriggers.ON_ESCAPE_KEY_DOWN: lambda e0: [e0.target.value],
- EventTriggers.ON_POINTER_DOWN_OUTSIDE: lambda e0: [e0.target.value],
- EventTriggers.ON_INTERACT_OUTSIDE: lambda e0: [e0.target.value],
- }
- class DrawerOverlay(DrawerComponent):
- """A layer that covers the inert portion of the view when the dialog is open."""
- tag = "Drawer.Overlay"
- # 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.8)",
- }
- style = self.style or {}
- base_style.update(style)
- self.style.update(
- {
- "css": base_style,
- }
- )
- return self.style
- class DrawerClose(DrawerComponent):
- """A button that closes the drawer."""
- tag = "Drawer.Close"
- class DrawerTitle(DrawerComponent):
- """A title for the drawer."""
- tag = "Drawer.Title"
- # 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)
- self.style.update(
- {
- "css": base_style,
- }
- )
- return self.style
- class DrawerDescription(DrawerComponent):
- """A description for the drawer."""
- tag = "Drawer.Description"
- # 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)
- self.style.update(
- {
- "css": base_style,
- }
- )
- return self.style
- class Drawer(SimpleNamespace):
- """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)
- drawer = Drawer()
|