A political conference and discussion platform, in Rust and Dioxus
Something went wrong. Try again.
3.2 kB · 68 lines
Rust
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869//! The standard loading / error / empty (LEE) feedback states, so every async//! surface renders the four states the same way. The data + loading states are//! screen-specific (a screen picks its skeleton and renders its own rows); these//! two cover the shared empty and error presentations. Domain-free: the caller//! passes localized strings.//!//! The reference pattern for a `use_data_resource!` returning `Result<T, _>`://!//! ```ignore//! match &*resource.read() {//! Some(Ok(data)) if !data.is_empty() => rsx! { /* rows */ },//! Some(Ok(_)) => rsx! { div { class: "card", EmptyState { icon: "inbox", message: t("..."), small: true } } },//! Some(Err(e)) => { crate::errors::log_handled("thing load failed", e); rsx! { div { class: "card accent-error", ErrorState { title: t("error.somethingWentWrong"), small: true } } } },//! None => rsx! { Spinner {} }, // or a shape-matched skeleton//! }//! ```//!//! `log_handled` rather than `log::error!`: this arm is a render body, so it//! runs again on every re-render while the card is up, and error is the level//! that leaves the device. See [`crate::errors::log_handled`].
use dioxus::prelude::*;
/// A standard empty-state block: an expressive orb + a message. Wrap it in a/// `.card` for the carded form. Use for `Some(Ok(empty))`.#[component]pub fn EmptyState(icon: String, message: String, #[props(default)] small: bool) -> Element { rsx! { div { class: if small { "empty-state empty-state-sm" } else { "empty-state" }, div { class: if small { "empty-state-orb empty-state-orb-sm" } else { "empty-state-orb" }, span { class: "material-icons", "{icon}" } } p { class: "empty-state-body", "{message}" } } }}
/// A standard error-state block: an error-tinted orb + a friendly title. Never/// renders raw error text (log the detail separately). Wrap in/// `.card.accent-error` for the carded form. Use for `Some(Err(_))`.////// `on_retry` adds a "try again" button. Pass it wherever the load is worth/// another attempt, which is most of them: the usual cause is a network that/// dropped for a moment, on a phone in a hall full of other phones, and the/// alternative the reader is left with is reloading the whole app.#[component]pub fn ErrorState( title: String, #[props(default)] small: bool, on_retry: Option<EventHandler<()>>,) -> Element { rsx! { div { class: if small { "empty-state empty-state-sm" } else { "empty-state" }, div { class: if small { "empty-state-orb empty-state-orb-sm error-orb" } else { "empty-state-orb error-orb" }, span { class: "material-icons", "error_outline" } } h3 { class: "empty-state-title", "{title}" } if let Some(retry) = on_retry { button { class: "btn btn-tonal btn-sm", onclick: move |_| retry.call(()), span { class: "material-icons", "refresh" } "{crate::i18n::t(\"error.retry\")}" } } } }}