Askr
UI & Components

Advanced Layout

Use advanced layout with the current published Askr packages.

  • @askrjs/themes0.0.13

How to use advanced layout

Advanced Layout should use the standard themed surface unless the application is deliberately implementing its own design system on top of @askrjs/ui.

  1. Import the themed component from @askrjs/themes/components; use @askrjs/ui directly only when building a custom visual system.
  2. Keep advanced layout labels, state, and application actions visible at the call site instead of styling internal DOM nodes.
  3. Verify keyboard behavior, focus movement or return, disabled state, and both standard themes.
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@askrjs/themes/components';

<Card>
  <CardHeader><CardTitle>Project health</CardTitle><CardDescription>Updated just now</CardDescription></CardHeader>
  <CardContent><ProjectHealth /></CardContent>
</Card>

Purpose

This page extends Application Layout into more involved shells — persistent sidebars, nested content regions, and multi-panel apps — using the same `Block`-based primitives plus `Sidebar` and its parts. As with Application Layout, there's no single component to reach for; it's a set of composable pieces and a recommended way to combine them.

Install and import

`Sidebar`, `SidebarContent`, `SidebarHeader`, `SidebarFooter`, `SidebarGroup`, `SidebarGroupLabel`, `SidebarGroupContent`, `SidebarMenu`, `SidebarMenuItem`, `SidebarMenuButton`, `SidebarMenuAction`, `SidebarMenuBadge`, `SidebarRail`, `SidebarScope`, `SidebarInset`, and `SidebarTrigger` all come from `@askrjs/themes/sidebar` (also available through the `@askrjs/themes/components` barrel). Combine them with `Block`, `Header`, and `Main` from `@askrjs/themes/core` for the surrounding shell.

Live examples

A standard admin layout is `SidebarScope` wrapping a `Sidebar` (with `SidebarHeader`, `SidebarContent` full of `SidebarGroup`/`SidebarMenu` entries, and `SidebarFooter`) alongside a `SidebarInset` holding the routed page content, with `SidebarTrigger` somewhere in the header to toggle it. Set `collapsible="icon"` on `Sidebar` when you want it to shrink to an icon rail instead of disappearing entirely on collapse.

Anatomy

`Sidebar` itself renders as an `aside` and accepts `side` (`'left' | 'right'`), `variant` (`'sidebar' | 'floating' | 'inset'`), and `collapsible` (`'offcanvas' | 'icon' | 'none'`). Inside it, `SidebarGroup` clusters related `SidebarMenuItem`s under an optional `SidebarGroupLabel`, and `SidebarMenuButton`/`SidebarMenuAction` are the actual interactive rows and trailing controls within each item.

State model

Collapse state lives with `SidebarScope`, which coordinates open/closed and (on `variant="icon"`) expanded/rail state across the `Sidebar` and its `SidebarTrigger` — you don't need to track that boolean yourself. Individual `SidebarMenuButton`s and `SidebarMenuAction`s take an `active?: boolean` prop for marking the current route, which is a value you compute from your router, not something the component derives on its own.

Keyboard and accessibility

`SidebarMenuButton` and `SidebarTrigger` accept `tooltip` and `tooltipSide` props, which matter most in the collapsed icon-rail state where the label text is hidden — always set a `tooltip` so icon-only buttons still communicate their purpose to sighted users and, indirectly, screen reader users relying on the accessible name. As with any nav structure, keep `SidebarMenuButton` rendered as real buttons or links rather than divs with click handlers, so keyboard and screen reader navigation work without extra effort.

Styling and tokens

The `variant` prop's three values — `sidebar`, `floating`, `inset` — control fairly different visual treatments (attached, elevated-and-detached, or content-inset), and switching between them is a token-driven style change rather than a structural one. `SidebarMenuButton`'s `size` (`'default' | 'sm' | 'lg'`) and `variant` (`'default' | 'outline'`) follow the same density and variant conventions as `Button`, so a sidebar built from these components looks native next to the rest of the theme rather than like a separate design language.

API

`SidebarProps` omits `as`, `width`, and `shrink` from the general `BlockElementProps<'aside'>` shape and re-adds typed versions of `width` and `shrink`, plus `collapsible`, `side`, and `variant`. `SidebarButtonProps` (used by `SidebarMenuButton` and `SidebarMenuAction`) adds `active`, `asChild`, `size`, `tooltip`, `tooltipSide`, and `variant` on top of native button attributes. The remaining `Sidebar*` parts (`SidebarContent`, `SidebarHeader`, `SidebarFooter`, `SidebarGroup`, etc.) take `SidebarPartProps` — just `as`, `asChild`, and native `div` attributes.

Edge cases

A `collapsible="none"` sidebar ignores `SidebarTrigger` entirely from a visual standpoint, so don't render a trigger for a sidebar that isn't meant to collapse — it'll be misleading UI. Deeply nested `SidebarGroup`s inside `SidebarGroup`s aren't part of the documented shape; keep groups to one level and use `SidebarMenu`/`SidebarMenuItem` for the actual hierarchy of links within a group.

Application Layout covers the simpler header-and-main shell this page builds on top of. NavigationMenu and Navbar are worth comparing for top-nav-driven apps that don't need a persistent side panel. Item and ItemGroup are a reasonable alternative to `SidebarMenu` when you need list rows that aren't specifically navigation.