Sidebar
Implemented NavigationRecursive navigation groups, account/zone views, search, loading, resize and full-screen mobile breadcrumbs.
Kumo reference: kumo-ui.com/components/sidebar/
Presentation commands show demo feedback. Read the interaction guide to connect real actions.
Basic
Reference groups with nested Compute / Workers & Pages navigation.
Show template
{% load wdj %}
<div class="flex h-auto flex-col sm:h-[500px] sm:flex-row [&>.wdj-sidebar]:h-[400px] sm:[&>.wdj-sidebar]:h-full w-full min-w-0 overflow-hidden rounded-lg ring-1 ring-kumo-line" x-data="{ selected: 'Main content area' }" @wdj:sidebar-select="selected = $event.detail.label">
{% include "wdj/components/sidebar.html" with brand_mark=True groups=sidebar_reference_groups contained=True show_header=False show_trigger=False aria_label="Basic navigation" default_width=260 persist_key="sidebar-reference-basic" only %}
<div class="flex min-w-0 flex-1 items-center justify-center p-4 text-center text-base text-kumo-subtle" aria-live="polite" x-text="selected">Main content area</div>
</div>
Grouped, collapsible rail
Labelled groups, icon-only collapse, hover-peek and drag-to-resize.
Show template
{% load wdj %}
<div class="w-full sm:h-96 overflow-hidden rounded-lg border border-kumo-hairline">
<div class="flex flex-col sm:flex-row h-full">
{% include "wdj/components/sidebar.html" with brand_mark=True groups=sidebar_groups aria_label="Grouped navigation" brand_label="Console" brand_initials="C" collapsible="icon" peekable=True resizable=True contained=True default_width=232 persist_key="wdj-ex-sidebar-groups" %}
<div class="min-w-0 flex-1 p-4 text-base text-kumo-subtle">
Labelled groups with an icon rail: collapse with the control at the bottom,
hover the rail to peek, and drag the edge (or use the arrow keys) to resize.
</div>
</div>
</div>
Sliding views
Swap the nav body between views inside one panel footprint.
Show template
{% load wdj %}
<div class="w-full sm:h-96 overflow-hidden rounded-lg border border-kumo-hairline">
<div class="flex flex-col sm:flex-row h-full">
{% include "wdj/components/sidebar.html" with brand_mark=True views=sidebar_views active_view="main" aria_label="Sliding views" brand_label="Console" brand_initials="C" contained=True persist_key="wdj-ex-sidebar-views" %}
<div class="min-w-0 flex-1 p-4 text-base text-kumo-subtle">
Sliding views: the segmented control at the top of the rail swaps the nav
content with a horizontal slide, keeping a single panel footprint.
</div>
</div>
</div>
Nested items
Expandable sub-menus built on native <details>.
Show template
{% load wdj %}
<div class="w-full sm:h-88 overflow-hidden rounded-lg border border-kumo-hairline">
<div class="flex flex-col sm:flex-row h-full">
{% include "wdj/components/sidebar.html" with brand_mark=True items=sidebar_items_nested aria_label="Nested navigation" brand_label="Console" brand_initials="C" collapsible="none" contained=True persist_key="wdj-ex-sidebar-nested" %}
<div class="min-w-0 flex-1 p-4 text-base text-kumo-subtle">
Nested groups use native <details> disclosures, so they open and close
without JavaScript.
</div>
</div>
</div>
Static rail
Show template
{% load wdj %}
{% include "wdj/components/sidebar.html" with brand_mark=True contained=True aria_label="Static rail" persist_key="sidebar_static_rail" items=sidebar_items collapsible="none" only %}
Right side
Show template
{% load wdj %}
{% include "wdj/components/sidebar.html" with brand_mark=True contained=True aria_label="Right-side rail" persist_key="sidebar_right_side" groups=sidebar_groups side="right" only %}
Loading
Show template
{% load wdj %}
<div class="flex flex-col gap-3">
<button type="button" data-wdj-sidebar-loading-toggle aria-pressed="true" class="h-9 w-fit rounded-lg bg-kumo-fill px-3 text-base">Toggle loading</button>
<div class="h-96 overflow-hidden rounded-lg ring-1 ring-kumo-line">{% include "wdj/components/sidebar.html" with brand_mark=True contained=True aria_label="Loading rail" persist_key="sidebar_loading" groups=sidebar_reference_groups loading=True only %}</div>
</div>
Initially collapsed
Show template
{% load wdj %}
<div class="flex flex-col sm:flex-row sm:h-80 w-full overflow-hidden rounded-lg ring-1 ring-kumo-hairline">{% include "wdj/components/sidebar.html" with brand_mark=True contained=True items=sidebar_items persist_key="sidebar_initially_collapsed" aria_label="Initially collapsed" default_open=False only %}<div class="min-w-0 flex-1 p-4 text-kumo-subtle">Initially collapsed</div></div>
Peek on hover
Show template
{% load wdj %}
<div class="flex flex-col sm:flex-row sm:h-80 w-full overflow-hidden rounded-lg ring-1 ring-kumo-hairline">{% include "wdj/components/sidebar.html" with brand_mark=True contained=True items=sidebar_items persist_key="sidebar_peek_on_hover" aria_label="Peek on hover" default_open=False peekable=True only %}<div class="min-w-0 flex-1 p-4 text-kumo-subtle">Peek on hover</div></div>
Keyboard resizing
Show template
{% load wdj %}
<div class="flex flex-col sm:flex-row sm:h-80 w-full overflow-hidden rounded-lg ring-1 ring-kumo-hairline">{% include "wdj/components/sidebar.html" with brand_mark=True contained=True items=sidebar_items persist_key="sidebar_keyboard_resizing" aria_label="Keyboard resizing" resizable=True only %}<div class="min-w-0 flex-1 p-4 text-kumo-subtle">Keyboard resizing</div></div>
Wide rail
Show template
{% load wdj %}
<div class="flex flex-col sm:flex-row sm:h-80 w-full overflow-hidden rounded-lg ring-1 ring-kumo-hairline">{% include "wdj/components/sidebar.html" with brand_mark=True contained=True items=sidebar_items persist_key="sidebar_wide_rail" aria_label="Wide rail" default_width=300 only %}<div class="min-w-0 flex-1 p-4 text-kumo-subtle">Wide rail</div></div>
Settings view
Show template
{% load wdj %}
<div class="flex flex-col sm:flex-row sm:h-80 w-full overflow-hidden rounded-lg ring-1 ring-kumo-hairline">{% include "wdj/components/sidebar.html" with brand_mark=True contained=True items=sidebar_items persist_key="sidebar_settings_view" aria_label="Settings view" views=sidebar_views active_view="settings" only %}<div class="min-w-0 flex-1 p-4 text-kumo-subtle">Settings view</div></div>
Full example
Account/zone views, quick search, nested navigation, badges, resizing and collapse.
Show template
{% load wdj %}
<div x-data="{ selected: 'Main content area', query: '' }" @wdj:sidebar-select="selected = $event.detail.label">
<div class="mb-3 flex flex-wrap gap-2">
{% include "wdj/components/button.html" with label="Quick search" icon="search" attrs=sidebar_search_attrs only %}
<button type="button" data-wdj-sidebar-scroll="zone-security" class="h-9 rounded-lg bg-kumo-fill px-3 text-base">Go to zone security</button>
</div>
<div class="flex h-auto flex-col sm:h-[500px] sm:flex-row [&>.wdj-sidebar]:h-[400px] sm:[&>.wdj-sidebar]:h-full min-w-0 overflow-hidden rounded-lg ring-1 ring-kumo-line">
{% include "wdj/components/sidebar.html" with brand_mark=True views=sidebar_reference_views contained=True brand_label="Console" view_controls="header" resizable=True peekable=True auto_scroll=True aria_label="Full example navigation" default_width=240 persist_key="sidebar-reference-full" only %}
<div class="flex min-w-0 flex-1 items-center justify-center p-4 text-center text-base text-kumo-subtle" aria-live="polite" x-text="selected">Main content area</div>
</div>
{% wdj_component "wdj/components/dialog.html" id="sidebar-reference-search" title="Quick search" %}
<div class="flex flex-col gap-3">
<input type="search" aria-label="Search navigation" x-model="query" placeholder="Search navigation…" class="h-9 w-full rounded-lg bg-kumo-control px-3 text-base ring-1 ring-kumo-line">
{% for group in sidebar_reference_groups %}{% for item in group.items %}
{% if item.value %}<button type="button" class="min-h-9 rounded-lg px-3 text-left text-base hover:bg-kumo-tint" x-show="$el.textContent.toLowerCase().includes(query.toLowerCase())" @click="selected = $el.textContent.trim()" data-wdj-dialog-close>{{ item.label }}</button>{% endif %}
{% endfor %}{% endfor %}
</div>
{% endwdj_component %}
</div>
Mobile
Mobile drawer preview with focus trapping, Escape and dismiss controls.
Show template
{% load wdj %}
<div class="flex flex-col gap-3">
<button type="button" data-wdj-sidebar-open="sidebar-reference-mobile" aria-expanded="false" class="h-9 w-fit rounded-lg bg-kumo-fill px-3 text-base">Open mobile navigation</button>
<div class="relative h-[500px] w-full overflow-hidden rounded-lg ring-1 ring-kumo-line">
<div class="absolute inset-0 flex items-center justify-center p-4 text-base text-kumo-subtle">Main content area</div>
{% include "wdj/components/sidebar.html" with brand_mark=True groups=sidebar_reference_groups contained=True mobile_preview=True mobile_breakpoint=9999 show_trigger=False brand_label="Console" aria_label="Mobile preview navigation" persist_key="sidebar-reference-mobile" only %}
</div>
</div>
Full-screen mobile preview
Adjust the phone width, open nested navigation and return with the breadcrumb controls.
Show template
{% load wdj %}
<div class="flex flex-col gap-3" x-data="{ viewport: 375, selected: 'Main content area' }" @wdj:sidebar-select="selected = $event.detail.label">
<label class="flex flex-wrap items-center gap-2 text-base">Viewport width <input type="range" min="320" max="768" value="375" x-model="viewport" aria-label="Mobile viewport width" class="min-w-0 max-w-full"><output x-text="viewport + 'px'">375px</output></label>
<button type="button" data-wdj-sidebar-open="sidebar-reference-mobile-full" aria-expanded="false" class="h-9 w-fit rounded-lg bg-kumo-fill px-3 text-base">Open full-screen mobile preview</button>
<div class="relative h-[500px] max-w-full overflow-hidden rounded-lg ring-1 ring-kumo-line" :style="'width:' + viewport + 'px'">
<div class="absolute inset-0 flex items-center justify-center p-4 text-base text-kumo-subtle" x-text="selected" aria-live="polite">Main content area</div>
{% include "wdj/components/sidebar.html" with brand_mark=True groups=sidebar_reference_groups contained=True mobile_preview=True mobile_breakpoint=9999 full_screen_mobile=True show_trigger=False brand_label="Console" aria_label="Full-screen mobile preview navigation" persist_key="sidebar-reference-mobile-full" only %}
</div>
</div>
Auto scroll to active item
Show template
{% load wdj %}
<div class="h-80 overflow-hidden rounded-lg ring-1 ring-kumo-hairline">{% include "wdj/components/sidebar.html" with brand_mark=True groups=sidebar_auto_groups contained=True auto_scroll=True brand_label="Project navigation" persist_key="audit-sidebar-auto" only %}</div>
Scroll to item
Show template
{% load wdj %}
<button type="button" data-wdj-sidebar-scroll="/guide/?section=30" class="h-9 w-fit rounded-lg bg-kumo-fill px-3 text-base">Scroll to section 30</button><div class="h-80 overflow-hidden rounded-lg ring-1 ring-kumo-hairline">{% include "wdj/components/sidebar.html" with brand_mark=True items=audit_sidebar_items contained=True brand_label="Sections" persist_key="audit-sidebar-scroll" only %}</div>
Transition completion
Show template
{% load wdj %}
<div x-data="{ state: 'Choose a view' }" @wdj:sidebar-transition="state = 'Transition complete: ' + $event.detail.activeView"><div class="h-96 overflow-hidden rounded-lg ring-1 ring-kumo-hairline">{% include "wdj/components/sidebar.html" with brand_mark=True views=sidebar_views contained=True brand_label="Console" persist_key="audit-sidebar-transition" only %}</div><p class="mt-2 text-base" aria-live="polite" x-text="state"></p></div>
Full-screen mobile
This instance fills the phone viewport and restores focus when closed.
Show template
{% load wdj %}
<button type="button" data-wdj-sidebar-open="audit-sidebar-fullscreen" class="h-9 w-fit rounded-lg bg-kumo-fill px-3 text-base lg:hidden">Open full-screen navigation</button><div class="flex min-w-0"><div class="lg:h-80">{% include "wdj/components/sidebar.html" with brand_mark=True items=audit_sidebar_items full_screen_mobile=True class="lg:static! lg:h-full!" brand_label="Full-screen navigation" persist_key="audit-sidebar-fullscreen" only %}</div><p class="min-w-0 flex-1 p-3 text-base text-kumo-subtle">This instance fills the phone viewport and restores focus when closed.</p></div>
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| groups | list[dict] | unset | Sidebar: label/items groups; items support recursive children, id, value, href, view, icon, badge, active and open. |
| items | list[dict] | [] | Component-specific item dictionaries; see each rendered source example and integration context. |
| views | list[dict] | unset | Views; pass the documented value shown in the examples. |
| active_view | string | unset | Active view; pass the documented value shown in the examples. |
| aria_label | string | unset | Aria label; pass the documented value shown in the examples. |
| brand_label | string | unset | Brand label; pass the documented value shown in the examples. |
| brand_href | string | unset | Brand href; pass the documented value shown in the examples. |
| brand_initials | string | unset | Brand initials; pass the documented value shown in the examples. |
| brand_mark | string | unset | Brand mark; pass the documented value shown in the examples. |
| brand_slot | HTML slot | unset | Brand slot; pass the documented value shown in the examples. |
| header_slot | HTML slot | unset | Header slot; pass the documented value shown in the examples. |
| footer_slot | HTML slot | unset | Footer slot; pass the documented value shown in the examples. |
| slot | string / HTML slot | unset | Rich HTML supplied by the wdj_component block tag, rendered in an isolated context. |
| collapsible | string | icon | Collapsible; pass the documented value shown in the examples. |
| default_open | bool | True | Default open; pass the documented value shown in the examples. |
| peekable | bool | False | Peekable; pass the documented value shown in the examples. |
| resizable | bool | False | Resizable; pass the documented value shown in the examples. |
| contained | bool | False | Contained; pass the documented value shown in the examples. |
| default_width | number | 240 | Default width; pass the documented value shown in the examples. |
| min_width | number | 180 | Min width; pass the documented value shown in the examples. |
| max_width | number | 420 | Max width; pass the documented value shown in the examples. |
| side | string | component-specific | Side; pass the documented value shown in the examples. |
| loading | bool | False | Loading; pass the documented value shown in the examples. |
| persist_key | string | unset | Persist key; pass the documented value shown in the examples. |
| auto_scroll | bool | False | Auto scroll; pass the documented value shown in the examples. |
| full_screen_mobile | bool | False | Full screen mobile; pass the documented value shown in the examples. |
| show_header | bool | True | Show header; pass the documented value shown in the examples. |
| show_trigger | bool | True | Show trigger; pass the documented value shown in the examples. |
| view_controls | string | tabs | Sidebar: tabs (default) or header buttons for account/zone switching. |
| mobile_preview | bool | False | Sidebar: contain the mobile backdrop and focus trap within the example. |
| mobile_breakpoint | number | 1024 | Sidebar: enter drawer mode below this viewport width; default 1024px. |
| search_target | string | unset | Search target; pass the documented value shown in the examples. |
| search_label | string | unset | Search label; pass the documented value shown in the examples. |
| search_aria_label | string | unset | Search aria label; pass the documented value shown in the examples. |
| class | string | "" | Class; pass the documented value shown in the examples. |