dioxus_tw_components/components/
sidepanel.rs1use crate::components::icon::*;
2use crate::dioxus_core::IntoAttributeValue;
3use dioxus::prelude::*;
4use dioxus_core::AttributeValue;
5
6#[derive(Clone, Copy)]
7pub struct SidePanelState {
8 is_active: bool,
9}
10
11impl SidePanelState {
12 fn new(is_active: bool) -> Self {
13 Self { is_active }
14 }
15
16 pub fn toggle(&mut self) {
17 self.is_active = !self.is_active;
18 }
19
20 pub fn open(&mut self) {
21 self.is_active = true;
22 }
23
24 pub fn close(&mut self) {
25 self.is_active = false;
26 }
27}
28
29impl IntoAttributeValue for SidePanelState {
30 fn into_value(self) -> AttributeValue {
31 match self.is_active {
32 true => AttributeValue::Text("active".to_string()),
33 false => AttributeValue::Text("inactive".to_string()),
34 }
35 }
36}
37
38#[derive(Clone, PartialEq, Props)]
39pub struct SidePanelProps {
40 #[props(default = false)]
41 is_active: bool,
42
43 children: Element,
44}
45
46#[component]
47pub fn SidePanel(props: SidePanelProps) -> Element {
48 use_context_provider(|| Signal::new(SidePanelState::new(props.is_active)));
49
50 rsx! {
51 {props.children}
52 }
53}
54
55#[derive(Clone, PartialEq, Props)]
56pub struct SidePanelTriggerProps {
57 #[props(extends = div, extends = GlobalAttributes)]
58 attributes: Vec<Attribute>,
59
60 #[props(optional, default)]
61 onclick: EventHandler<MouseEvent>,
62
63 children: Element,
64}
65
66#[component]
67pub fn SidePanelTrigger(mut props: SidePanelTriggerProps) -> Element {
68 let mut state = use_context::<Signal<SidePanelState>>();
69
70 let default_classes = "button";
71 crate::setup_class_attribute(&mut props.attributes, default_classes);
72
73 let onclick = move |event: Event<MouseData>| {
74 state.write().open();
75 props.onclick.call(event)
76 };
77
78 rsx! {
79 button { onclick, ..props.attributes, {props.children} }
80 }
81}
82
83#[derive(Clone, PartialEq, Props)]
84pub struct SidePanelCloseProps {
85 #[props(extends = div, extends = GlobalAttributes)]
86 attributes: Vec<Attribute>,
87
88 #[props(default)]
89 children: Element,
90}
91
92impl std::default::Default for SidePanelCloseProps {
93 fn default() -> Self {
94 Self {
95 attributes: Vec::<Attribute>::default(),
96 children: Ok(VNode::default()), }
98 }
99}
100
101#[component]
104pub fn SidePanelClose(mut props: SidePanelCloseProps) -> Element {
105 let mut state = use_context::<Signal<SidePanelState>>();
106
107 let has_children = props.children != Ok(VNode::default());
108
109 if !has_children {
110 let default_classes = "sidepanel-close";
111 crate::setup_class_attribute(&mut props.attributes, default_classes);
112 }
113
114 let onclick = move |event: Event<MouseData>| {
115 event.stop_propagation();
116 state.write().close();
117 };
118
119 rsx! {
120 div { onclick, ..props.attributes,
121 if !has_children {
122 Icon { icon: Icons::Close }
123 } else {
124 {props.children}
125 }
126 }
127 }
128}
129
130#[derive(Clone, PartialEq, Props)]
131pub struct SidePanelContentProps {
132 #[props(extends = div, extends = GlobalAttributes)]
133 attributes: Vec<Attribute>,
134
135 children: Element,
136}
137
138#[component]
139pub fn SidePanelContent(mut props: SidePanelContentProps) -> Element {
140 let state = use_context::<Signal<SidePanelState>>();
141
142 let default_classes = "sidepanel-content";
143 crate::setup_class_attribute(&mut props.attributes, default_classes);
144
145 rsx! {
146 div {
147 "data-state": state.read().into_value(),
148 ..props.attributes,
149 {props.children}
150 }
151 }
152}
153
154#[derive(Clone, PartialEq, Props)]
155pub struct SidePanelBackgroundProps {
156 #[props(optional, default = true)]
157 interactive: bool,
158
159 #[props(extends = div, extends = GlobalAttributes)]
160 attributes: Vec<Attribute>,
161
162 #[props(optional, default)]
163 onclick: EventHandler<MouseEvent>,
164
165 children: Element,
166}
167
168#[component]
169pub fn SidePanelBackground(mut props: SidePanelBackgroundProps) -> Element {
170 let mut state = use_context::<Signal<SidePanelState>>();
171
172 let default_classes = "sidepanel-background";
173 crate::setup_class_attribute(&mut props.attributes, default_classes);
174
175 let onclick = move |event: Event<MouseData>| {
176 event.stop_propagation();
177 if props.interactive {
178 state.write().close();
179 props.onclick.call(event)
180 }
181 };
182
183 rsx! {
184 div {
185 "data-state": state.read().into_value(),
186 onclick,
187 ..props.attributes,
188 {props.children}
189 }
190 }
191}