Sidebar
A collapsible app sidebar: offcanvas or icon mode, a sheet on mobile, Ctrl/⌘+B, and its state kept in a cookie read on the server.
<pb-ui.sidebar-provider :open="sidebar_open" collapsible="icon">
<pb-ui.sidebar>
<pb-ui.sidebar-content>
<pb-ui.sidebar-group>
<pb-ui.sidebar-group-label>Application</pb-ui.sidebar-group-label>
<pb-ui.sidebar-group-content>
<pb-ui.sidebar-menu>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" active tooltip="Accueil"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"/><path d="M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg><span>Home</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Messages"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12"/><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"/></svg><span>Messages</span></pb-ui.sidebar-menu-button>
<pb-ui.sidebar-menu-badge>12</pb-ui.sidebar-menu-badge>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Calendrier"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v4"/><path d="M16 2v4"/><rect width="18" height="18" x="3" y="4" rx="2"/><path d="M3 10h18"/></svg><span>Calendar</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Recherche"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34"/><circle cx="11" cy="11" r="8"/></svg><span>Search</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Paramètres"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg><span>Settings</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
</pb-ui.sidebar-menu>
</pb-ui.sidebar-group-content>
</pb-ui.sidebar-group>
</pb-ui.sidebar-content>
<pb-ui.sidebar-rail />
</pb-ui.sidebar>
<pb-ui.sidebar-inset>
<header class="flex h-14 shrink-0 items-center gap-2 border-b px-4">
<pb-ui.sidebar-trigger class="-ml-1" />
<span class="text-sm font-medium">Dashboard</span>
<span class="ml-auto hidden text-xs text-muted-foreground sm:block">Ctrl / ⌘ + B</span>
</header>
<div class="grid flex-1 auto-rows-min gap-4 p-4 md:grid-cols-3">
<div class="aspect-video rounded-xl bg-muted/60"></div>
<div class="aspect-video rounded-xl bg-muted/60"></div>
<div class="aspect-video rounded-xl bg-muted/60"></div>
<div class="min-h-40 rounded-xl bg-muted/60 md:col-span-3"></div>
</div>
</pb-ui.sidebar-inset>
</pb-ui.sidebar-provider>Installation
pyblade-ui add sidebar- Install the dependencies
Alpine.js, loaded in your
<head>. - Copy these files into your projectcomponents/ui/sidebar_provider.html
@props({'open': True, 'collapsible': 'offcanvas', 'variant': 'sidebar', 'side': 'left'}) <div data-slot="sidebar-wrapper" data-state="{{ {'True': 'expanded', 'False': 'collapsed'}[str(bool(open))] }}" data-collapsible="{{ {'True': '', 'False': collapsible}[str(bool(open))] }}" data-variant="{{ variant }}" data-side="{{ side }}" data-mobile="closed" x-data="{ open: {{ str(bool(open)).lower() }}, openMobile: false, mobile: window.matchMedia('(max-width: 767px)').matches, setOpen(value) { this.open = value; document.cookie = 'sidebar_state=' + value + '; path=/; max-age=604800; samesite=lax'; }, toggle() { this.mobile ? (this.openMobile = !this.openMobile) : this.setOpen(!this.open) }, }" x-init="window.matchMedia('(max-width: 767px)').addEventListener('change', (e) => { mobile = e.matches; openMobile = false })" x-bind:data-state="open ? 'expanded' : 'collapsed'" x-bind:data-collapsible="open ? '' : '{{ collapsible }}'" x-bind:data-mobile="openMobile ? 'open' : 'closed'" x-on:keydown.window="($event.metaKey || $event.ctrlKey) && $event.key.toLowerCase() === 'b' && ($event.preventDefault(), toggle())" x-on:keydown.escape.window="openMobile = false" x-effect="document.body.classList.toggle('overflow-hidden', openMobile && mobile)" style="--sidebar-width: 16rem; --sidebar-width-mobile: 18rem; --sidebar-width-icon: 3rem" {{ attributes.cn("group/sidebar flex min-h-svh w-full data-[variant=inset]:bg-sidebar") }}>{{ slot }}</div>components/ui/sidebar.html<div data-slot="sidebar" class="text-sidebar-foreground group-data-[side=right]/sidebar:order-last"> <div data-slot="sidebar-gap" class="relative hidden w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear md:block group-data-[collapsible=offcanvas]/sidebar:w-0 group-data-[collapsible=icon]/sidebar:w-(--sidebar-width-icon) group-data-[variant=floating]/sidebar:group-data-[collapsible=icon]/sidebar:w-[calc(var(--sidebar-width-icon)+1rem)] group-data-[variant=inset]/sidebar:group-data-[collapsible=icon]/sidebar:w-[calc(var(--sidebar-width-icon)+1rem)]"></div> <div data-slot="sidebar-container" class="fixed inset-y-0 z-50 flex h-svh w-(--sidebar-width-mobile) transition-[left,right,width,translate] duration-200 ease-linear md:z-10 md:w-(--sidebar-width) group-data-[side=left]/sidebar:left-0 group-data-[side=right]/sidebar:right-0 max-md:group-data-[mobile=closed]/sidebar:group-data-[side=left]/sidebar:-translate-x-full max-md:group-data-[mobile=closed]/sidebar:group-data-[side=right]/sidebar:translate-x-full md:group-data-[collapsible=offcanvas]/sidebar:group-data-[side=left]/sidebar:left-[calc(var(--sidebar-width)*-1)] md:group-data-[collapsible=offcanvas]/sidebar:group-data-[side=right]/sidebar:right-[calc(var(--sidebar-width)*-1)] md:group-data-[collapsible=icon]/sidebar:w-(--sidebar-width-icon) md:group-data-[variant=floating]/sidebar:p-2 md:group-data-[variant=inset]/sidebar:p-2 md:group-data-[variant=floating]/sidebar:group-data-[collapsible=icon]/sidebar:w-[calc(var(--sidebar-width-icon)+1rem+2px)] md:group-data-[variant=inset]/sidebar:group-data-[collapsible=icon]/sidebar:w-[calc(var(--sidebar-width-icon)+1rem+2px)] group-data-[variant=sidebar]/sidebar:group-data-[side=left]/sidebar:border-r group-data-[variant=sidebar]/sidebar:group-data-[side=right]/sidebar:border-l border-sidebar-border"> <div data-slot="sidebar-inner" {{ attributes.cn("flex h-full w-full flex-col bg-sidebar md:group-data-[variant=floating]/sidebar:rounded-lg md:group-data-[variant=floating]/sidebar:border md:group-data-[variant=floating]/sidebar:border-sidebar-border md:group-data-[variant=floating]/sidebar:shadow-sm") }}>{{ slot }}</div> </div> <div data-slot="sidebar-overlay" x-show="openMobile" x-cloak x-transition.opacity x-on:click="openMobile = false" class="fixed inset-0 z-40 bg-black/50 md:hidden"></div> </div>components/ui/sidebar_trigger.html<button type="button" data-slot="sidebar-trigger" x-on:click="toggle()" {{ attributes.cn("inline-flex size-7 shrink-0 cursor-pointer items-center justify-center rounded-md transition-all outline-none hover:bg-accent hover:text-accent-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50 dark:hover:bg-accent/50 [&_svg]:size-4") }}> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M9 3v18"/></svg> <span class="sr-only">Toggle Sidebar</span> </button>components/ui/sidebar_rail.html<button type="button" data-slot="sidebar-rail" x-on:click="toggle()" tabindex="-1" aria-label="Toggle Sidebar" title="Toggle Sidebar" {{ attributes.cn( "absolute inset-y-0 z-20 hidden w-4 cursor-pointer transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border md:flex", "group-data-[side=left]/sidebar:-right-4 group-data-[side=right]/sidebar:left-0 group-data-[side=left]/sidebar:cursor-w-resize group-data-[side=right]/sidebar:cursor-e-resize", "group-data-[side=left]/sidebar:group-data-[state=collapsed]/sidebar:cursor-e-resize group-data-[side=right]/sidebar:group-data-[state=collapsed]/sidebar:cursor-w-resize", "group-data-[collapsible=offcanvas]/sidebar:translate-x-0 group-data-[collapsible=offcanvas]/sidebar:after:left-full group-data-[side=left]/sidebar:group-data-[collapsible=offcanvas]/sidebar:-right-2 group-data-[side=right]/sidebar:group-data-[collapsible=offcanvas]/sidebar:-left-2", ) }}></button>components/ui/sidebar_inset.html<main data-slot="sidebar-inset" {{ attributes.cn( "relative flex w-full min-w-0 flex-1 flex-col bg-background", "md:group-data-[variant=inset]/sidebar:m-2 md:group-data-[variant=inset]/sidebar:ml-0 md:group-data-[variant=inset]/sidebar:rounded-xl md:group-data-[variant=inset]/sidebar:shadow-sm md:group-data-[variant=inset]/sidebar:group-data-[state=collapsed]/sidebar:ml-2", ) }}>{{ slot }}</main>components/ui/sidebar_header.html<div data-slot="sidebar-header" {{ attributes.cn("flex flex-col gap-2 p-2") }}>{{ slot }}</div>components/ui/sidebar_footer.html<div data-slot="sidebar-footer" {{ attributes.cn("flex flex-col gap-2 p-2") }}>{{ slot }}</div>components/ui/sidebar_separator.html<div role="separator" data-slot="sidebar-separator" {{ attributes.cn("mx-2 h-px w-auto shrink-0 bg-sidebar-border") }}></div>components/ui/sidebar_content.html<div data-slot="sidebar-content" {{ attributes.cn("flex min-h-0 flex-1 flex-col gap-2 overflow-auto md:group-data-[collapsible=icon]/sidebar:overflow-visible") }}>{{ slot }}</div>components/ui/sidebar_input.html@props({'type': 'text'}) <input type="{{ type }}" data-slot="sidebar-input" {{ attributes.cn("h-8 w-full min-w-0 rounded-md border border-input bg-background px-3 py-1 text-sm shadow-none outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 dark:bg-input/30") }} />components/ui/sidebar_group.html<div data-slot="sidebar-group" {{ attributes.cn("relative flex w-full min-w-0 flex-col p-2") }}>{{ slot }}</div>components/ui/sidebar_group_label.html<div data-slot="sidebar-group-label" {{ attributes.cn("flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium whitespace-nowrap text-sidebar-foreground/70 outline-hidden transition-[margin,opacity] duration-200 ease-linear md:group-data-[collapsible=icon]/sidebar:-mt-8 md:group-data-[collapsible=icon]/sidebar:opacity-0 [&>svg]:size-4 [&>svg]:shrink-0") }}>{{ slot }}</div>components/ui/sidebar_group_action.html<button type="button" data-slot="sidebar-group-action" {{ attributes.cn("absolute top-3.5 right-3 flex aspect-square w-5 cursor-pointer items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 after:absolute after:-inset-2 md:after:hidden md:group-data-[collapsible=icon]/sidebar:hidden [&>svg]:size-4 [&>svg]:shrink-0") }}>{{ slot }}</button>components/ui/sidebar_group_content.html<div data-slot="sidebar-group-content" {{ attributes.cn("w-full text-sm") }}>{{ slot }}</div>components/ui/sidebar_menu.html<ul data-slot="sidebar-menu" {{ attributes.cn("flex w-full min-w-0 flex-col gap-1") }}>{{ slot }}</ul>components/ui/sidebar_menu_item.html<li data-slot="sidebar-menu-item" {{ attributes.cn("group/menu-item relative") }}>{{ slot }}</li>components/ui/sidebar_menu_button.html@props({'href': None, 'active': False, 'size': 'default', 'variant': 'default', 'tooltip': ''}) <a data-slot="sidebar-menu-button" @if(href)href="{{ href }}"@endif tabindex="0" @if(active)aria-current="page"@endif data-active="{{ str(bool(active)).lower() }}" data-size="{{ size }}" {{ attributes.cn( "group/menu-button peer/menu-button relative flex w-full cursor-pointer items-center gap-2 rounded-md p-2 text-left text-sm whitespace-nowrap ring-sidebar-ring outline-hidden transition-[width,height,padding] select-none", "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground aria-disabled:pointer-events-none aria-disabled:opacity-50", "data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground group-has-data-[slot=sidebar-menu-action]/menu-item:pr-8", "[&>span:not([data-slot])]:min-w-0 [&>span:not([data-slot])]:truncate [&>svg]:size-4 [&>svg]:shrink-0", "md:group-data-[collapsible=icon]/sidebar:size-8! md:group-data-[collapsible=icon]/sidebar:p-2! md:group-data-[collapsible=icon]/sidebar:[&>:not(:first-child):not([data-slot=sidebar-tooltip])]:hidden", { 'default': '', 'outline': 'bg-background shadow-[0_0_0_1px_var(--sidebar-border)] hover:shadow-[0_0_0_1px_var(--sidebar-accent)]', }[variant], { 'default': 'h-8 text-sm', 'sm': 'h-7 text-xs', 'lg': 'h-12 text-sm md:group-data-[collapsible=icon]/sidebar:p-0!', }[size], ) }}>{{ slot }}@if(tooltip)<span data-slot="sidebar-tooltip" role="tooltip" class="pointer-events-none absolute top-1/2 left-full z-50 ml-3 hidden w-max -translate-y-1/2 rounded-md bg-foreground px-3 py-1.5 text-xs font-normal text-background opacity-0 transition-opacity group-hover/menu-button:opacity-100 group-focus-visible/menu-button:opacity-100 md:group-data-[collapsible=icon]/sidebar:block">{{ tooltip }}</span>@endif</a>components/ui/sidebar_menu_action.html@props({'show_on_hover': False}) <button type="button" data-slot="sidebar-menu-action" {{ attributes.cn( "absolute top-1.5 right-1 flex aspect-square w-5 cursor-pointer items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform peer-hover/menu-button:text-sidebar-accent-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 after:absolute after:-inset-2 md:after:hidden md:group-data-[collapsible=icon]/sidebar:hidden [&>svg]:size-4 [&>svg]:shrink-0", {'True': 'group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 peer-data-[active=true]/menu-button:text-sidebar-accent-foreground md:opacity-0', 'False': ''}[str(bool(show_on_hover))], ) }}>{{ slot }}</button>components/ui/sidebar_menu_badge.html<div data-slot="sidebar-menu-badge" {{ attributes.cn("pointer-events-none absolute top-1.5 right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium text-sidebar-foreground tabular-nums select-none peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground md:group-data-[collapsible=icon]/sidebar:hidden") }}>{{ slot }}</div>components/ui/sidebar_menu_skeleton.html@props({'show_icon': False, 'width': '70%'}) <div data-slot="sidebar-menu-skeleton" {{ attributes.cn("flex h-8 items-center gap-2 rounded-md px-2") }}> @if(show_icon)<div class="size-4 animate-pulse rounded-md bg-sidebar-accent"></div>@endif <div class="h-4 max-w-(--skeleton-width) flex-1 animate-pulse rounded-md bg-sidebar-accent" style="--skeleton-width: {{ width }}"></div> </div>components/ui/sidebar_menu_sub.html<ul data-slot="sidebar-menu-sub" {{ attributes.cn("mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5 md:group-data-[collapsible=icon]/sidebar:hidden") }}>{{ slot }}</ul>components/ui/sidebar_menu_sub_item.html<li data-slot="sidebar-menu-sub-item" {{ attributes.cn("group/menu-sub-item relative") }}>{{ slot }}</li>components/ui/sidebar_menu_sub_button.html@props({'href': None, 'active': False, 'size': 'md'}) <a data-slot="sidebar-menu-sub-button" @if(href)href="{{ href }}"@endif tabindex="0" @if(active)aria-current="page"@endif data-active="{{ str(bool(active)).lower() }}" data-size="{{ size }}" {{ attributes.cn( "flex h-7 min-w-0 -translate-x-px cursor-pointer items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground ring-sidebar-ring outline-hidden hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground", {'sm': 'text-xs', 'md': 'text-sm'}[size], ) }}>{{ slot }}</a> - Update the path to fit your project
The
componentsfolder is the one set inpyblade.toml.
Usage
The tags <pb-ui.sidebar-provider> <pb-ui.sidebar> <pb-ui.sidebar-trigger> <pb-ui.sidebar-rail> <pb-ui.sidebar-inset> <pb-ui.sidebar-header> <pb-ui.sidebar-footer> <pb-ui.sidebar-separator> <pb-ui.sidebar-content> <pb-ui.sidebar-input> <pb-ui.sidebar-group> <pb-ui.sidebar-group-label> <pb-ui.sidebar-group-action> <pb-ui.sidebar-group-content> <pb-ui.sidebar-menu> <pb-ui.sidebar-menu-item> <pb-ui.sidebar-menu-button> <pb-ui.sidebar-menu-action> <pb-ui.sidebar-menu-badge> <pb-ui.sidebar-menu-skeleton> <pb-ui.sidebar-menu-sub> <pb-ui.sidebar-menu-sub-item> <pb-ui.sidebar-menu-sub-button> are available in all your templates.
<pb-ui.sidebar-provider :open="sidebar_open" collapsible="icon">
<pb-ui.sidebar>
<pb-ui.sidebar-content>
<pb-ui.sidebar-group>
<pb-ui.sidebar-group-label>Application</pb-ui.sidebar-group-label>
<pb-ui.sidebar-menu>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="/" active tooltip="Home"><span>Home</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
</pb-ui.sidebar-menu>
</pb-ui.sidebar-group>
</pb-ui.sidebar-content>
<pb-ui.sidebar-rail />
</pb-ui.sidebar>
<pb-ui.sidebar-inset>
<header class="flex h-14 items-center gap-2 border-b px-4"><pb-ui.sidebar-trigger /></header>
<main class="p-4">...</main>
</pb-ui.sidebar-inset>
</pb-ui.sidebar-provider>
{# sidebar_open comes from the cookie: pyblade_ui.sidebar_open(request), or the Django context processor #}Server-side state
When the sidebar is collapsed or expanded, it writes the cookie sidebar_state=true|false (7 days). On the next request the server reads it back and passes sidebar_open to the provider: the page arrives in the right state, with no flash and no wait for JavaScript.
TEMPLATES = [
{
"BACKEND": "pyblade.django.PyBladeEngine",
# ...
"OPTIONS": {
"context_processors": [
# ...
"pyblade_ui.context_processors.sidebar", # adds sidebar_open
],
},
},
]from flask import request
from pyblade_ui import sidebar_open
@app.get("/dashboard")
def dashboard():
return render("dashboard", sidebar_open=sidebar_open(request))from fastapi import Request
from pyblade_ui import sidebar_open
@app.get("/dashboard")
def dashboard(request: Request):
return render("dashboard", sidebar_open=sidebar_open(request))Then in the template: <pb-ui.sidebar-provider :open="sidebar_open">. sidebar_open(request, default=True) accepts Django's request (request.COOKIES) as well as Flask, Starlette, FastAPI, Litestar, Quart or Sanic requests (request.cookies).
Colors
The sidebar has its own variables: --sidebar, --sidebar-foreground, --sidebar-primary, --sidebar-accent, --sidebar-border, --sidebar-ring. If your theme.css predates the sidebar, regenerate it:
pyblade-ui theme setWidths are set on the provider: --sidebar-width (16rem), --sidebar-width-mobile (18rem) and --sidebar-width-icon (3rem), for example style="--sidebar-width: 20rem".
Keyboard and mobile
Ctrl + B (or ⌘ + B) collapses or expands the sidebar. Below 768px it becomes a panel that slides over the page, with a clickable backdrop and Escape to close it; the mobile state is not saved in the cookie.
Examples
Collapsed on load (cookie set to false)
<pb-ui.sidebar-provider :open="False" collapsible="icon">
<pb-ui.sidebar>
<pb-ui.sidebar-content>
<pb-ui.sidebar-group>
<pb-ui.sidebar-group-label>Application</pb-ui.sidebar-group-label>
<pb-ui.sidebar-group-content>
<pb-ui.sidebar-menu>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" active tooltip="Accueil"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"/><path d="M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg><span>Home</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Messages"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12"/><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"/></svg><span>Messages</span></pb-ui.sidebar-menu-button>
<pb-ui.sidebar-menu-badge>12</pb-ui.sidebar-menu-badge>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Calendrier"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v4"/><path d="M16 2v4"/><rect width="18" height="18" x="3" y="4" rx="2"/><path d="M3 10h18"/></svg><span>Calendar</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Recherche"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34"/><circle cx="11" cy="11" r="8"/></svg><span>Search</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Paramètres"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg><span>Settings</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
</pb-ui.sidebar-menu>
</pb-ui.sidebar-group-content>
</pb-ui.sidebar-group>
</pb-ui.sidebar-content>
<pb-ui.sidebar-rail />
</pb-ui.sidebar>
<pb-ui.sidebar-inset>
<header class="flex h-14 shrink-0 items-center gap-2 border-b px-4">
<pb-ui.sidebar-trigger class="-ml-1" />
<span class="text-sm font-medium">Rendered collapsed by the server</span>
<span class="ml-auto hidden text-xs text-muted-foreground sm:block">Ctrl / ⌘ + B</span>
</header>
<div class="grid flex-1 auto-rows-min gap-4 p-4 md:grid-cols-3">
<div class="aspect-video rounded-xl bg-muted/60"></div>
<div class="aspect-video rounded-xl bg-muted/60"></div>
<div class="aspect-video rounded-xl bg-muted/60"></div>
<div class="min-h-40 rounded-xl bg-muted/60 md:col-span-3"></div>
</div>
</pb-ui.sidebar-inset>
</pb-ui.sidebar-provider>Offcanvas
<pb-ui.sidebar-provider collapsible="offcanvas">
<pb-ui.sidebar>
<pb-ui.sidebar-content>
<pb-ui.sidebar-group>
<pb-ui.sidebar-group-label>Application</pb-ui.sidebar-group-label>
<pb-ui.sidebar-group-content>
<pb-ui.sidebar-menu>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" active tooltip="Accueil"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"/><path d="M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg><span>Home</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Messages"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12"/><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"/></svg><span>Messages</span></pb-ui.sidebar-menu-button>
<pb-ui.sidebar-menu-badge>12</pb-ui.sidebar-menu-badge>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Calendrier"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v4"/><path d="M16 2v4"/><rect width="18" height="18" x="3" y="4" rx="2"/><path d="M3 10h18"/></svg><span>Calendar</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Recherche"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34"/><circle cx="11" cy="11" r="8"/></svg><span>Search</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Paramètres"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg><span>Settings</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
</pb-ui.sidebar-menu>
</pb-ui.sidebar-group-content>
</pb-ui.sidebar-group>
</pb-ui.sidebar-content>
<pb-ui.sidebar-rail />
</pb-ui.sidebar>
<pb-ui.sidebar-inset>
<header class="flex h-14 shrink-0 items-center gap-2 border-b px-4">
<pb-ui.sidebar-trigger class="-ml-1" />
<span class="text-sm font-medium">The sidebar slides fully off screen</span>
<span class="ml-auto hidden text-xs text-muted-foreground sm:block">Ctrl / ⌘ + B</span>
</header>
<div class="grid flex-1 auto-rows-min gap-4 p-4 md:grid-cols-3">
<div class="aspect-video rounded-xl bg-muted/60"></div>
<div class="aspect-video rounded-xl bg-muted/60"></div>
<div class="aspect-video rounded-xl bg-muted/60"></div>
<div class="min-h-40 rounded-xl bg-muted/60 md:col-span-3"></div>
</div>
</pb-ui.sidebar-inset>
</pb-ui.sidebar-provider>Floating
<pb-ui.sidebar-provider variant="floating" collapsible="icon">
<pb-ui.sidebar>
<pb-ui.sidebar-content>
<pb-ui.sidebar-group>
<pb-ui.sidebar-group-label>Application</pb-ui.sidebar-group-label>
<pb-ui.sidebar-group-content>
<pb-ui.sidebar-menu>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" active tooltip="Accueil"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"/><path d="M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg><span>Home</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Messages"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12"/><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"/></svg><span>Messages</span></pb-ui.sidebar-menu-button>
<pb-ui.sidebar-menu-badge>12</pb-ui.sidebar-menu-badge>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Calendrier"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v4"/><path d="M16 2v4"/><rect width="18" height="18" x="3" y="4" rx="2"/><path d="M3 10h18"/></svg><span>Calendar</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Recherche"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34"/><circle cx="11" cy="11" r="8"/></svg><span>Search</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Paramètres"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg><span>Settings</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
</pb-ui.sidebar-menu>
</pb-ui.sidebar-group-content>
</pb-ui.sidebar-group>
</pb-ui.sidebar-content>
<pb-ui.sidebar-rail />
</pb-ui.sidebar>
<pb-ui.sidebar-inset>
<header class="flex h-14 shrink-0 items-center gap-2 border-b px-4">
<pb-ui.sidebar-trigger class="-ml-1" />
<span class="text-sm font-medium">Floating variant</span>
<span class="ml-auto hidden text-xs text-muted-foreground sm:block">Ctrl / ⌘ + B</span>
</header>
<div class="grid flex-1 auto-rows-min gap-4 p-4 md:grid-cols-3">
<div class="aspect-video rounded-xl bg-muted/60"></div>
<div class="aspect-video rounded-xl bg-muted/60"></div>
<div class="aspect-video rounded-xl bg-muted/60"></div>
<div class="min-h-40 rounded-xl bg-muted/60 md:col-span-3"></div>
</div>
</pb-ui.sidebar-inset>
</pb-ui.sidebar-provider>Inset
<pb-ui.sidebar-provider variant="inset" collapsible="icon">
<pb-ui.sidebar>
<pb-ui.sidebar-content>
<pb-ui.sidebar-group>
<pb-ui.sidebar-group-label>Application</pb-ui.sidebar-group-label>
<pb-ui.sidebar-group-content>
<pb-ui.sidebar-menu>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" active tooltip="Accueil"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"/><path d="M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg><span>Home</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Messages"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12"/><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"/></svg><span>Messages</span></pb-ui.sidebar-menu-button>
<pb-ui.sidebar-menu-badge>12</pb-ui.sidebar-menu-badge>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Calendrier"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v4"/><path d="M16 2v4"/><rect width="18" height="18" x="3" y="4" rx="2"/><path d="M3 10h18"/></svg><span>Calendar</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Recherche"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34"/><circle cx="11" cy="11" r="8"/></svg><span>Search</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Paramètres"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg><span>Settings</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
</pb-ui.sidebar-menu>
</pb-ui.sidebar-group-content>
</pb-ui.sidebar-group>
</pb-ui.sidebar-content>
<pb-ui.sidebar-rail />
</pb-ui.sidebar>
<pb-ui.sidebar-inset>
<header class="flex h-14 shrink-0 items-center gap-2 border-b px-4">
<pb-ui.sidebar-trigger class="-ml-1" />
<span class="text-sm font-medium">Inset variant</span>
<span class="ml-auto hidden text-xs text-muted-foreground sm:block">Ctrl / ⌘ + B</span>
</header>
<div class="grid flex-1 auto-rows-min gap-4 p-4 md:grid-cols-3">
<div class="aspect-video rounded-xl bg-muted/60"></div>
<div class="aspect-video rounded-xl bg-muted/60"></div>
<div class="aspect-video rounded-xl bg-muted/60"></div>
<div class="min-h-40 rounded-xl bg-muted/60 md:col-span-3"></div>
</div>
</pb-ui.sidebar-inset>
</pb-ui.sidebar-provider>On the right
<pb-ui.sidebar-provider side="right">
<pb-ui.sidebar>
<pb-ui.sidebar-content>
<pb-ui.sidebar-group>
<pb-ui.sidebar-group-label>Application</pb-ui.sidebar-group-label>
<pb-ui.sidebar-group-content>
<pb-ui.sidebar-menu>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" active tooltip="Accueil"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"/><path d="M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg><span>Home</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Messages"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12"/><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"/></svg><span>Messages</span></pb-ui.sidebar-menu-button>
<pb-ui.sidebar-menu-badge>12</pb-ui.sidebar-menu-badge>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Calendrier"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v4"/><path d="M16 2v4"/><rect width="18" height="18" x="3" y="4" rx="2"/><path d="M3 10h18"/></svg><span>Calendar</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Recherche"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34"/><circle cx="11" cy="11" r="8"/></svg><span>Search</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-item>
<pb-ui.sidebar-menu-button href="#" tooltip="Paramètres"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg><span>Settings</span></pb-ui.sidebar-menu-button>
</pb-ui.sidebar-menu-item>
</pb-ui.sidebar-menu>
</pb-ui.sidebar-group-content>
</pb-ui.sidebar-group>
</pb-ui.sidebar-content>
<pb-ui.sidebar-rail />
</pb-ui.sidebar>
<pb-ui.sidebar-inset>
<header class="flex h-14 shrink-0 items-center gap-2 border-b px-4">
<pb-ui.sidebar-trigger class="-ml-1" />
<span class="text-sm font-medium">Sidebar on the right</span>
<span class="ml-auto hidden text-xs text-muted-foreground sm:block">Ctrl / ⌘ + B</span>
</header>
<div class="grid flex-1 auto-rows-min gap-4 p-4 md:grid-cols-3">
<div class="aspect-video rounded-xl bg-muted/60"></div>
<div class="aspect-video rounded-xl bg-muted/60"></div>
<div class="aspect-video rounded-xl bg-muted/60"></div>
<div class="min-h-40 rounded-xl bg-muted/60 md:col-span-3"></div>
</div>
</pb-ui.sidebar-inset>
</pb-ui.sidebar-provider>Props
| Prop | Default |
|---|---|
| open | True |
| collapsible | 'offcanvas' |
| variant | 'sidebar' |
| side | 'left' |
| Prop | Default |
|---|---|
| type | 'text' |
| Prop | Default |
|---|---|
| href | None |
| active | False |
| size | 'default' |
| variant | 'default' |
| tooltip | '' |
| Prop | Default |
|---|---|
| show_on_hover | False |
| Prop | Default |
|---|---|
| show_icon | False |
| width | '70%' |
| Prop | Default |
|---|---|
| href | None |
| active | False |
| size | 'md' |
Any other attribute (class, id, x-on:click, hx-post…) is passed to the root element; your Tailwind classes win over the component's.