/ libs / primitives / src / progress.rs
progress.rs
  1  //! Defines the [`Progress`] component and its sub-components.
  2  
  3  use dioxus::prelude::*;
  4  
  5  /// The props for the [`Progress`] component.
  6  #[derive(Props, Clone, PartialEq)]
  7  pub struct ProgressProps {
  8      /// The current progress value, between 0 and max.
  9      pub value: ReadSignal<Option<f64>>,
 10  
 11      /// The maximum value. Defaults to 100.
 12      #[props(default = ReadSignal::new(Signal::new(100.0)))]
 13      pub max: ReadSignal<f64>,
 14  
 15      /// Additional attributes to apply to the progress element.
 16      #[props(extends = GlobalAttributes)]
 17      pub attributes: Vec<Attribute>,
 18  
 19      /// The children of the progress component.
 20      pub children: Element,
 21  }
 22  
 23  /// # Progress
 24  ///
 25  /// The `Progress` component shows the progress of an operation.
 26  ///
 27  /// ## Example
 28  ///
 29  /// ```rust
 30  /// use dioxus::prelude::*;
 31  /// use dioxus_primitives::progress::{Progress, ProgressIndicator};
 32  /// #[component]
 33  /// fn Demo() -> Element {
 34  ///     rsx! {
 35  ///         Progress {
 36  ///             aria_label: "Progressbar Demo",
 37  ///             value: 50.0,
 38  ///             ProgressIndicator {}
 39  ///         }
 40  ///     }
 41  /// }
 42  /// ```
 43  ///
 44  /// ## Styling
 45  ///
 46  /// The [`Progress`] component defines the following data attributes you can use to control styling:
 47  /// - `data-state`: Indicates the state of the progress. Values are `loading` or `indeterminate`.
 48  /// - `data-value`: The current progress value between 0 and max.
 49  /// - `data-max`: The maximum progress value.
 50  ///
 51  /// The [`Progress`] component defines the following css variables you can use to control styling:
 52  /// - `--progress-value`: A value between 0 and 100 representing the current progress percentage.
 53  #[component]
 54  pub fn Progress(props: ProgressProps) -> Element {
 55      // Calculate percentage for styling and "data-state"
 56      let percentage = use_memo(move || {
 57          props.value.cloned().map(|v| {
 58              let max = (props.max)();
 59              (v / max) * 100.0
 60          })
 61      });
 62  
 63      let state = use_memo(move || match percentage() {
 64          Some(_) => "loading",
 65          None => "indeterminate",
 66      });
 67  
 68      rsx! {
 69          div {
 70              role: "progressbar",
 71              "aria-valuemin": 0,
 72              "aria-valuemax": props.max,
 73              "aria-valuenow": props.value.cloned(),
 74              "data-state": state,
 75              "data-value": props.value.cloned().map(|v| v.to_string()),
 76              "data-max": props.max,
 77              style: percentage().map(|p| format!("--progress-value: {p}%")),
 78              ..props.attributes,
 79  
 80              {props.children}
 81          }
 82      }
 83  }
 84  
 85  /// The props for the [`ProgressIndicator`] component.
 86  #[derive(Props, Clone, PartialEq)]
 87  pub struct ProgressIndicatorProps {
 88      /// Additional attributes to apply to the indicator element.
 89      #[props(extends = GlobalAttributes)]
 90      pub attributes: Vec<Attribute>,
 91      /// The children of the indicator component.
 92      pub children: Element,
 93  }
 94  
 95  /// # ProgressIndicator
 96  ///
 97  /// The `ProgressIndicator` component represents the visual indicator that shows the progress completion.
 98  ///
 99  /// This must be used inside a [`Progress`] component.
100  ///
101  /// ## Example
102  ///
103  /// ```rust
104  /// use dioxus::prelude::*;
105  /// use dioxus_primitives::progress::{Progress, ProgressIndicator};
106  /// #[component]
107  /// fn Demo() -> Element {
108  ///     rsx! {
109  ///         Progress {
110  ///             aria_label: "Progressbar Demo",
111  ///             value: 50.0,
112  ///             ProgressIndicator {}
113  ///         }
114  ///     }
115  /// }
116  /// ```
117  #[component]
118  pub fn ProgressIndicator(props: ProgressIndicatorProps) -> Element {
119      rsx! {
120          div { ..props.attributes, {props.children} }
121      }
122  }