dioxus_docs_kit/components/blog/
mobile_drawer.rs1use dioxus::prelude::*;
2use dioxus_free_icons::Icon;
3use dioxus_free_icons::icons::ld_icons::LdX;
4
5use crate::BlogContext;
6use crate::blog::registry::BlogRegistry;
7
8use super::tag_filter::TagFilter;
9
10#[component]
12pub fn BlogMobileDrawer(mut open: Signal<bool>) -> Element {
13 let ctx = use_context::<BlogContext>();
14 let registry = use_context::<&'static BlogRegistry>();
15
16 let current_slug = ctx.current_slug;
17 use_effect(move || {
18 let _ = current_slug();
19 open.set(false);
20 });
21
22 let is_open = open();
23
24 let backdrop_class = if is_open {
25 "fixed inset-0 z-[60] bg-black/50 lg:hidden transition-opacity duration-300 opacity-100"
26 } else {
27 "fixed inset-0 z-[60] bg-black/50 lg:hidden transition-opacity duration-300 opacity-0 pointer-events-none"
28 };
29
30 let panel_class = if is_open {
31 "fixed left-0 top-0 bottom-0 z-[70] w-72 bg-base-200 lg:hidden transition-transform duration-300 translate-x-0 shadow-2xl"
32 } else {
33 "fixed left-0 top-0 bottom-0 z-[70] w-72 bg-base-200 lg:hidden transition-transform duration-300 -translate-x-full shadow-2xl"
34 };
35
36 rsx! {
37 div {
38 class: "{backdrop_class}",
39 onclick: move |_| open.set(false),
40 }
41
42 div {
43 class: "{panel_class}",
44 onclick: move |e| e.stop_propagation(),
45
46 div { class: "flex items-center justify-between px-4 py-3 border-b border-base-300",
47 span { class: "font-semibold text-sm", "Blog" }
48 button {
49 class: "btn btn-ghost btn-xs btn-square",
50 onclick: move |_| open.set(false),
51 Icon { class: "size-4", icon: LdX }
52 }
53 }
54
55 div { class: "overflow-y-auto h-[calc(100%-3.5rem)] p-4",
56 if !registry.all_tags().is_empty() {
57 div { class: "mb-6",
58 h3 { class: "font-semibold text-sm text-base-content/70 uppercase tracking-wider mb-3",
59 "Tags"
60 }
61 TagFilter {}
62 }
63 }
64
65 div {
66 h3 { class: "font-semibold text-sm text-base-content/70 uppercase tracking-wider mb-3",
67 "Recent Posts"
68 }
69 ul { class: "space-y-1",
70 for post in registry.all_posts().iter().take(10) {
71 {
72 let href = format!("{}/{}", ctx.base_path, post.slug);
73 let is_active = current_slug() == post.slug;
74 let active_class = if is_active {
75 "bg-primary/10 text-primary font-medium"
76 } else {
77 "text-base-content/70 hover:text-base-content hover:bg-base-200"
78 };
79 rsx! {
80 li {
81 Link {
82 to: NavigationTarget::Internal(href),
83 class: "block px-3 py-2 text-sm rounded-lg transition-colors {active_class}",
84 "{post.frontmatter.title}"
85 }
86 }
87 }
88 }
89 }
90 }
91 }
92 }
93 }
94 }
95}