Skip to main content

freya_material_design/
tile.rs

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