1use crate::icon::{Icon, IconKind};
2use dioxus::prelude::*;
3
4#[derive(Clone, Copy, PartialEq, Debug, Default)]
5pub enum DrawerPosition {
6 Left,
7 #[default]
8 Right,
9}
10
11#[derive(Clone, Copy, PartialEq, Debug, Default)]
12pub enum DrawerSize {
13 Sm,
14 #[default]
15 Md,
16 Lg,
17}
18
19impl DrawerSize {
20 pub fn scss_class(&self) -> &'static str {
21 match self {
22 DrawerSize::Sm => "sd-drawer-panel--sm",
23 DrawerSize::Md => "sd-drawer-panel--md",
24 DrawerSize::Lg => "sd-drawer-panel--lg",
25 }
26 }
27}
28
29#[component]
30pub fn Drawer(
31 is_open: Signal<bool>,
32 #[props(default)] title: Option<String>,
33 #[props(default)] position: DrawerPosition,
34 #[props(default)] size: DrawerSize,
35 #[props(default)] glow: Option<bool>,
36 #[props(default)] class: String,
37 children: Element,
38) -> Element {
39 if !*is_open.read() {
40 return rsx! {};
41 }
42
43 #[cfg(feature = "theme")]
44 let theme_val = crate::theme::use_theme()();
45 #[cfg(feature = "theme")]
46 let base_override = theme_val.resolve_component_base("drawer").unwrap_or("");
47 #[cfg(feature = "theme")]
48 let class_modifiers = theme_val.resolve_class_modifiers("drawer", &class);
49 #[cfg(feature = "theme")]
50 let glow_class = theme_val.resolve_elevation_class("drawer", glow);
51
52 #[cfg(not(feature = "theme"))]
53 let base_override = "";
54 #[cfg(not(feature = "theme"))]
55 let class_modifiers = String::new();
56 #[cfg(not(feature = "theme"))]
57 let glow_class = if glow.unwrap_or(false) {
58 "sd-drawer-panel--glow".to_string()
59 } else {
60 String::new()
61 };
62
63 #[cfg(feature = "animation")]
64 let anim_class = match position {
65 DrawerPosition::Left => crate::animation::Animations::DRAWER_LEFT,
66 DrawerPosition::Right => crate::animation::Animations::DRAWER_RIGHT,
67 };
68 #[cfg(not(feature = "animation"))]
69 let anim_class = match position {
70 DrawerPosition::Left => "animate-drawer-slide-left",
71 DrawerPosition::Right => "animate-drawer-slide-right",
72 };
73
74 let pos_class = match position {
75 DrawerPosition::Left => "sd-drawer-panel--left",
76 DrawerPosition::Right => "sd-drawer-panel--right",
77 };
78 let size_class = size.scss_class();
79
80 rsx! {
81 div {
82 class: "sd-drawer-backdrop",
83 onclick: move |_| *is_open.write() = false,
84 div {
85 class: "sd-drawer-panel {base_override} {pos_class} {size_class} {glow_class} {anim_class} {class_modifiers} {class}",
86 onclick: move |e| e.stop_propagation(),
87 div { class: "sd-drawer__header",
88 h3 { class: "sd-drawer__title",
89 "{title.as_deref().unwrap_or_default()}"
90 }
91 button {
92 r#type: "button",
93 class: "sd-drawer__close",
94 onclick: move |_| *is_open.write() = false,
95 Icon { kind: IconKind::X, size: 16 }
96 }
97 }
98 div { class: "sd-drawer__body",
99 {children}
100 }
101 }
102 }
103 }
104}