Skip to content

Sidebar Navigation

The sidebar organizes navigation links into labeled groups using NavGroup and NavItem. A shared HEADER_HEIGHT_CLASS constant keeps all top-level header bars aligned.

NavGroup wraps a set of NavItem elements under a labeled section. It adapts to the sidebar’s collapsed state.

src/shared/components/nav_group.rs
#[component]
pub fn NavGroup(
label: String,
is_collapsed: Signal<bool>,
children: Element,
) -> Element
PropTypeDescription
labelStringSection heading shown when expanded (e.g. "Contacts", "AI")
is_collapsedSignal<bool>Sidebar collapse state
childrenElementNavItem elements to render inside the group

Expanded — renders an uppercase label above the children:

NavGroup { label: "Contacts", is_collapsed: is_collapsed,
NavItem { icon: rsx! { Users { size: 20 } }, label: "Contacts", href: "/contacts", is_collapsed }
NavItem { icon: rsx! { History { size: 20 } }, label: "Calls", href: "/calls", is_collapsed }
}

Collapsed — replaces the label with a thin h-px bg-border separator line, keeping groups visually distinct without text.

NavItem renders a single link with an icon and label. It handles collapsed and active states.

src/shared/components/nav_item.rs
#[component]
pub fn NavItem(
icon: Element,
label: String,
href: String,
is_collapsed: Signal<bool>,
) -> Element
Sidebar stateActive indicator
ExpandedAmber left border (border-l-2 border-primary) + amber icon ([&_svg]:text-primary)
CollapsedMuted background (bg-muted) + amber icon

On mobile, tapping a NavItem auto-collapses the sidebar overlay by calling is_collapsed.set(true).

All items use py-1.5 mb-px rounded-md for tight, uniform spacing.

The sidebar organizes links into five sections:

GroupItems
(standalone)Dashboard
ContactsContacts, Calls, Messaging
ActivityNotifications, Tasks
AIAgents, Knowledge, Analyzers, Text Agents
AutomationPlan Templates, Plans

Settings and Admin sit below a final separator, outside any group. All items except Dashboard, Contacts, and Settings are permission-gated.

src/shared/constants/layout_constant.rs
pub const HEADER_HEIGHT_CLASS: &str = "h-14";

This Tailwind class is shared by three header bars so they stay the same height:

  • Sidebar brand bar — the “Loquent” logo row at the top of the sidebar
  • Main header (Header component) — the top bar with page actions and assistant toggle
  • Assistant panel header (AssistantHeader) — the header inside the assistant panel

Import it from the shared module:

use crate::shared::HEADER_HEIGHT_CLASS;

Apply it with tw_merge!:

div { class: tw_merge!("flex items-center px-4 border-b border-border", HEADER_HEIGHT_CLASS),
// ...
}

The sidebar footer contains a user avatar button that opens an upward popover with three actions: Settings navigation, theme toggle (light/dark), and Log out. The theme state is read from the data-theme DOM attribute on mount and persisted to localStorage under loquent-theme.