use maud::{html, Markup};
#[derive(Clone, Debug, Default)]
pub enum Side {
#[default]
Left,
Right,
}
impl Side {
pub fn as_data(&self) -> &'static str {
match self {
Side::Left => "left",
Side::Right => "right",
}
}
}
#[derive(Clone, Debug, Default)]
pub enum SidebarVariant {
#[default]
Sidebar,
Floating,
Inset,
}
impl SidebarVariant {
pub fn as_data(&self) -> &'static str {
match self {
SidebarVariant::Sidebar => "sidebar",
SidebarVariant::Floating => "floating",
SidebarVariant::Inset => "inset",
}
}
}
#[derive(Clone, Debug, Default)]
pub enum Collapsible {
#[default]
Offcanvas,
Icon,
None,
}
impl Collapsible {
pub fn as_data(&self) -> &'static str {
match self {
Collapsible::Offcanvas => "offcanvas",
Collapsible::Icon => "icon",
Collapsible::None => "none",
}
}
}
#[derive(Clone, Debug)]
pub struct Props {
pub id: String,
pub side: Side,
pub variant: SidebarVariant,
pub collapsible: Collapsible,
pub default_open: bool,
pub children: Markup,
}
impl Default for Props {
fn default() -> Self {
Self {
id: "sidebar".to_string(),
side: Side::default(),
variant: SidebarVariant::default(),
collapsible: Collapsible::default(),
default_open: true,
children: html! {},
}
}
}
pub fn provider(children: Markup) -> Markup {
html! {
div class="mui-sidebar-provider" data-mui="sidebar-provider" {
(children)
}
}
}
pub fn render(props: Props) -> Markup {
let state = if props.default_open {
"expanded"
} else {
"collapsed"
};
html! {
aside
class="mui-sidebar"
id=(props.id)
data-mui="sidebar"
data-state=(state)
data-side=(props.side.as_data())
data-variant=(props.variant.as_data())
data-collapsible=(props.collapsible.as_data())
aria-label="Sidebar"
{
(props.children)
}
}
}
pub fn header(children: Markup) -> Markup {
html! { div class="mui-sidebar__header" { (children) } }
}
pub fn content(children: Markup) -> Markup {
html! { div class="mui-sidebar__content" { (children) } }
}
pub fn footer(children: Markup) -> Markup {
html! { div class="mui-sidebar__footer" { (children) } }
}
pub fn group(children: Markup) -> Markup {
html! { div class="mui-sidebar__group" { (children) } }
}
pub fn group_label(children: Markup) -> Markup {
html! { div class="mui-sidebar__group-label" { (children) } }
}
pub fn group_action(children: Markup) -> Markup {
html! {
button type="button" class="mui-sidebar__group-action" {
(children)
}
}
}
pub fn group_content(children: Markup) -> Markup {
html! { div class="mui-sidebar__group-content" { (children) } }
}
pub fn menu(children: Markup) -> Markup {
html! { ul class="mui-sidebar__menu" { (children) } }
}
pub fn menu_item(children: Markup) -> Markup {
html! { li class="mui-sidebar__menu-item" { (children) } }
}
pub fn menu_button(children: Markup) -> Markup {
html! {
button type="button" class="mui-sidebar__menu-button" {
(children)
}
}
}
pub fn menu_action(children: Markup) -> Markup {
html! {
button type="button" class="mui-sidebar__menu-action" {
(children)
}
}
}
pub fn menu_sub(children: Markup) -> Markup {
html! { ul class="mui-sidebar__menu-sub" { (children) } }
}
pub fn menu_sub_item(children: Markup) -> Markup {
html! { li class="mui-sidebar__menu-sub-item" { (children) } }
}
pub fn menu_badge(children: Markup) -> Markup {
html! { span class="mui-sidebar__menu-badge" { (children) } }
}
pub fn menu_skeleton() -> Markup {
html! {
li class="mui-sidebar__menu-item" {
div class="mui-sidebar__menu-skeleton" {
div class="mui-sidebar__menu-skeleton-icon" {}
div class="mui-sidebar__menu-skeleton-text" {}
}
}
}
}
pub fn trigger(target_id: &str, label: &str) -> Markup {
html! {
button type="button"
class="mui-btn mui-btn--ghost mui-btn--sm mui-sidebar__trigger"
data-mui="sidebar-trigger"
data-target=(target_id)
aria-label=(label)
{
span class="mui-sidebar__trigger-icon" aria-hidden="true" {
"\u{2630}"
}
span class="mui-sidebar__trigger-label" { (label) }
}
}
}
pub fn rail() -> Markup {
html! {
button type="button"
class="mui-sidebar__rail"
data-mui="sidebar-rail"
aria-label="Toggle sidebar"
tabindex="-1"
{}
}
}
pub fn inset(children: Markup) -> Markup {
html! {
main class="mui-sidebar-inset" data-mui="sidebar-inset" {
(children)
}
}
}
pub fn showcase() -> Markup {
html! {
div class="mui-showcase__grid" {
section {
h2 { "App shell (left, icon-collapsible)" }
p class="mui-showcase__caption" {
"Press " kbd { "Cmd/Ctrl" } " + " kbd { "B" } " to toggle, or click the menu button."
}
(provider(html! {
(render(Props {
id: "demo-sidebar".to_string(),
side: Side::Left,
variant: SidebarVariant::Sidebar,
collapsible: Collapsible::Icon,
default_open: true,
children: html! {
(header(html! {
div class="mui-sidebar__brand" {
span class="mui-sidebar__brand-mark" aria-hidden="true" { "M" }
span class="mui-sidebar__brand-name" { "maud-ui" }
}
}))
(content(html! {
(group(html! {
(group_label(html! { "Platform" }))
(group_content(html! {
(menu(html! {
(menu_item(menu_button(html! {
span { "Dashboard" }
})))
(menu_item(menu_button(html! {
span { "Projects" }
(menu_badge(html! { "12" }))
})))
(menu_item(menu_button(html! {
span { "Deployments" }
})))
}))
}))
}))
(group(html! {
(group_label(html! { "Workspace" }))
(group_content(html! {
(menu(html! {
(menu_item(menu_button(html! {
span { "Members" }
})))
(menu_item(menu_button(html! {
span { "Billing" }
})))
(menu_item(menu_button(html! {
span { "Settings" }
})))
}))
}))
}))
}))
(footer(html! {
div class="mui-sidebar__user" {
span class="mui-sidebar__user-avatar" aria-hidden="true" { "JD" }
span class="mui-sidebar__user-name" { "Jane Doe" }
}
}))
(rail())
},
}))
(inset(html! {
div class="mui-sidebar-inset__bar" {
(trigger("demo-sidebar", "Toggle sidebar"))
span class="mui-sidebar-inset__title" { "Dashboard" }
}
div class="mui-sidebar-inset__body" {
p class="mui-placeholder" { "Main content goes here." }
}
}))
}))
}
}
}
}