use dioxus::prelude::*; use dioxus_free_icons::icons::bs_icons::*; use dioxus_free_icons::Icon; /// A small copy-to-clipboard button that shows a checkmark after copying. /// /// Usage: `CopyButton { value: "text to copy" }` #[component] pub fn CopyButton(value: String, #[props(default = false)] small: bool) -> Element { let mut copied = use_signal(|| false); let size = if small { 12 } else { 14 }; let class = if small { "copy-btn copy-btn-sm" } else { "copy-btn" }; rsx! { button { class: class, title: if copied() { "Copied!" } else { "Copy to clipboard" }, onclick: move |_| { let val = value.clone(); // Escape single quotes for JS let escaped = val.replace('\\', "\\\\").replace('\'', "\\'"); let js = format!("navigator.clipboard.writeText('{escaped}')"); document::eval(&js); copied.set(true); spawn(async move { #[cfg(feature = "web")] gloo_timers::future::TimeoutFuture::new(2000).await; #[cfg(not(feature = "web"))] tokio::time::sleep(std::time::Duration::from_secs(2)).await; copied.set(false); }); }, if copied() { Icon { icon: BsCheckLg, width: size, height: size } } else { Icon { icon: BsClipboard, width: size, height: size } } } } }