AWS-Style Panel Menu Design¶
Overview¶
Replace the current sidebar with an AWS Console-inspired navigation panel that adapts to user behavior and role.
AWS Console Menu Features (Reference)¶
AWS Console sidebar includes: 1. Pinned/Favorites - User-pinned services at top 2. Recently Visited - Last 5-10 accessed services 3. All Services - Grouped by category (Compute, Storage, etc.) 4. Search - Quick filter across all menu items 5. Collapse/Expand - Icon-only mode
Proposed cbapp Panel Features¶
1. Quick Access Section (Top)¶
Personalized shortcuts based on usage patterns:
┌─────────────────────────────┐
│ ⭐ Quick Access │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │Queue│ │ AI │ │Audit│ │
│ └─────┘ └─────┘ └─────┘ │
│ ┌─────┐ ┌─────┐ │
│ │Segs │ │Users│ │
│ └─────┘ └─────┘ │
└─────────────────────────────┘
- Max 6 items
- Default based on role, then learns from usage
- User can pin/unpin items
2. Recently Visited¶
Auto-populated from navigation history:
┌─────────────────────────────┐
│ 🕒 Recently Visited │
│ • Segment: Likely Voters │
│ • Person: John Smith │
│ • Event: Town Hall 12/15 │
│ • Report: Weekly Summary │
└─────────────────────────────┘
- Shows last 5 visited pages with context
- Includes entity names, not just page types
- Stored in localStorage + optional DB sync
3. Role-Based Sections¶
Field Staff View:
┌─────────────────────────────┐
│ 📋 My Tasks │
│ • Work Queue (12 pending) │
│ • My Assignments │
│ • Event Check-ins │
│ │
│ 📞 Outreach │
│ • Communications │
│ • Call Lists │
│ │
│ 🤖 Tools │
│ • AI Assistant │
│ • Map │
└─────────────────────────────┘
Director/Admin View:
┌─────────────────────────────┐
│ 📊 Overview │
│ • Dashboard │
│ • Reports │
│ • Goals Progress │
│ │
│ 👥 Team │
│ • Work Queues (all) │
│ • User Management │
│ • Assignments │
│ │
│ 📁 Data │
│ • Audience │
│ • Segments │
│ • Tags │
│ • i360 Integration │
│ • Import/Export │
│ │
│ 🤖 Tools │
│ • AI Assistant │
│ • Map │
│ │
│ ⚙️ Admin │
│ • Settings │
│ • Audit Log │
└─────────────────────────────┘
4. Search/Filter¶
Quick search across menu items:
- Fuzzy match on menu item names
- Keyboard shortcut: Cmd/Ctrl + K
- Shows matching items as you type
5. Badge Notifications¶
Show counts on menu items:
- Pending work queue items
- Unread communications
- Upcoming events
Data Model¶
User Preferences (localStorage + DB)¶
{
"pinnedItems": ["work-queue", "ai-chat", "segments"],
"recentlyVisited": [
{"path": "/segments/abc123", "title": "Likely Voters", "timestamp": "..."},
{"path": "/persons/xyz789", "title": "John Smith", "timestamp": "..."}
],
"sidebarCollapsed": false,
"menuLayout": "panel" // "panel" | "classic"
}
API Endpoint (Optional)¶
Syncs preferences across devices.
Implementation Phases¶
Phase 1: Enhanced Current Sidebar¶
- Add search filter at top
- Add badges for counts
- Persist collapsed state
- Effort: Small
Phase 2: Quick Access + Recently Visited¶
- Add localStorage tracking for page visits
- Show Quick Access section with pinned items
- Show Recently Visited section
- Effort: Medium
Phase 3: Full Panel Mode¶
- Redesign as slide-out panel (like AWS)
- Grid layout for Quick Access
- Role-adaptive sections
- DB sync for preferences
- Effort: Large
UI Components Needed¶
- PanelMenu - Main container component
- QuickAccessGrid - Pinnable shortcut tiles
- RecentlyVisited - History list with entity context
- MenuSection - Collapsible group with header
- MenuSearch - Filter input with keyboard nav
- MenuBadge - Notification count indicator
CSS Architecture¶
/* Panel container */
.panel-menu {
width: 280px;
height: 100vh;
position: fixed;
left: 0;
top: 64px;
background: var(--color-surface);
border-right: 1px solid var(--color-border);
overflow-y: auto;
transition: width 0.2s ease;
}
.panel-menu.collapsed {
width: 64px;
}
/* Quick access grid */
.quick-access-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px;
padding: 12px;
}
.quick-access-tile {
aspect-ratio: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-radius: 8px;
background: var(--color-surface-alt);
cursor: pointer;
transition: all 0.15s ease;
}
.quick-access-tile:hover {
background: var(--color-primary-light);
}
/* Menu sections */
.menu-section {
border-bottom: 1px solid var(--color-border);
padding-bottom: 8px;
margin-bottom: 8px;
}
.menu-section-header {
font-size: 0.7rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--color-text-secondary);
padding: 12px 16px 8px;
display: flex;
align-items: center;
gap: 8px;
}
/* Badges */
.menu-badge {
background: var(--color-primary);
color: white;
font-size: 0.65rem;
font-weight: 600;
padding: 2px 6px;
border-radius: 10px;
margin-left: auto;
}
JavaScript Architecture¶
// Navigation tracking
class NavigationTracker {
constructor() {
this.maxRecent = 10;
this.storageKey = 'cbapp_nav_history';
}
trackVisit(path, title, entityType) {
const history = this.getHistory();
const entry = {
path,
title,
entityType,
timestamp: new Date().toISOString()
};
// Remove duplicate, add to front
const filtered = history.filter(h => h.path !== path);
filtered.unshift(entry);
// Trim to max
localStorage.setItem(
this.storageKey,
JSON.stringify(filtered.slice(0, this.maxRecent))
);
}
getHistory() {
try {
return JSON.parse(localStorage.getItem(this.storageKey)) || [];
} catch {
return [];
}
}
}
// Quick access management
class QuickAccessManager {
constructor() {
this.storageKey = 'cbapp_quick_access';
this.maxItems = 6;
}
getPinned() {
try {
return JSON.parse(localStorage.getItem(this.storageKey)) || [];
} catch {
return [];
}
}
togglePin(itemId) {
const pinned = this.getPinned();
const index = pinned.indexOf(itemId);
if (index >= 0) {
pinned.splice(index, 1);
} else if (pinned.length < this.maxItems) {
pinned.push(itemId);
}
localStorage.setItem(this.storageKey, JSON.stringify(pinned));
return pinned;
}
}
// Menu search
function initMenuSearch() {
const input = document.getElementById('menuSearch');
const items = document.querySelectorAll('.menu-item');
input.addEventListener('input', (e) => {
const query = e.target.value.toLowerCase();
items.forEach(item => {
const text = item.textContent.toLowerCase();
item.style.display = text.includes(query) ? '' : 'none';
});
// Show/hide sections based on visible items
document.querySelectorAll('.menu-section').forEach(section => {
const hasVisible = section.querySelector('.menu-item:not([style*="display: none"])');
section.style.display = hasVisible ? '' : 'none';
});
});
// Keyboard shortcut
document.addEventListener('keydown', (e) => {
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
e.preventDefault();
input.focus();
}
});
}
Migration Path¶
- Current state: Static sidebar with grouped sections
- Add search: Non-breaking enhancement
- Add badges: Requires API integration
- Add recently visited: localStorage-based
- Add quick access: localStorage-based with pin UI
- Full panel: Major UI change, consider feature flag
Questions to Resolve¶
- Should preferences sync to server or stay local-only?
- Show "Recently Visited" for all users or just admins?
- Include quick access tiles on mobile or simplify?
- Allow users to switch between "panel" and "classic" modes?
Files to Modify¶
src/app/templates/layout.html # Panel menu HTML
src/app/static/css/styles.css # Panel styles
src/app/static/js/panel-menu.js # NEW: Panel logic
src/api/routes/users.py # Preferences endpoint (optional)
src/api/models/user.py # Preferences model (optional)
Timeline Estimate¶
- Phase 1 (Search + Badges): 1-2 sessions
- Phase 2 (Quick Access + Recent): 2-3 sessions
- Phase 3 (Full Panel): 3-5 sessions
Total: ~6-10 development sessions for complete implementation.