dioxus_router/components/
history_buttons.rs

1use dioxus_lib::prelude::*;
2
3use tracing::error;
4
5use crate::utils::use_router_internal::use_router_internal;
6
7/// The properties for a [`GoBackButton`] or a [`GoForwardButton`].
8#[derive(Debug, Props, Clone, PartialEq)]
9pub struct HistoryButtonProps {
10    /// The children to render within the generated HTML button tag.
11    pub children: Element,
12}
13
14/// A button to go back through the navigation history. Similar to a browsers back button.
15///
16/// Only works as descendant of a [`Link`] component, otherwise it will be inactive.
17///
18/// The button will disable itself if it is known that no prior history is available.
19///
20/// # Panic
21/// - When the [`GoBackButton`] is not nested within a [`Link`] component
22///   hook, but only in debug builds.
23///
24/// # Example
25/// ```rust
26/// # use dioxus::prelude::*;
27/// # use dioxus_router::prelude::*;
28/// #[derive(Clone, Routable)]
29/// enum Route {
30///     #[route("/")]
31///     Index {},
32/// }
33///
34/// #[component]
35/// fn App() -> Element {
36///     rsx! {
37///         Router::<Route> {}
38///     }
39/// }
40///
41/// #[component]
42/// fn Index() -> Element {
43///     rsx! {
44///         GoBackButton {
45///             "go back"
46///         }
47///     }
48/// }
49/// #
50/// # let mut vdom = VirtualDom::new(App);
51/// # vdom.rebuild_in_place();
52/// # assert_eq!(
53/// #     dioxus_ssr::render(&vdom),
54/// #     r#"<button disabled="true">go back</button>"#
55/// # );
56/// ```
57pub fn GoBackButton(props: HistoryButtonProps) -> Element {
58    let HistoryButtonProps { children } = props;
59
60    // hook up to router
61    let router = match use_router_internal() {
62        Some(r) => r,
63        #[allow(unreachable_code)]
64        None => {
65            let msg = "`GoBackButton` must have access to a parent router";
66            error!("{msg}, will be inactive");
67            #[cfg(debug_assertions)]
68            panic!("{}", msg);
69            return VNode::empty();
70        }
71    };
72
73    let disabled = !router.can_go_back();
74
75    rsx! {
76        button {
77            disabled: "{disabled}",
78            onclick: move |evt| {
79                evt.prevent_default();
80                router.go_back()
81            },
82            {children}
83        }
84    }
85}
86
87/// A button to go forward through the navigation history. Similar to a browsers forward button.
88///
89/// Only works as descendant of a [`Link`] component, otherwise it will be inactive.
90///
91/// The button will disable itself if it is known that no later history is available.
92///
93/// # Panic
94/// - When the [`GoForwardButton`] is not nested within a [`Link`] component
95///   hook, but only in debug builds.
96///
97/// # Example
98/// ```rust
99/// # use dioxus::prelude::*;
100/// # use dioxus_router::prelude::*;
101/// #[derive(Clone, Routable)]
102/// enum Route {
103///     #[route("/")]
104///     Index {},
105/// }
106///
107/// #[component]
108/// fn App() -> Element {
109///     rsx! {
110///         Router::<Route> {}
111///     }
112/// }
113///
114/// #[component]
115/// fn Index() -> Element {
116///     rsx! {
117///         GoForwardButton {
118///             "go forward"
119///         }
120///     }
121/// }
122/// #
123/// # let mut vdom = VirtualDom::new(App);
124/// # vdom.rebuild_in_place();
125/// # assert_eq!(
126/// #     dioxus_ssr::render(&vdom),
127/// #     r#"<button disabled="true">go forward</button>"#
128/// # );
129/// ```
130pub fn GoForwardButton(props: HistoryButtonProps) -> Element {
131    let HistoryButtonProps { children } = props;
132
133    // hook up to router
134    let router = match use_router_internal() {
135        Some(r) => r,
136        #[allow(unreachable_code)]
137        None => {
138            let msg = "`GoForwardButton` must have access to a parent router";
139            error!("{msg}, will be inactive");
140            #[cfg(debug_assertions)]
141            panic!("{}", msg);
142            return VNode::empty();
143        }
144    };
145
146    let disabled = !router.can_go_forward();
147
148    rsx! {
149        button {
150            disabled: "{disabled}",
151            onclick: move |evt| {
152                evt.prevent_default();
153                router.go_forward()
154            },
155            {children}
156        }
157    }
158}