aura-gui 0.1.0

UI nativa acelerada por GPU para escritorio, Android e iOS, en un solo crate: estilo tipo Tailwind, componentes, sombras, animaciones y agentes de IA. Reposo a cero. Licencia AGPL-3.0 o comercial.
//! Botón con las cuatro variantes de shadcn.

use crate::core::px;
use crate::view::interactivity::ClickHandler;
use crate::view::prelude::*;
use std::rc::Rc;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ButtonVariant {
    Primary,
    Ghost,
    Subtle,
    Danger,
}

pub struct Button {
    label: String,
    variant: ButtonVariant,
    style: Style,
    id: Option<String>,
    on_click: Option<ClickHandler>,
}

impl Button {
    pub fn new(label: impl Into<String>) -> Self {
        Self { label: label.into(), variant: ButtonVariant::Primary, style: Style::default(), id: None, on_click: None }
    }

    pub fn variant(mut self, variant: ButtonVariant) -> Self {
        self.variant = variant;
        self
    }

    pub fn id(mut self, id: impl Into<String>) -> Self {
        self.id = Some(id.into());
        self
    }

    pub fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut EventContext) + 'static) -> Self {
        self.on_click = Some(Rc::new(handler));
        self
    }

    /// `(fondo, texto, fondo en hover, fondo en active)`.
    fn palette(&self) -> (Option<Token>, Token, Token, Token) {
        match self.variant {
            ButtonVariant::Primary => (Some(Token::Accent), Token::AccentText, Token::AccentHover, Token::Accent),
            ButtonVariant::Danger => (Some(Token::Danger), Token::DangerText, Token::DangerHover, Token::Danger),
            ButtonVariant::Subtle => (Some(Token::ElevatedSurface), Token::Text, Token::Hover, Token::Active),
            ButtonVariant::Ghost => (None, Token::Text, Token::Hover, Token::Active),
        }
    }
}

impl Styled for Button {
    fn style(&mut self) -> &mut Style {
        &mut self.style
    }
}

impl IntoElement for Button {
    fn into_element(self) -> AnyElement {
        let (background, foreground, hover, active) = self.palette();
        let is_subtle = self.variant == ButtonVariant::Subtle;
        let handler = self.on_click.clone();

        div()
            .role(Role::Button)
            .label(self.label.clone())
            .flex_row()
            .items_center()
            .justify_center()
            .h(px(32.0))
            .px_3()
            .rounded_md()
            .text_sm()
            .text_color(foreground)
            .when_some(background, |button, color| button.bg(color))
            .when(is_subtle, |button| button.border_1().border_color(Token::BorderSubtle))
            .hover(|style| style.bg(hover))
            .active(|style| style.bg(active))
            .when_some(self.id, |button, id| button.id(id))
            .when_some(handler, |button, handler| button.cursor_pointer().on_click(move |event, cx| handler(event, cx)))
            .refine_style(&self.style)
            .child(self.label)
            .into_element()
    }
}