Skip to main content

UX Standards — 17: Application Switcher

Governs: Cross-module navigation between Anshin Health Solutions applications. Parent rules: See 03-SIDEBAR-NAVIGATION.md and 00-OVERVIEW-AND-CSS-RULES.md first.


Overview

The Application Switcher allows users to navigate between Anshin applications directly from the sidebar header. It is triggered by clicking the sidebar header logo/app name area and opens a DropdownMenu listing all available Anshin applications.


Trigger Location

The switcher is embedded in the SidebarHeader — the very top zone of the sidebar. It is not in the header (the header bar to the right of the sidebar). Clicking the trigger opens the application switcher dropdown.

Expanded sidebar — trigger shows shield + app name + subtitle + chevron:

┌─────────────────────────────────────┐
│ [🛡] Anshin Orchestrate ⌄ │ ← Click → opens switcher
│ Tour & Booking Management │
├─────────────────────────────────────┤
│ Nav item │
│ Nav item │
│ ... │

Collapsed sidebar — trigger is the shield icon only (no text, no chevron):

┌──────┐
│ 🛡 │ ← Click → opens switcher
├──────┤
│ [ico]│
│ [ico]│
│ ... │

Visual Anatomy

[▼ Shield + App Name / subtitle]
┌────────────────────────────────────────────┐
│ Anshin Applications │ ← DropdownMenuLabel
├────────────────────────────────────────────┤
│ ✓ Anshin Orchestrate │ ← Current app — checked
│ Tour & booking management │
├────────────────────────────────────────────┤
│ Anshin MCP │
│ Model Context Protocol dashboard │
│ Anshin Comply │
│ Compliance & regulatory management │
│ Anshin Predict │
│ Predictive analytics & forecasting │
│ Anshin Admin Portal │
│ System administration & configuration │
│ Anshin Client Portal │
│ Client-facing portal & self-service │
│ Anshin Engage │
│ Engagement platform & campaigns │
├────────────────────────────────────────────┤
│ Settings [›] │ ← Workspace/account settings
└────────────────────────────────────────────┘

Implementation Pattern

// SidebarHeader with embedded Application Switcher
<SidebarHeader>
<SidebarMenu>
<SidebarMenuItem>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<SidebarMenuButton
size="lg"
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
>
{/* Shield icon — always visible (expanded and collapsed) */}
<img
src="/images/logo-shield.svg"
alt="Anshin"
className="h-8 w-8 shrink-0"
/>
{/* Text — visible in expanded mode only */}
<div className="flex flex-col leading-tight group-data-[collapsible=icon]:hidden">
<span className="font-semibold text-sm">{APP_NAME}</span>
<span className="text-xs text-muted-foreground truncate">
{APP_SUBTITLE}
</span>
</div>
<ChevronsUpDown className="ml-auto h-4 w-4 text-muted-foreground group-data-[collapsible=icon]:hidden" />
</SidebarMenuButton>
</DropdownMenuTrigger>

<DropdownMenuContent
className="w-[240px]"
align="start"
side="bottom"
sideOffset={4}
>
<DropdownMenuLabel className="text-xs text-muted-foreground font-normal">
Anshin Applications
</DropdownMenuLabel>
<DropdownMenuSeparator />

{/* Current app — checkmarked */}
<DropdownMenuItem className="gap-2">
<Check className="h-4 w-4 text-primary shrink-0" />
<div className="flex flex-col">
<span className="font-medium text-sm">{APP_NAME}</span>
<span className="text-xs text-muted-foreground">{APP_DESCRIPTION}</span>
</div>
</DropdownMenuItem>

{/* Other apps */}
{otherApps.map((app) => (
<DropdownMenuItem key={app.id} asChild>
<Link href={app.url} className="gap-2">
<div className="h-4 w-4 shrink-0" /> {/* Spacer to align with checkmark */}
<div className="flex flex-col">
<span className="font-medium text-sm">{app.name}</span>
<span className="text-xs text-muted-foreground">{app.description}</span>
</div>
</Link>
</DropdownMenuItem>
))}

<DropdownMenuSeparator />

{/* Settings link */}
<DropdownMenuItem asChild>
<Link href="/settings" className="flex items-center justify-between">
<span>Settings</span>
<ChevronRight className="h-4 w-4 text-muted-foreground" />
</Link>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>

PropertyValue
ComponentDropdownMenu + DropdownMenuContent
Widthw-[240px]
Alignalign="start"
Sideside="bottom"
OffsetsideOffset={4}
HeaderDropdownMenuLabel"Anshin Applications" (text-xs text-muted-foreground font-normal)

App List Items

Each application entry shows:

  1. Check icon (current app only): Check h-4 w-4 text-primary shrink-0
  2. Spacer div (other apps): h-4 w-4 shrink-0 — maintains alignment with check icon
  3. App name: font-medium text-sm
  4. App description: text-xs text-muted-foreground (one line, truncated)

Anshin Application Catalog

App NameDescriptionURL Pattern
Anshin OrchestrateTour & booking managementorchestrate.anshin.us
Anshin MCPModel Context Protocol dashboardmcp.anshin.us
Anshin ComplyCompliance & regulatory managementcomply.anshin.us
Anshin PredictPredictive analytics & forecastingpredict.anshin.us
Anshin Admin PortalSystem administration & configurationadmin.anshinhealth.net
Anshin Client PortalClient-facing portal & self-serviceportal.anshin.us
Anshin EngageEngagement platform & campaignsengage.anshin.us

Collapsed Sidebar Behavior

When the sidebar is in collapsed (icon-only) mode:

  • Only the shield logo is visible (logo-shield.svg, h-8 w-8) — no app name, no chevron
  • The DropdownMenu trigger still works — clicking the logo icon opens the switcher
  • In collapsed mode the text elements are hidden via group-data-[collapsible=icon]:hidden
  • The DropdownMenu opens from the shield icon position: side="bottom" with sideOffset={4}

The last item in the switcher is a Settings link with a ChevronRight icon on the right:

<DropdownMenuItem asChild>
<Link href="/settings" className="flex items-center justify-between">
<span>Settings</span>
<ChevronRight className="h-4 w-4 text-muted-foreground" />
</Link>
</DropdownMenuItem>

This navigates to the workspace/account settings (different from user-specific settings, which are in the SidebarUser dropdown).


Relation to Logo Navigation

The SidebarHeader logo trigger replaces any plain <Link> to /dashboard that may have existed in earlier implementations. The visual (shield icon) does not change — only the behavior changes from a navigation link to a dropdown trigger.


Violation Checklist

  • Switcher trigger is in SidebarHeader — NOT in the top header bar
  • Shield icon (logo-shield.svg) is always visible in both expanded and collapsed states
  • Expanded: shows app name + subtitle + ChevronsUpDown beside shield
  • Collapsed: shield only — text and chevron hidden via group-data-[collapsible=icon]:hidden
  • DropdownMenuLabel reads "Anshin Applications" with text-xs text-muted-foreground font-normal
  • Current app shows Check h-4 w-4 text-primary shrink-0 icon
  • Other apps have spacer h-4 w-4 shrink-0 div to align text with current app entry
  • Each entry shows app name (font-medium text-sm) + description (text-xs text-muted-foreground)
  • Settings item at bottom with ChevronRight icon
  • Dropdown width: w-[240px]
  • App catalog uses the 7 Anshin applications listed above