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}