Skip to main content

freya_material_design/
sidebar.rs

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