Skip to main content

ui_storybook/components/primitives/
button.rs

1//! Button — rust-ui-style with a small variant matrix.
2//!
3//! Variants follow the shadcn / rust-ui convention: a primary `Default`, a
4//! transparent-edged `Outline`, a borderless `Ghost`, a destructive red, and a
5//! quiet `Secondary`. Sizes are `Sm`, `Md` (default), `Lg`.
6
7use leptos::prelude::*;
8
9#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
10pub enum ButtonVariant {
11    #[default]
12    Default,
13    Outline,
14    Ghost,
15    Destructive,
16    Secondary,
17}
18
19impl ButtonVariant {
20    fn css(self) -> &'static str {
21        match self {
22            ButtonVariant::Default => "btn-default",
23            ButtonVariant::Outline => "btn-outline",
24            ButtonVariant::Ghost => "btn-ghost",
25            ButtonVariant::Destructive => "btn-destructive",
26            ButtonVariant::Secondary => "btn-secondary",
27        }
28    }
29}
30
31#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
32pub enum ButtonSize {
33    Sm,
34    #[default]
35    Md,
36    Lg,
37}
38
39impl ButtonSize {
40    fn css(self) -> &'static str {
41        match self {
42            ButtonSize::Sm => "btn-sm",
43            ButtonSize::Md => "btn-md",
44            ButtonSize::Lg => "btn-lg",
45        }
46    }
47}
48
49#[component]
50pub fn Button(
51    #[prop(optional)] variant: ButtonVariant,
52    #[prop(optional)] size: ButtonSize,
53    #[prop(optional, into)] extra_class: String,
54    #[prop(optional)] disabled: bool,
55    children: Children,
56) -> impl IntoView {
57    let class = format!(
58        "btn {} {}{}{}",
59        variant.css(),
60        size.css(),
61        if extra_class.is_empty() { "" } else { " " },
62        extra_class,
63    );
64    view! {
65        <button class=class disabled=disabled>
66            {children()}
67        </button>
68    }
69}