Preview
Loading GPUI
Props
Install
cargo add evilbuttonsUsage
use evilbuttons::AshBurstButton;
use gpui::{div, prelude::*, rgb, Context, IntoElement, Render, Window};
struct ButtonDemo;
impl Render for ButtonDemo {
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
div().child(
AshBurstButton::new("incinerate")
.label("Incinerate")
.colors([rgb(0x171717), rgb(0x404040), rgb(0x737373), rgb(0xf97316)])
.particle_count(120)
.on_destroy(|_, _| println!("Burned.")),
)
}
}Props
AshBurstButton is a GPUI RenderOnce builder; its simulation state is keyed by id. on_click still fires before the burst.
| Method | Type | Default | Description |
|---|---|---|---|
new(id) | impl Into<ElementId> | - | Unique id for the button's state. |
label(s) | impl Into<SharedString> | "Delete" | Button label. |
particle_count(n) | usize | 80 | Physics particles per burst (at least 12). |
spread(deg) | f32 | 110.0 | Explosion spread in degrees. |
start_velocity(v) | f32 | 42.0 | Launch velocity, in Matter.js units (px per 60Hz step). |
colors(iter) | IntoIterator<Item = impl Into<Hsla>> | charcoal/ember palette | Custom particle colors. Warm reds and oranges get a soft glow. |
icon(bool) | bool | true | Show the leading flame icon. |
on_click(f) | Fn(&ClickEvent, &mut Window, &mut App) | - | Fired on every click, before the burst. |
on_destroy(f) | Fn(&mut Window, &mut App) | - | Fired after each ash burst. |
disabled(bool) | bool | false | Dims the button and ignores input. |
Good to know
- No Matter.js: the ash is a small built-in rigid-body simulation with Matter's gravity, air friction, restitution and friction per particle, colliding with the button, two lips on its top corners, and each other. Pieces collide as circles, so piles settle a little rounder than Matter's boxes.
- Ash is painted on an unclipped overlay above everything else in the window, so it flies past the button's bounds.
- The simulation runs in real time at a fixed 60Hz step, so it looks the same on high-refresh displays.