83 lines
3.3 KiB
Plaintext
83 lines
3.3 KiB
Plaintext
component Sidebar {
|
|
outputs {
|
|
toggle(payload: { open: boolean })
|
|
open(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
|
|
close(payload: { source: string })
|
|
select(payload: { item: string | number | boolean | null | object; value: string | number | boolean; level: string })
|
|
}
|
|
|
|
props {
|
|
size: string = "default"
|
|
color: string = "primary"
|
|
label: string = "Sidebar"
|
|
items: unknown[] = []
|
|
active: string = ""
|
|
orientation: string = "horizontal"
|
|
mobileLabel: string = "Open navigation"
|
|
class: string = ""
|
|
}
|
|
|
|
state mobileOpen: boolean = false
|
|
|
|
functions {
|
|
client function toggleSidebar() {
|
|
mobileOpen = !mobileOpen
|
|
output.toggle({ open: mobileOpen })
|
|
output[mobileOpen ? "open" : "close"]({ source: "mobile" })
|
|
}
|
|
|
|
client function closeSidebar() {
|
|
mobileOpen = false
|
|
output.close({ source: "mobile" })
|
|
}
|
|
|
|
client function selectItem(item, level) {
|
|
mobileOpen = false
|
|
output.select({ item: item, value: item.value || "", level: level })
|
|
}
|
|
}
|
|
|
|
view {
|
|
<div class="wire-sidebar-shell wire-next--color-{color} wire-next--size-{size} {mobileOpen ? 'is-open' : ''} {class}">
|
|
<button type="button" class="wire-sidebar-toggle" aria-label="{mobileLabel}" aria-expanded="{mobileOpen}" @click="toggleSidebar()">
|
|
<span class="icon-[lucide--panel-left-open]" aria-hidden="true"></span>
|
|
<span>{label}</span>
|
|
</button>
|
|
<button type="button" class="wire-sidebar-backdrop" aria-label="Close navigation" @click="closeSidebar()"></button>
|
|
<nav class="wire-next wire-next--sidebar wire-next--{orientation} wire-sidebar-panel" aria-label="{label}">
|
|
<div class="wire-sidebar-panel__head">
|
|
<strong>{label}</strong>
|
|
<button type="button" aria-label="Close navigation" @click="closeSidebar()"><span class="icon-[lucide--x]" aria-hidden="true"></span></button>
|
|
</div>
|
|
<div class="wire-sidebar-items">
|
|
{#each items as item}
|
|
{#if item.children && item.children.length}
|
|
<details class="wire-sidebar-group" name="wire-sidebar-group">
|
|
<summary>
|
|
{#if item.icon}<span class="{item.icon}" aria-hidden="true"></span>{/if}
|
|
<span>{item.label}</span>
|
|
<span class="icon-[lucide--chevron-down]" aria-hidden="true"></span>
|
|
</summary>
|
|
<div class="wire-sidebar-group__children">
|
|
{#each item.children as child}
|
|
<a href="{child.href || '#'}" aria-current="{child.value === active ? 'page' : ''}" @click="selectItem(child, 2)">
|
|
{#if child.icon}<span class="{child.icon}" aria-hidden="true"></span>{/if}
|
|
<span>{child.label}</span>
|
|
</a>
|
|
{/each}
|
|
</div>
|
|
</details>
|
|
{:else}
|
|
<a href="{item.href || '#'}" aria-current="{item.value === active ? 'page' : ''}" @click="selectItem(item, 1)">
|
|
{#if item.icon}<span class="{item.icon}" aria-hidden="true"></span>{/if}
|
|
<span>{item.label}</span>
|
|
</a>
|
|
{/if}
|
|
{/each}
|
|
</div>
|
|
<slot />
|
|
</nav>
|
|
</div>
|
|
}
|
|
}
|