PyBlade/ui
Menu⌄
DocsComponentsSidebar

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.

Alpine.js23 files

Installation

pyblade-ui add sidebar

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.

settings.py
TEMPLATES = [
    {
        "BACKEND": "pyblade.django.PyBladeEngine",
        # ...
        "OPTIONS": {
            "context_processors": [
                # ...
                "pyblade_ui.context_processors.sidebar",  # adds sidebar_open
            ],
        },
    },
]

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 set

Widths 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

Offcanvas

Floating

Inset

On the right

Props

<pb-ui.sidebar-provider>
PropDefault
openTrue
collapsible'offcanvas'
variant'sidebar'
side'left'
<pb-ui.sidebar-input>
PropDefault
type'text'
<pb-ui.sidebar-menu-button>
PropDefault
hrefNone
activeFalse
size'default'
variant'default'
tooltip''
<pb-ui.sidebar-menu-action>
PropDefault
show_on_hoverFalse
<pb-ui.sidebar-menu-skeleton>
PropDefault
show_iconFalse
width'70%'
<pb-ui.sidebar-menu-sub-button>
PropDefault
hrefNone
activeFalse
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.