ThreeDButton

A minimal 3D button with a clean deck-style press and sliding click sheen.

Preview

Loading GPUI

Custom Label

Loading GPUI
ThreeDButton::new("open-panel", "Open Panel").dark(is_dark)

Install

cargo add evilbuttons

Usage

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

struct ButtonDemo;

impl Render for ButtonDemo {
    fn render(&mut self, window: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
        let is_dark = matches!(
            window.appearance(),
            gpui::WindowAppearance::Dark | gpui::WindowAppearance::VibrantDark
        );
        div().child(
            ThreeDButton::new("continue", "Continue")
                .dark(is_dark)
                .on_click(|_, _, _| println!("Continue")),
        )
    }
}

Props

ThreeDButton is a GPUI RenderOnce builder; its press state is keyed by id.

MethodTypeDefaultDescription
new(id, label)impl Into<ElementId>, impl Into<SharedString>-Unique id and the visible button label.
dark(bool)boolfalseUse the dark palette (zinc-900 face, white rim and deck) instead of the light one.
on_click(f)Fn(&ClickEvent, &mut Window, &mut App)-Fired on click, and on Space/Enter while focused.
disabled(bool)boolfalseDims the button and ignores input.

Good to know

  • The React version switches palettes with Tailwind's dark: variant; GPUI has no page theme, so pass dark(true) on dark backgrounds.
  • Every layer (deck, face, press spot, sheen, label) rides the same spring (stiffness 620, damping 32, mass 0.5), so retargeting mid-press stays smooth.
  • The press spot's blur-sm is drawn as a Gaussian shadow, and the sheen is clipped to the pill row by row, since GPUI has no CSS filters or clip paths.

Search docs

Jump to a button documentation page