Skip to main content

freya_material_design/
sidebar.rs

1use std::time::Duration;
2
3use freya_components::{
4    get_theme,
5    sidebar::{
6        SideBarItem,
7        SideBarItemThemePreference,
8    },
9};
10use freya_core::prelude::*;
11use torin::size::Size;
12
13use crate::ripple::Ripple;
14
15/// Extension trait that adds ripple effect support to [SideBarItem].
16///
17/// This trait provides the [SideBarItemRippleExt::ripple] method that wraps the item's children
18/// in a [Ripple] component, creating a Material Design-style ripple effect on click.
19///
20/// # Example
21///
22/// ```rust
23/// # use freya::{material_design::*, prelude::*};
24/// fn app() -> impl IntoElement {
25///     SideBarItem::new()
26///         .on_press(|_| println!("Pressed"))
27///         .ripple()
28///         .child("Settings")
29/// }
30/// ```
31pub trait SideBarItemRippleExt {
32    /// Enable ripple effect on this sidebar item.
33    /// Returns a [RippleSideBarItem] that allows adding children and configuring the ripple.
34    fn ripple(self) -> RippleSideBarItem;
35}
36
37impl SideBarItemRippleExt for SideBarItem {
38    fn ripple(self) -> RippleSideBarItem {
39        RippleSideBarItem {
40            item: self,
41            ripple: Ripple::new(),
42        }
43    }
44}
45
46/// A SideBarItem with a Ripple effect wrapper.
47///
48/// Created by calling [SideBarItemRippleExt::ripple] on a SideBarItem.
49/// Allows adding children to the ripple and configuring its color/duration.
50#[derive(Clone, PartialEq)]
51pub struct RippleSideBarItem {
52    item: SideBarItem,
53    ripple: Ripple,
54}
55
56impl ChildrenExt for RippleSideBarItem {
57    fn get_children(&mut self) -> &mut Vec<Element> {
58        self.ripple.get_children()
59    }
60}
61
62impl KeyExt for RippleSideBarItem {
63    fn write_key(&mut self) -> &mut DiffKey {
64        self.item.write_key()
65    }
66}
67
68impl RippleSideBarItem {
69    /// Set the color of the ripple effect.
70    pub fn color(mut self, color: impl Into<Color>) -> Self {
71        self.ripple = self.ripple.color(color);
72        self
73    }
74
75    /// Set the duration of the ripple animation.
76    pub fn duration(mut self, duration: Duration) -> Self {
77        self.ripple = self.ripple.duration(duration);
78        self
79    }
80}
81
82impl Component for RippleSideBarItem {
83    fn render(&self) -> impl IntoElement {
84        let mut item = self.item.clone();
85
86        let theme = get_theme!(
87            &item.get_theme(),
88            SideBarItemThemePreference,
89            "sidebar_item"
90        );
91
92        let ripple = self
93            .ripple
94            .clone()
95            .padding(theme.padding)
96            .width(Size::fill());
97
98        let theme_override = item.get_theme().cloned().unwrap_or_default().padding(0.);
99
100        item.get_children().clear();
101        item.get_children().push(ripple.into());
102        item.theme(theme_override)
103    }
104
105    fn render_key(&self) -> DiffKey {
106        self.item.render_key()
107    }
108}