orbit/kit/components/
button.rs

1// Button component for OrbitKit
2
3use crate::component::{Component, ComponentError, ComponentId, Context, Node};
4use std::any::Any;
5
6/// Button size variants
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum ButtonSize {
9    Small,
10    Medium,
11    Large,
12}
13
14/// Button style variants
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum ButtonVariant {
17    Primary,
18    Secondary,
19    Outline,
20    Ghost,
21    Link,
22}
23
24/// Button component that follows Orbit's design system
25///
26/// # Examples
27///
28/// ```orbit
29/// <template>
30///   <Button
31///     variant="primary"
32///     size="medium"
33///     @click="handle_click"
34///   >
35///     Click me
36///   </Button>
37/// </template>
38///
39/// <code lang="rust">
40/// fn handle_click() {
41///     log::info!("Button clicked!");
42/// }
43/// </code>
44/// ```
45#[derive(Debug)]
46pub struct Button {
47    /// Component ID for tracking
48    id: ComponentId,
49    /// Text content of the button
50    pub text: String,
51    /// Visual style variant of the button
52    pub variant: ButtonVariant,
53    /// Whether the button is disabled
54    pub disabled: bool,
55    /// Size variant of the button
56    pub size: ButtonSize,
57    /// Click event handler
58    pub on_click: Option<fn()>,
59}
60
61/// Properties for the Button component
62#[derive(Debug, Clone)]
63pub struct ButtonProps {
64    /// Text content of the button
65    pub text: String,
66    /// Visual style variant of the button
67    pub variant: Option<ButtonVariant>,
68    /// Whether the button is disabled
69    pub disabled: Option<bool>,
70    /// Size variant of the button
71    pub size: Option<ButtonSize>,
72    /// Click event handler
73    pub on_click: Option<fn()>,
74}
75
76impl Default for Button {
77    fn default() -> Self {
78        Self {
79            id: ComponentId::new(),
80            text: String::new(),
81            variant: ButtonVariant::Primary,
82            disabled: false,
83            size: ButtonSize::Medium,
84            on_click: None,
85        }
86    }
87}
88
89impl Component for Button {
90    type Props = ButtonProps;
91
92    fn component_id(&self) -> ComponentId {
93        self.id
94    }
95
96    fn create(props: Self::Props, _context: Context) -> Self {
97        Self {
98            id: ComponentId::new(),
99            text: props.text,
100            variant: props.variant.unwrap_or(ButtonVariant::Primary),
101            disabled: props.disabled.unwrap_or(false),
102            size: props.size.unwrap_or(ButtonSize::Medium),
103            on_click: props.on_click,
104        }
105    }
106
107    fn update(&mut self, props: Self::Props) -> Result<(), ComponentError> {
108        self.text = props.text;
109        self.variant = props.variant.unwrap_or(self.variant);
110        self.disabled = props.disabled.unwrap_or(self.disabled);
111        self.size = props.size.unwrap_or(self.size);
112        self.on_click = props.on_click;
113        Ok(())
114    }
115
116    fn as_any(&self) -> &dyn Any {
117        self
118    }
119
120    fn as_any_mut(&mut self) -> &mut dyn Any {
121        self
122    }
123
124    fn render(&self) -> Result<Vec<Node>, ComponentError> {
125        // For now, return an empty Vec since we're not yet using the Node system
126        // In a real implementation, this would return the actual DOM nodes
127        Ok(vec![])
128    }
129}