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