Drawer / side panel
In reviewLive · web
Edge · mode: set them, then open a drawer from the matching edge
Drawer opened 0 times · section chat. Esc, the scrim, or Close dismisses it. The island is live.
// Web: React, consuming @dizyx/nockerl-tokens. (Web is the laggard platform;// this is the canonical API the published @dizyx/nockerl-react package exposes.)// NockerlDrawer + NockerlNavSurface are the SAME component ( · D5): the ONE edge-anchored// nav / panel surface. OVERLAY mode composes the shipped NockerlOverlay primitive (scrim +// focus-trap + Esc); INLINE omits it (no scrim; shift the app aside so it stays live) for// the persistent nav-rail / sidebar role. Nav rows are the real NockerlNavItem primitive.import { NockerlDrawer, NockerlNavItem, NockerlButton } from '@dizyx/nockerl-react';
export function Workspace({ stage }: { stage: HTMLElement | null }) { const [nav, setNav] = useState(false); const [inspect, setInspect] = useState(false); return ( <> {/* LEFT: an overlay navigation drawer (mobile nav over a scrim) */} <NockerlDrawer open={nav} onDismiss={() => setNav(false)} stage={stage} edge="left" mode="overlay" title="Nockerl" subtitle="dizyx workspace"> <nav aria-label="Primary"> <NockerlNavItem icon={<ChatIcon />} label="Chat" status="streaming" active onSelect={goChat} /> <NockerlNavItem icon={<TasksIcon />} label="Tasks" count={{ value: 3 }} onSelect={goTasks} /> <NockerlNavItem icon={<FilesIcon />} label="Files" onSelect={goFiles} /> </nav> </NockerlDrawer>
{/* RIGHT: an inline/push inspector drawer (desktop detail pane) */} <NockerlDrawer open={inspect} onDismiss={() => setInspect(false)} stage={stage} edge="right" mode="inline" title="Session details" footer={<NockerlButton text="Open session" variant="primary" onClick={open} />} > <SessionInspector session={active} /> </NockerlDrawer> </> );}// Android: Jetpack Compose Material 3 (canonical drawer primitives).// LEFT navigation drawer: ModalNavigationDrawer over a scrim.import androidx.compose.material3.ModalNavigationDrawerimport androidx.compose.material3.ModalDrawerSheetimport androidx.compose.material3.NavigationDrawerItemimport androidx.compose.material3.rememberDrawerStateimport androidx.compose.material3.DrawerValue
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
ModalNavigationDrawer( drawerState = drawerState, drawerContent = { ModalDrawerSheet { Text("Nockerl", Modifier.padding(16.dp)) NavigationDrawerItem( label = { Text("Chat") }, icon = { Icon(Icons.Outlined.Chat, contentDescription = null) }, selected = section == Section.Chat, onClick = { scope.launch { drawerState.close() }; goChat() }, ) NavigationDrawerItem( label = { Text("Tasks") }, badge = { Text("3") }, selected = section == Section.Tasks, onClick = { goTasks() }, ) } },) { // Main content. A DismissibleNavigationDrawer is the inline/push variant // (no scrim); a PermanentNavigationDrawer is the always-open rail. ChatScreen()}// macOS: SwiftUI (canonical drawer primitives).// LEFT navigation drawer: NavigationSplitView (collapsible sidebar + detail).NavigationSplitView(columnVisibility: $columns) { List(selection: $section) { Label("Chat", systemImage: "bubble.left.and.bubble.right") Label("Tasks", systemImage: "checklist") Label("Files", systemImage: "folder") } .navigationTitle("Nockerl")} detail: { ChatView() // RIGHT inspector / detail drawer: the .inspector modifier (macOS 14+). .inspector(isPresented: $showInspector) { SessionInspectorView(session: active) .inspectorColumnWidth(min: 240, ideal: 280, max: 360) }}Parameters
Section titled “Parameters”| Prop | Type | Default | Description |
|---|---|---|---|
open * | boolean | Whether the drawer is presented. | |
onDismiss * | () => void | Dismiss handler: scrim tap, Esc, or the close button. | |
edge | DrawerEdge | 'left' | Which vertical edge the panel is anchored to + slides from. |
mode | DrawerMode | 'overlay' | 'overlay' = the drawer role (scrim + focus trap); 'inline' = the persistent nav-rail role (no scrim, app stays live). 'modal' is a deprecated alias of 'overlay'. Default 'overlay'. |
title * | string | Accessible title shown in the header (carries the dialog/region name). | |
subtitle | string | Optional supporting line under the title. | |
footer | React.ReactNode | Optional right-aligned action row pinned to the panel footer. | |
stage * | HTMLElement | null | The contained stage element, which gates rendering so the drawer never escapes it. | |
children * | React.ReactNode | Panel body: a nav list (left) or detail content (right). |
| Parameter | Type | Default | Description |
|---|---|---|---|
drawerState | DrawerState | rememberDrawerState(Closed) | Open/closed state. DrawerValue.Open / Closed; animate via drawerState.open() / close(). |
drawerContent * | @Composable ColumnScope.() -> Unit | The sheet content, typically a ModalDrawerSheet wrapping NavigationDrawerItems. | |
modifier | Modifier | Modifier | External modifier applied to the whole drawer container. |
gesturesEnabled | Boolean | true | Whether the edge swipe + scrim drag can open/close the drawer. |
scrimColor | Color | DrawerDefaults.scrimColor | The modal scrim tint over the content. (Resolve to color.scrim.) |
content * | @Composable -> Unit | The main screen behind/beside the drawer (the trailing lambda). | |
selected * | Boolean | NavigationDrawerItem: the selected row gets the cyan container + indicator. | |
onClick * | () -> Unit | NavigationDrawerItem: row activation (usually navigates, then closes the drawer). |
SwiftUI has no single “Drawer” view; the edge-anchored panel is built from two
standard primitives: NavigationSplitView (the collapsible left sidebar) and the
.inspector modifier (the right detail drawer, macOS 14+). State comes from the
bindings below.
| Style | Type | Default | Description |
|---|---|---|---|
NavigationSplitView | View | The left navigation drawer: a sidebar column + a detail column. The sidebar collapses to an overlay on compact widths. | |
columnVisibility | Binding<NavigationSplitViewVisibility> | Drives the sidebar: .all (open) / .detailOnly (collapsed) / .automatic. | |
.inspector(isPresented:) | ViewModifier | The right inspector / detail drawer (macOS 14+). isPresented is a Binding<Bool> that slides it in from the trailing edge. | |
.inspectorColumnWidth | ViewModifier | Sets the inspector’s min / ideal / max width. | |
.navigationTitle | ViewModifier | The drawer/region accessible name, shown at the top of the sidebar. |