soma-ui 0.1.1

A Leptos 0.8 component library: 160+ accessible UI components, blocks, charts, and a ChartDB-style schema diagram — with a prebuilt stylesheet.
Documentation
use crate::icons::{icondata, Icon};
use leptos::prelude::*;

/// A single nav item for the Sidebar.
#[derive(Clone)]
pub struct SidebarItem {
    pub label: String,
    pub href: String,
    pub icon: Option<icondata::Icon>,
}

#[component]
pub fn Sidebar(
    #[prop(into)] items: Vec<SidebarItem>,
    #[prop(into)] active_path: Signal<String>,
    #[prop(optional)] brand: Option<AnyView>,
    #[prop(default = String::new())] class: String,
) -> impl IntoView {
    let nav_class = format!(
        "bg-card border-e border-border w-60 flex flex-col h-full {}",
        class
    );

    let items_view = items
        .into_iter()
        .map(|item| {
            let href_attr = item.href.clone();
            let href_cmp = item.href.clone();
            let label = item.label.clone();
            let icon = item.icon;
            view! {
                <a
                    href=href_attr
                    class=move || {
                        if active_path.get() == href_cmp {
                            "flex items-center gap-2 px-3 py-2 rounded-md text-sm font-medium bg-accent text-foreground transition-colors".to_string()
                        } else {
                            "flex items-center gap-2 px-3 py-2 rounded-md text-sm text-muted-foreground hover:text-foreground hover:bg-accent/50 transition-colors".to_string()
                        }
                    }
                >
                    {icon.map(|ic| view! { <Icon icon=Signal::derive(move || ic) attr:class="w-4 h-4 shrink-0" /> })}
                    <span class="truncate">{label}</span>
                </a>
            }
        })
        .collect::<Vec<_>>();

    view! {
        <nav class=nav_class>
            {brand.map(|b| view! { <div class="p-4 border-b border-border">{b}</div> })}
            <div class="flex flex-col gap-0.5 p-2 flex-1">
                {items_view}
            </div>
        </nav>
    }
}