use crate::components::shared::{disabled_cls, CONTROL_MOTION, FOCUS_RING, PRESSABLE};
use leptos::prelude::*;
#[derive(Debug, Clone, PartialEq, Default)]
pub enum ButtonVariant {
#[default]
Default,
Outline,
Ghost,
Destructive,
Secondary,
Link,
}
#[derive(Debug, Clone, PartialEq, Default)]
pub enum ButtonSize {
Sm,
#[default]
Md,
Lg,
Icon,
}
#[component]
pub fn Button(
#[prop(default = ButtonVariant::Default)] variant: ButtonVariant,
#[prop(default = ButtonSize::Md)] size: ButtonSize,
#[prop(default = false)] disabled: bool,
#[prop(default = String::new())] class: String,
#[prop(optional)] aria_label: Option<String>,
children: Children,
) -> impl IntoView {
let variant_class = match variant {
ButtonVariant::Default => "bg-primary text-primary-foreground hover:bg-primary/90 shadow-elev-sm hover:shadow-elev",
ButtonVariant::Outline => "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground",
ButtonVariant::Ghost => "hover:bg-accent hover:text-accent-foreground",
ButtonVariant::Destructive => "bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-elev-sm hover:shadow-elev",
ButtonVariant::Secondary => "bg-secondary text-secondary-foreground hover:bg-secondary/80 shadow-elev-sm hover:shadow-elev",
ButtonVariant::Link => "text-primary underline-offset-4 hover:underline",
};
let size_class = match size {
ButtonSize::Sm => "h-8 px-3 text-xs",
ButtonSize::Md => "h-10 px-4 text-sm",
ButtonSize::Lg => "h-12 px-6 text-base",
ButtonSize::Icon => "h-10 w-10",
};
let disabled_class = disabled_cls(disabled);
let combined = format!(
"inline-flex items-center justify-center whitespace-nowrap rounded-md font-medium {} {} {} {} {} {}",
CONTROL_MOTION, PRESSABLE, FOCUS_RING, variant_class, size_class, disabled_class
);
let combined = if class.is_empty() {
combined
} else {
format!("{} {}", combined, class)
};
view! {
<button class=combined disabled=disabled aria-label=aria_label>
{children()}
</button>
}
}