dioxus_router/components/history_buttons.rs
1use dioxus_core::{Element, VNode};
2use dioxus_core_macro::{rsx, Props};
3use dioxus_html as dioxus_elements;
4
5use tracing::error;
6
7use crate::utils::use_router_internal::use_router_internal;
8
9/// The properties for a [`GoBackButton`] or a [`GoForwardButton`].
10#[derive(Debug, Props, Clone, PartialEq)]
11pub struct HistoryButtonProps {
12 /// The children to render within the generated HTML button tag.
13 pub children: Element,
14}
15
16/// A button to go back through the navigation history. Similar to a browsers back button.
17///
18/// Only works as descendant of a [`super::Link`] component, otherwise it will be inactive.
19///
20/// The button will disable itself if it is known that no prior history is available.
21///
22/// # Panic
23/// - When the [`GoBackButton`] is not nested within a [`super::Link`] component
24/// hook, but only in debug builds.
25///
26/// # Example
27/// ```rust
28/// # use dioxus::prelude::*;
29/// #[derive(Clone, Routable)]
30/// enum Route {
31/// #[route("/")]
32/// Index {},
33/// }
34///
35/// #[component]
36/// fn App() -> Element {
37/// rsx! {
38/// Router::<Route> {}
39/// }
40/// }
41///
42/// #[component]
43/// fn Index() -> Element {
44/// rsx! {
45/// GoBackButton {
46/// "go back"
47/// }
48/// }
49/// }
50/// #
51/// # let mut vdom = VirtualDom::new(App);
52/// # vdom.rebuild_in_place();
53/// # assert_eq!(
54/// # dioxus_ssr::render(&vdom),
55/// # r#"<button disabled="true">go back</button>"#
56/// # );
57/// ```
58pub fn GoBackButton(props: HistoryButtonProps) -> Element {
59 let HistoryButtonProps { children } = props;
60
61 // hook up to router
62 let router = match use_router_internal() {
63 Some(r) => r,
64 #[allow(unreachable_code)]
65 None => {
66 let msg = "`GoBackButton` must have access to a parent router";
67 error!("{msg}, will be inactive");
68 #[cfg(debug_assertions)]
69 panic!("{}", msg);
70 return VNode::empty();
71 }
72 };
73
74 let disabled = !router.can_go_back();
75
76 rsx! {
77 button {
78 disabled: "{disabled}",
79 onclick: move |evt| {
80 evt.prevent_default();
81 router.go_back()
82 },
83 {children}
84 }
85 }
86}
87
88/// A button to go forward through the navigation history. Similar to a browsers forward button.
89///
90/// Only works as descendant of a [`super::Link`] component, otherwise it will be inactive.
91///
92/// The button will disable itself if it is known that no later history is available.
93///
94/// # Panic
95/// - When the [`GoForwardButton`] is not nested within a [`super::Link`] component
96/// hook, but only in debug builds.
97///
98/// # Example
99/// ```rust
100/// # use dioxus::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}