StretchyButton

A rubbery pill you can grab and pull. Its outline and every letter of its label stretch toward the cursor, and it wobbles back into shape when you let go.

Original idea by Adi (@AdityaSur11)

Preview

Loading GPUI

Props

Install

cargo add evilbuttons

Usage

use evilbuttons::StretchyButton;
use gpui::{div, prelude::*, Context, IntoElement, Render, Window};

struct ButtonDemo;

impl Render for ButtonDemo {
    fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
        div().child(StretchyButton::new("stretch", "Stretch me"))
    }
}

Variants

Taffy

A long stretch and a far snap point: it pulls a long way before it slips free.

Loading GPUI
StretchyButton::new("taffy", "Pull harder")
    .color(rgb(0xf472b6))
    .stretch(110.0)
    .snap(320.0)

Firm Rubber

Short stretch and almost no wobble, so it barely gives and settles quickly.

Loading GPUI
StretchyButton::new("firm", "Barely budges")
    .color(rgb(0x22c55e))
    .stretch(35.0)
    .wobble(0.1)

Props

StretchyButton is a GPUI RenderOnce builder; its pull state is keyed by id.

MethodTypeDefaultDescription
new(id, label)impl Into<ElementId>, impl Into<SharedString>-Unique id and the label, which bends letter by letter.
color(c)impl Into<Hsla>#3d9df5Fill color of the rubber body. The rim is mixed from it.
stretch(px)f3270.0How far in px the rubber gives before it stiffens up.
snap(px)f32220.0Drag distance in px at which the button slips out of your grip.
wobble(w)f320.6How much it jiggles when let go, from 0 (settles) to 1 (very wobbly).
on_click(f)Fn(&ClickEvent, &mut Window, &mut App)-Fired by a press that barely moves.
disabled(bool)boolfalseTurns it into a plain, dimmed pill.

Good to know

  • Press anywhere on the button and drag. The spot you grabbed follows the cursor and the rubber around it comes along: pull from the middle and it bends like a banana, pull from an end and that end stretches out.
  • The label rides the same deformation, so the letters arc, spread and grow or shrink with the body. GPUI can't rotate or squash glyphs, so letters don't lean with the slope or stretch sideways as they do in the React version.
  • A drag is not a click. Only a press that barely moves fires on_click, and it dents the rubber where you hit it.
  • Pull past snap and it slips out of your grip and wobbles home.
  • disabled turns it into a plain pill.

Credits

The original idea and design are by Adi (@AdityaSur11), from the Stretchy button post. This is an independent re-implementation for Evil Buttons. Go give the original some love.

Search docs

Jump to a button documentation page