dioxus_tw_components/components/molecules/sidepanel/
props.rs1use crate::{attributes::*, components::atoms::icon::*};
2use dioxus::prelude::*;
3use dioxus_core::AttributeValue;
4use dioxus_tw_components_macro::UiComp;
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, UiComp)]
39pub struct SidePanelProps {
40 #[props(default = false)]
41 is_active: bool,
42
43 children: Element,
44}
45
46impl std::default::Default for SidePanelProps {
47 fn default() -> Self {
48 Self {
49 is_active: false,
50 children: rsx! {},
51 }
52 }
53}
54
55#[component]
56pub fn SidePanel(props: SidePanelProps) -> Element {
57 use_context_provider(|| Signal::new(SidePanelState::new(props.is_active)));
58
59 rsx! {
60 {props.children}
61 }
62}
63
64#[derive(Clone, PartialEq, Props, UiComp)]
65pub struct SidePanelTriggerProps {
66 #[props(extends = div, extends = GlobalAttributes)]
67 attributes: Vec<Attribute>,
68
69 #[props(optional, default)]
70 onclick: EventHandler<MouseEvent>,
71
72 children: Element,
73}
74
75impl std::default::Default for SidePanelTriggerProps {
76 fn default() -> Self {
77 Self {
78 attributes: Vec::<Attribute>::default(),
79 onclick: EventHandler::<MouseEvent>::default(),
80 children: rsx! {},
81 }
82 }
83}
84
85#[component]
86pub fn SidePanelTrigger(mut props: SidePanelTriggerProps) -> Element {
87 let mut state = use_context::<Signal<SidePanelState>>();
88
89 props.update_class_attribute();
90
91 let onclick = move |event: Event<MouseData>| {
92 state.write().open();
93 props.onclick.call(event)
94 };
95
96 rsx! {
97 div { onclick, ..props.attributes, {props.children} }
98 }
99}
100
101#[derive(Clone, PartialEq, Props, UiComp)]
102pub struct SidePanelCloseProps {
103 #[props(extends = div, extends = GlobalAttributes)]
104 attributes: Vec<Attribute>,
105
106 #[props(optional)]
107 children: Element,
108}
109
110impl std::default::Default for SidePanelCloseProps {
111 fn default() -> Self {
112 Self {
113 attributes: Vec::<Attribute>::default(),
114 children: Ok(VNode::default()), }
116 }
117}
118
119#[component]
122pub fn SidePanelClose(mut props: SidePanelCloseProps) -> Element {
123 let mut state = use_context::<Signal<SidePanelState>>();
124
125 let has_children = props.children != Ok(VNode::default());
126
127 if !has_children {
128 props.update_class_attribute();
129 }
130
131 let onclick = move |event: Event<MouseData>| {
132 event.stop_propagation();
133 state.write().close();
134 };
135
136 rsx! {
137 div { onclick, ..props.attributes,
138 if !has_children {
139 Icon { icon: Icons::Close }
140 } else {
141 {props.children}
142 }
143 }
144 }
145}
146
147#[derive(Clone, PartialEq, Props, UiComp)]
148pub struct SidePanelContentProps {
149 #[props(extends = div, extends = GlobalAttributes)]
150 attributes: Vec<Attribute>,
151
152 #[props(optional, default)]
153 pub animation: ReadOnlySignal<Animation>,
154 #[props(optional, default)]
155 pub side: ReadOnlySignal<Side>,
156
157 children: Element,
158}
159
160impl std::default::Default for SidePanelContentProps {
161 fn default() -> Self {
162 Self {
163 attributes: Vec::<Attribute>::default(),
164 animation: ReadOnlySignal::<Animation>::default(),
165 side: ReadOnlySignal::<Side>::default(),
166 children: rsx! {},
167 }
168 }
169}
170
171#[component]
172pub fn SidePanelContent(mut props: SidePanelContentProps) -> Element {
173 let state = use_context::<Signal<SidePanelState>>();
174
175 props.update_class_attribute();
176
177 rsx! {
178 div { "data-state": state.read().into_value(), ..props.attributes, {props.children} }
179 }
180}
181
182#[derive(Clone, PartialEq, Props, UiComp)]
183pub struct SidePanelBackgroundProps {
184 #[props(optional, default = true)]
185 interactive: bool,
186
187 #[props(extends = div, extends = GlobalAttributes)]
188 attributes: Vec<Attribute>,
189
190 #[props(optional, default)]
191 pub color: ReadOnlySignal<Color>,
192 #[props(optional, default)]
193 pub animation: ReadOnlySignal<Animation>,
194 #[props(optional, default)]
195 onclick: EventHandler<MouseEvent>,
196
197 children: Element,
198}
199
200impl std::default::Default for SidePanelBackgroundProps {
201 fn default() -> Self {
202 Self {
203 interactive: true,
204 attributes: Vec::<Attribute>::default(),
205 color: ReadOnlySignal::<Color>::default(),
206 animation: ReadOnlySignal::<Animation>::default(),
207 onclick: EventHandler::<MouseEvent>::default(),
208 children: rsx! {},
209 }
210 }
211}
212
213#[component]
214pub fn SidePanelBackground(mut props: SidePanelBackgroundProps) -> Element {
215 let mut state = use_context::<Signal<SidePanelState>>();
216
217 props.update_class_attribute();
218
219 let onclick = move |event: Event<MouseData>| {
220 event.stop_propagation();
221 if props.interactive {
222 state.write().close();
223 props.onclick.call(event)
224 }
225 };
226
227 rsx! {
228 div {
229 "data-state": state.read().into_value(),
230 onclick,
231 ..props.attributes,
232 {props.children}
233 }
234 }
235}