feat(leptos): UI primitives — Button, Badge, Card
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
pub mod app;
|
pub mod app;
|
||||||
|
pub mod ui;
|
||||||
|
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
use leptos::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum BadgeVariant {
|
||||||
|
Default,
|
||||||
|
Primary,
|
||||||
|
Success,
|
||||||
|
Warning,
|
||||||
|
Destructive,
|
||||||
|
Outline,
|
||||||
|
Info,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for BadgeVariant {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn Badge(
|
||||||
|
#[prop(optional)] variant: BadgeVariant,
|
||||||
|
children: Children,
|
||||||
|
) -> impl IntoView {
|
||||||
|
let variant_class = match variant {
|
||||||
|
BadgeVariant::Default => "",
|
||||||
|
BadgeVariant::Primary => "badge-primary",
|
||||||
|
BadgeVariant::Success => "badge-success",
|
||||||
|
BadgeVariant::Warning => "badge-warning",
|
||||||
|
BadgeVariant::Destructive => "badge-destructive",
|
||||||
|
BadgeVariant::Outline => "badge-outline",
|
||||||
|
BadgeVariant::Info => "badge-info",
|
||||||
|
};
|
||||||
|
|
||||||
|
let combined = format!("badge {}", variant_class);
|
||||||
|
|
||||||
|
view! {
|
||||||
|
<span class=combined>
|
||||||
|
{children()}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
use leptos::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
pub enum ButtonVariant {
|
||||||
|
#[default]
|
||||||
|
Primary,
|
||||||
|
Secondary,
|
||||||
|
Tertiary,
|
||||||
|
Destructive,
|
||||||
|
Outline,
|
||||||
|
Ghost,
|
||||||
|
Link,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum ButtonSize {
|
||||||
|
Default,
|
||||||
|
Sm,
|
||||||
|
Lg,
|
||||||
|
Icon,
|
||||||
|
IconSm,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ButtonSize {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn Button(
|
||||||
|
#[prop(optional)] variant: ButtonVariant,
|
||||||
|
#[prop(optional)] size: ButtonSize,
|
||||||
|
#[prop(optional)] disabled: bool,
|
||||||
|
#[prop(optional)] class: &'static str,
|
||||||
|
#[prop(optional)] on_click: Option<Box<dyn Fn(leptos::ev::MouseEvent)>>,
|
||||||
|
children: Children,
|
||||||
|
) -> impl IntoView {
|
||||||
|
let variant_class = match variant {
|
||||||
|
ButtonVariant::Primary => "btn-primary",
|
||||||
|
ButtonVariant::Secondary => "btn-secondary",
|
||||||
|
ButtonVariant::Tertiary => "btn-tertiary",
|
||||||
|
ButtonVariant::Destructive => "btn-destructive",
|
||||||
|
ButtonVariant::Outline => "btn-outline",
|
||||||
|
ButtonVariant::Ghost => "btn-ghost",
|
||||||
|
ButtonVariant::Link => "btn-link",
|
||||||
|
};
|
||||||
|
let size_class = match size {
|
||||||
|
ButtonSize::Default => "",
|
||||||
|
ButtonSize::Sm => "btn-sm",
|
||||||
|
ButtonSize::Lg => "btn-lg",
|
||||||
|
ButtonSize::Icon => "btn-icon",
|
||||||
|
ButtonSize::IconSm => "btn-icon-sm",
|
||||||
|
};
|
||||||
|
|
||||||
|
let combined = format!("btn {} {} {}", variant_class, size_class, class);
|
||||||
|
|
||||||
|
view! {
|
||||||
|
<button
|
||||||
|
class=combined
|
||||||
|
disabled=disabled
|
||||||
|
on:click=move |ev| { if let Some(ref cb) = on_click { cb(ev); } }
|
||||||
|
>
|
||||||
|
{children()}
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
use leptos::prelude::*;
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn Card(
|
||||||
|
#[prop(optional)] elevated: bool,
|
||||||
|
#[prop(optional)] bordered: bool,
|
||||||
|
#[prop(optional)] class: &'static str,
|
||||||
|
children: Children,
|
||||||
|
) -> impl IntoView {
|
||||||
|
let combined = format!("card {}", class);
|
||||||
|
|
||||||
|
view! {
|
||||||
|
<div
|
||||||
|
class=combined
|
||||||
|
class:card-elevated=elevated
|
||||||
|
class:card-bordered=bordered
|
||||||
|
>
|
||||||
|
{children()}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn CardHeader(children: Children) -> impl IntoView {
|
||||||
|
view! { <div class="card-header">{children()}</div> }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn CardTitle(children: Children) -> impl IntoView {
|
||||||
|
view! { <h3 class="card-title">{children()}</h3> }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn CardDescription(children: Children) -> impl IntoView {
|
||||||
|
view! { <p class="card-description">{children()}</p> }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn CardContent(children: Children) -> impl IntoView {
|
||||||
|
view! { <div class="card-content">{children()}</div> }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn CardFooter(children: Children) -> impl IntoView {
|
||||||
|
view! { <div class="card-footer">{children()}</div> }
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// services/frontend-leptos/frontend/src/ui/mod.rs
|
||||||
|
pub mod badge;
|
||||||
|
pub mod button;
|
||||||
|
pub mod card;
|
||||||
Reference in New Issue
Block a user