/ libs / ui / src / components / dialog.rs
dialog.rs
  1  use dioxus::prelude::*;
  2  use dioxus_primitives::dialog;
  3  
  4  /// The props for the [`DialogRoot`] component
  5  #[derive(Props, Clone, PartialEq)]
  6  pub struct DialogRootProps {
  7      /// The ID of the dialog root element.
  8      pub id: ReadSignal<Option<String>>,
  9  
 10      /// Extra classes
 11      pub class: Option<String>,
 12  
 13      /// Whether the dialog is modal. If true, it will trap focus within the dialog when open.
 14      #[props(default = ReadSignal::new(Signal::new(true)))]
 15      pub is_modal: ReadSignal<bool>,
 16  
 17      /// The controlled `open` state of the dialog.
 18      pub open: ReadSignal<Option<bool>>,
 19  
 20      /// The default `open` state of the dialog if it is not controlled.
 21      #[props(default)]
 22      pub default_open: bool,
 23  
 24      /// A callback that is called when the open state changes.
 25      #[props(default)]
 26      pub on_open_change: Callback<bool>,
 27  
 28      /// Additional attributes to apply to the dialog root element.
 29      #[props(extends = GlobalAttributes)]
 30      pub attributes: Vec<Attribute>,
 31  
 32      /// The children of the dialog root component.
 33      pub children: Element,
 34  }
 35  
 36  #[component]
 37  pub fn DialogRoot(props: DialogRootProps) -> Element {
 38      let class = [
 39          "fixed inset-0 z-1000 flex items-center justify-center backdrop-blur-xs bg-black/40",
 40          props.class.as_deref().unwrap_or(""),
 41      ]
 42      .into_iter()
 43      .filter(|x| !x.is_empty())
 44      .collect::<Vec<_>>()
 45      .join(" ");
 46  
 47      rsx! {
 48          dialog::DialogRoot {
 49              id: props.id,
 50              class,
 51              is_modal: props.is_modal,
 52              open: props.open,
 53              default_open: props.default_open,
 54              on_open_change: props.on_open_change,
 55              attributes: props.attributes,
 56              {props.children}
 57          }
 58      }
 59  }
 60  
 61  /// The props for the [`DialogRoot`] component
 62  #[derive(Props, Clone, PartialEq)]
 63  pub struct DialogContentProps {
 64      /// The ID of the dialog content element.
 65      pub id: ReadSignal<Option<String>>,
 66      /// Extra classes
 67      #[props(default)]
 68      pub class: Option<String>,
 69      /// Additional attributes to apply to the dialog content element.
 70      #[props(extends = GlobalAttributes)]
 71      pub attributes: Vec<Attribute>,
 72      /// The children of the dialog content.
 73      pub children: Element,
 74  }
 75  
 76  #[component]
 77  pub fn DialogContent(props: DialogContentProps) -> Element {
 78      let class = [
 79          "flex flex-col border-border border-1 rounded-xl p-6 bg-background",
 80          props.class.as_deref().unwrap_or(""),
 81      ]
 82      .into_iter()
 83      .filter(|x| !x.is_empty())
 84      .collect::<Vec<_>>()
 85      .join(" ");
 86  
 87      rsx! {
 88          dialog::DialogContent { id: props.id, class, attributes: props.attributes, {props.children} }
 89      }
 90  }
 91  
 92  /// The props for the [`DialogTitle`] component
 93  #[derive(Props, Clone, PartialEq)]
 94  pub struct DialogTitleProps {
 95      /// The ID of the dialog title element.
 96      pub id: ReadSignal<Option<String>>,
 97      /// Extra classes
 98      pub class: Option<String>,
 99      /// Additional attributes for the dialog title element.
100      #[props(extends = GlobalAttributes)]
101      pub attributes: Vec<Attribute>,
102      /// The children of the dialog title.
103      pub children: Element,
104  }
105  
106  #[component]
107  pub fn DialogTitle(props: DialogTitleProps) -> Element {
108      let class = [
109          "text-lg font-semibold leading-none tracking-tight",
110          props.class.as_deref().unwrap_or(""),
111      ]
112      .into_iter()
113      .filter(|x| !x.is_empty())
114      .collect::<Vec<_>>()
115      .join(" ");
116  
117      rsx! {
118          dialog::DialogTitle { id: props.id, class, attributes: props.attributes, {props.children} }
119      }
120  }
121  
122  /// The props for the [`DialogDescription`] component
123  #[derive(Props, Clone, PartialEq)]
124  pub struct DialogDescriptionProps {
125      /// The ID of the dialog description element.
126      pub id: ReadSignal<Option<String>>,
127      /// Extra classes
128      pub class: Option<String>,
129      /// Additional attributes for the dialog description element.
130      #[props(extends = GlobalAttributes)]
131      pub attributes: Vec<Attribute>,
132      /// The children of the dialog description.
133      pub children: Element,
134  }
135  
136  #[component]
137  pub fn DialogDescription(props: DialogDescriptionProps) -> Element {
138      let class = [
139          "text-sm text-muted-foreground",
140          props.class.as_deref().unwrap_or(""),
141      ]
142      .into_iter()
143      .filter(|x| !x.is_empty())
144      .collect::<Vec<_>>()
145      .join(" ");
146  
147      rsx! {
148          dialog::DialogDescription { id: props.id, class, attributes: props.attributes, {props.children} }
149      }
150  }