atproto blogging
1use dioxus::prelude::*;
2use dioxus_primitives::dialog::{
3 self, DialogContentProps, DialogDescriptionProps, DialogRootProps, DialogTitleProps,
4};
5
6const DIALOG_CSS: Asset = asset!("./dialog.css");
7
8/// Fixed-position overlay that works in both SSR and client-only modes.
9/// Wraps dioxus_primitives DialogRoot with inline positioning styles
10/// since the CSS file doesn't load reliably in client-only mode.
11#[component]
12pub fn DialogRoot(props: DialogRootProps) -> Element {
13 let is_open = props.open.read().unwrap_or(false);
14
15 let overlay_style = if is_open {
16 "position: fixed; inset: 0; z-index: 1000; background: rgba(0,0,0,0.3); display: flex; align-items: center; justify-content: center;"
17 } else {
18 "display: none;"
19 };
20
21 rsx! {
22 document::Link { rel: "stylesheet", href: DIALOG_CSS }
23 div {
24 style: "{overlay_style}",
25 onclick: {
26 let on_change = props.on_open_change.clone();
27 move |_| {
28 on_change.call(false);
29 }
30 },
31 dialog::DialogRoot {
32 class: "dialog-backdrop-inner",
33 id: props.id,
34 is_modal: props.is_modal,
35 open: props.open,
36 default_open: props.default_open,
37 on_open_change: props.on_open_change,
38 attributes: props.attributes,
39 {props.children}
40 }
41 }
42 }
43}
44
45#[component]
46pub fn DialogContent(props: DialogContentProps) -> Element {
47 rsx! {
48 div {
49 onclick: move |e| e.stop_propagation(),
50 dialog::DialogContent {
51 class: "dialog",
52 id: props.id,
53 attributes: props.attributes,
54 {props.children}
55 }
56 }
57 }
58}
59
60#[component]
61pub fn DialogTitle(props: DialogTitleProps) -> Element {
62 rsx! {
63 dialog::DialogTitle {
64 class: "dialog-title",
65 id: props.id,
66 attributes: props.attributes,
67 {props.children}
68 }
69 }
70}
71
72#[component]
73pub fn DialogDescription(props: DialogDescriptionProps) -> Element {
74 rsx! {
75 dialog::DialogDescription {
76 class: "dialog-description",
77 id: props.id,
78 attributes: props.attributes,
79 {props.children}
80 }
81 }
82}