use crate::icons::{icondata, Icon};
use leptos::prelude::*;
#[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>
}
}