freya_components/
tile.rs

1use dioxus::prelude::*;
2use freya_core::platform::CursorIcon;
3use freya_elements::{
4    self as dioxus_elements,
5    events::{
6        KeyboardEvent,
7        MouseEvent,
8    },
9};
10use freya_hooks::{
11    use_applied_theme,
12    use_platform,
13    TileTheme,
14    TileThemeWith,
15};
16
17/// Indicates the current status of the Tile.
18#[derive(Debug, Default, PartialEq, Clone, Copy)]
19pub enum TileStatus {
20    /// Default state.
21    #[default]
22    Idle,
23    /// Mouse is hovering the tile.
24    Hovering,
25}
26
27/// Tile component to be used with [`Radio`](crate::Radio()) and [`Checkbox`](crate::Checkbox()).
28/// # Styling
29/// Inherits the [`TileTheme`](freya_hooks::TileTheme) theme.
30///
31/// # Example
32#[allow(non_snake_case)]
33#[component]
34pub fn Tile(
35    /// Inner children for the Tile.
36    children: Element,
37    /// Optional element to be placed before the inner children of the Tile. Such as a [`Radio`](crate::Radio())
38    leading: Option<Element>,
39    /// Event handler for when the Tile is selected, e.g when clicking on it.
40    onselect: Option<EventHandler<()>>,
41    /// Theme override.
42    theme: Option<TileThemeWith>,
43) -> Element {
44    let mut status = use_signal(TileStatus::default);
45    let platform = use_platform();
46    let TileTheme { padding } = use_applied_theme!(&theme, tile);
47
48    use_drop(move || {
49        if *status.read() == TileStatus::Hovering {
50            platform.set_cursor(CursorIcon::default());
51        }
52    });
53
54    let onkeydown = move |e: KeyboardEvent| {
55        if let Some(onselect) = &onselect {
56            e.stop_propagation();
57            onselect.call(())
58        }
59    };
60
61    let onclick = move |e: MouseEvent| {
62        if let Some(onselect) = &onselect {
63            e.stop_propagation();
64            onselect.call(())
65        }
66    };
67
68    let onmouseenter = move |_| {
69        platform.set_cursor(CursorIcon::Pointer);
70        status.set(TileStatus::Hovering);
71    };
72
73    let onmouseleave = move |_| {
74        platform.set_cursor(CursorIcon::default());
75        status.set(TileStatus::default());
76    };
77
78    rsx!(
79        rect {
80            onkeydown,
81            onclick,
82            onmouseenter,
83            onmouseleave,
84            direction: "horizontal",
85            padding: "{padding}",
86            cross_align: "center",
87            if let Some(leading) = leading {
88                rect {
89                    padding: "4",
90                    {leading}
91                }
92            }
93            {children}
94        }
95    )
96}