by_components/effects/
mod.rs

1#![allow(non_snake_case)]
2use dioxus::prelude::*;
3
4/// A component that creates a shadow effect on hover.
5///
6/// # Example
7///
8/// ```rust
9/// use dioxus::prelude::*;
10/// use by_components::effects::HoverEffects;
11///
12/// #[component]
13/// pub fn App() -> Element {
14///     rsx! {
15///         div {
16///             HoverEffects {}
17///             button { "Hover me" }
18///             a { "Hover me" }
19///             div { class: "hover-effect", "hover me" }
20///             div { "Don't hover me" }
21///         }
22///     }
23/// }
24/// ```
25///
26/// # Output
27///
28/// It shows a shadow effect on all of <button/> and <a/> tags.
29/// It also shows a shadow effect on the element starting with the class name "hover-effect".
30#[component]
31pub fn HoverEffects() -> Element {
32    #[cfg(feature = "web")]
33    use_effect(move || {
34        tracing::debug!("shadow mounted");
35        use wasm_bindgen::prelude::*;
36        use web_sys::*;
37
38        let document = web_sys::window().unwrap().document().unwrap();
39        let shadow = document.get_element_by_id("shadow").unwrap();
40        let closure = Closure::wrap(Box::new(move |event: web_sys::Event| {
41            if let Ok(event) = event.dyn_into::<MouseEvent>() {
42                if let Some(target) = event.target() {
43                    if let Ok(el) = target.dyn_into::<HtmlElement>() {
44                        if (el.tag_name().to_lowercase().as_str() == "button")
45                            || (el.tag_name().to_lowercase().as_str() == "a")
46                            || el
47                                .class_name()
48                                .split(" ")
49                                .collect::<Vec<&str>>()
50                                .contains(&"hover-effect")
51                        {
52                            let x = js_sys::Reflect::get(&event, &JsValue::from_str("pageX"))
53                                .unwrap()
54                                .as_f64()
55                                .unwrap_or(0.0) as i32;
56                            let y = js_sys::Reflect::get(&event, &JsValue::from_str("pageY"))
57                                .unwrap()
58                                .as_f64()
59                                .unwrap_or(0.0) as i32;
60
61                            shadow
62                                .set_attribute("style", &format!("left: {}px; top: {}px; position: absolute; width: 50px; height: 50px; background: radial-gradient(circle, rgba(100, 100, 100, 0.5), rgba(0, 0, 0, 0)); border-radius: 50%; pointer-events: none; transform: translate(-50%, -50%); mix-blend-mode: screen; opacity: 0.7; filter: blur(15px); z-index: 9999; ", x, y))
63                                .unwrap();
64                        } else {
65                            shadow.set_attribute("style", "display: none;").unwrap();
66                        }
67                    }
68                }
69            }
70        }) as Box<dyn FnMut(web_sys::Event)>);
71
72        document
73            .add_event_listener_with_callback("mousemove", closure.as_ref().unchecked_ref())
74            .unwrap();
75
76        closure.forget();
77    });
78
79    rsx! {
80        div { id: "shadow" }
81    }
82}