feat(leptos): UI primitives — Button, Badge, Card

This commit is contained in:
asepharyana
2026-07-03 17:41:07 +07:00
parent 65804acaca
commit 2b514142e6
5 changed files with 160 additions and 0 deletions
@@ -1,4 +1,5 @@
pub mod app;
pub mod ui;
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;