AppDrawer
AppModal navigation panel that slides in from the page edge: trigger button, backdrop, dismiss, focus trap and Escape-to-close. Renders grouped items via `navGroups`, an optional search box (filterAppDrawer) and emits an `appdrawer:select` custom event.
Navigation
Main
Account
<%- include('modules/app/AppDrawer', {
id: 'main-nav',
title: 'Navigation',
side: 'left',
activeId: 'dashboard',
navGroups: [
{ label: 'Main', items: [
{ id: 'dashboard', label: 'Dashboard', iconClass: 'fa-gauge' },
{ id: 'projects', label: 'Projects', iconClass: 'fa-folder', badge: 4 },
{ id: 'tasks', label: 'Tasks', iconClass: 'fa-list-check', badge: 12 }
]},
{ label: 'Account', items: [
{ id: 'settings', label: 'Settings', iconClass: 'fa-gear' },
{ id: 'signout', label: 'Sign out', iconClass: 'fa-right-from-bracket' }
]}
]
}) %>
Navigation
<%- include('modules/app/AppDrawer', {
id: 'account-drawer',
title: 'Account',
side: 'right',
searchable: false,
navItems: [
{ id: 'profile', label: 'Profile', iconClass: 'fa-user' },
{ id: 'billing', label: 'Billing', iconClass: 'fa-credit-card' },
{ id: 'keys', label: 'API keys', iconClass: 'fa-key' },
{ id: 'team', label: 'Team', iconClass: 'fa-users' }
]
}) %>
<%
var _id = locals.id || ('app-drawer-' + Math.random().toString(36).substr(2, 6));
var _title = locals.title || 'Navigation';
var _side = locals.side || 'left';
var _open = !!locals.open;
var _searchable = locals.searchable !== false;
var _navGroups = locals.navGroups || (locals.navItems ? [{ items: locals.navItems }] : []);
var _activeId = locals.activeId || '';
var _triggerLabel = locals.triggerLabel || 'Open Navigation';
var overlayClass = _open ? 'opacity-100' : 'opacity-0 pointer-events-none';
var panelBase = 'relative flex flex-col w-80 max-w-full h-full bg-surface-raised border-border shadow-xl transition-transform duration-200 focus-visible:outline-none';
var panelSide = _side === 'right' ? 'ml-auto border-l' : 'mr-auto border-r';
var panelTranslate = _open ? 'translate-x-0' : (_side === 'right' ? 'translate-x-full' : '-translate-x-full');
%>
<%# Trigger — fallback matches