1use crate::yew::logo::Logo;
2use crate::yew::menu::Menu;
3use crate::yew::{context::*, profile::Profile};
4use web_sys::window;
5use yew::prelude::*;
6
7#[derive(Properties, Clone, PartialEq)]
8pub struct SidebarProps {
9 #[prop_or_default]
10 pub children: ChildrenWithProps<Menu>,
11
12 #[prop_or(true)]
13 pub show_profile: bool,
14
15 #[prop_or_default]
16 pub user_name: &'static str,
17 #[prop_or_default]
18 pub designation: &'static str,
19 #[prop_or_default]
20 pub user_img: &'static str,
21
22 #[prop_or_default]
23 pub on_logout: Callback<()>,
24
25 #[prop_or("width: 270px; background: white;")]
26 pub style: &'static str,
27 #[prop_or_default]
28 pub class: &'static str,
29
30 #[prop_or(
31 "display: flex; justify-content: space-between; align-items: center; padding: 1rem;"
32 )]
33 pub header_style: &'static str,
34 #[prop_or_default]
35 pub header_class: &'static str,
36
37 #[prop_or_default]
38 pub logo_img_url: &'static str,
39 #[prop_or_default]
40 pub logo_href: &'static str,
41}
42#[function_component(Sidebar)]
43pub fn sidebar(props: &SidebarProps) -> Html {
44 let is_mobile = use_state(|| {
45 let width = window().unwrap().inner_width().unwrap().as_f64().unwrap();
46 width < 768.0
47 });
48
49 let config = use_state(|| SidebarConfig {
50 is_collapsed: *is_mobile,
51 });
52
53 let toggle_sidebar = {
54 let config = config.clone();
55 Callback::from(move |_| {
56 config.set(SidebarConfig {
57 is_collapsed: !config.is_collapsed,
58 });
59 })
60 };
61 let sidebar_style = if config.is_collapsed {
62 "width: 80px; background: white;"
63 } else {
64 props.style
65 };
66
67 html! {
68 <ContextProvider<SidebarContext> context={SidebarContext(config.clone().into())}>
69 <aside class={props.class} style={format!("display: flex; flex-direction: column; height: 100vh; {}", sidebar_style)} aria-label="Sidebar Navigation">
70 <div class={props.header_class} style={props.header_style}>
71 <Logo img_url={props.logo_img_url} href={props.logo_href} />
72 <button onclick={toggle_sidebar} aria-label="Toggle Sidebar">
73 { if config.is_collapsed { "▶" } else { "◀" } }
74 </button>
75 </div>
76
77 <div style="flex-grow: 1; overflow-y: auto;">
78 { for props.children.iter() }
79 </div>
80
81 if props.show_profile {
82 <Profile
83 user_name={props.user_name}
84 designation={props.designation}
85 user_img={props.user_img}
86 is_collapsed={config.is_collapsed}
87 on_logout={props.on_logout.clone()}
88 />
89 }
90 </aside>
91 </ContextProvider<SidebarContext>>
92 }
93}