Technical Design: Navigation Redesign
Decision and implementation design for Homey's unified navigation drawer architecture.
1. Overview
This document describes the redesign of Homey’s navigation architecture from a bottom navigation + scattered top bar icons approach to a unified Navigation Drawer pattern.
1.1 Problem Statement
The current navigation has several issues:
-
Icon Sprawl: Feature entry points are crammed into LocationScreen’s top bar (Checklist, Calendar, Shopping Cart, Settings), creating visual clutter and not scaling with new features.
-
FAB Overlap: Bottom navigation causes FAB (Floating Action Button) to be hidden or require manual padding on multiple screens (Recipes, Blueprints, Missions, Items).
-
Inconsistent Patterns: Some features are accessed via top bar icons, others via bottom nav, creating cognitive load for users.
-
Scalability: As features grow (Planner, Missions, Notifications), the current approach cannot accommodate them elegantly.
1.2 Goals
-
Unified Navigation: Single, consistent navigation pattern across the app
-
Scalable: Support unlimited feature additions without UI redesign
-
FAB-Friendly: No overlap issues with floating action buttons
-
Material 3 Compliant: Use standard Navigation Drawer component
-
Discoverable: Users can easily find all features
2. Options Considered
2.1 Option A: Drawer-Only
┌─────────────────────────────────────┐
│ [☰] Screen Title [...] │
├─────────────────────────────────────┤
│ │
│ (Content area) │
│ │
│ [FAB] │
└─────────────────────────────────────┘
Drawer (swipe or tap ☰):
┌──────────────────────┐
│ Homey │
│ ─────────────────── │
│ 🏠 Home │
│ ─────────────────── │
│ 📦 Add Items │
│ ─────────────────── │
│ 🍳 Recipes │
│ 📅 Menu Planner │
│ 🛒 Shopping List │
│ ─────────────────── │
│ 📋 Blueprints │
│ 🚀 Active Missions │
│ ─────────────────── │
│ ⚙️ Settings │
└──────────────────────┘
Evaluation:
| Pros | Cons |
|---|---|
Unlimited menu items |
Navigation hidden (1 extra tap) |
FAB never overlaps |
Less discoverable for new users |
Clean main screen |
|
Groups features logically |
|
Material 3 standard component |
|
Scales infinitely |
2.2 Option B: Bottom Nav + Drawer (Gmail Style)
┌─────────────────────────────────────┐
│ [☰] Screen Title │
├─────────────────────────────────────┤
│ (Content area) │
│ [FAB] │
├─────────────────────────────────────┤
│ 🏠 📅 📋 ⚙️ │
│ Home Planner Missions Settings │
└─────────────────────────────────────┘
Evaluation:
| Pros | Cons |
|---|---|
Core features always visible |
Complexity of what goes where |
Familiar Gmail pattern |
FAB still needs padding |
Bottom nav takes screen space |
|
Limited to 3-5 bottom items |
2.3 Option C: Hub Dashboard
┌─────────────────────────────────────┐
│ Homey [⚙️] │
├─────────────────────────────────────┤
│ ┌─────────┐ ┌─────────┐ │
│ │ Digital │ │ Add │ │
│ │ Twin │ │ Items │ │
│ └─────────┘ └─────────┘ │
│ ┌─────────┐ ┌─────────┐ │
│ │ Meal │ │ Mission │ │
│ │ Planner │ │ Control │ │
│ └─────────┘ └─────────┘ │
└─────────────────────────────────────┘
Evaluation:
| Pros | Cons |
|---|---|
Visual overview |
Extra tap to reach features |
Can show status badges |
Less efficient for power users |
Very clean |
Requires good iconography |
3. Decision: Drawer-Only (Option A)
3.1 Rationale
Primary Reasons:
-
Scalability: Homey has 5+ feature areas and growing. Drawer accommodates unlimited items with logical grouping via dividers.
-
FAB Freedom: With no bottom navigation, FAB floats naturally at bottom-right without any overlap or padding hacks.
-
Consistency: Every screen has the same navigation pattern - hamburger menu in top bar opens drawer.
-
Material 3 Alignment:
ModalNavigationDraweris a first-class Material 3 component with built-in accessibility and animations. -
Future-Proof: When Contextual Notifications feature is added, drawer can easily accommodate a "Notifications" item with badge.
Addressing the "Hidden Navigation" Con:
-
The hamburger icon (☰) is universally recognized
-
Users can also swipe from left edge to open drawer
-
Selected item in drawer shows current location
-
Drawer header can show user/household info for personalization
3.2 Feature-to-Drawer Mapping
| Group | Drawer Item | Destination |
|---|---|---|
Home |
🏠 Home |
LocationScreen (Digital Twin) |
Ingestion |
📦 Add Items |
IngestHubScreen |
Planning |
🍳 Recipes |
RecipeListScreen |
📅 Menu Planner |
MenuPlannerScreen |
|
🛒 Shopping List |
ShoppingListScreen |
|
Execution |
📋 Blueprints |
BlueprintListScreen |
🚀 Active Missions |
(Future: ActiveMissionsListScreen) |
|
System |
⚙️ Settings |
SettingsScreen |
4. Implementation Design
4.1 Architecture
┌─────────────────────┐
│ MainActivity │
│ (NavHost + Drawer) │
└─────────┬───────────┘
│
┌───────────────┼───────────────┐
│ │ │
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ Location │ │ Planner │ │ Mission │
│ Screen │ │ Screens │ │ Screens │
└───────────┘ └───────────┘ └───────────┘
The Navigation Drawer is managed at the MainActivity level, wrapping the entire NavHost. This ensures:
-
Drawer is accessible from every screen
-
Drawer state persists across navigation
-
Single source of truth for navigation items
4.2 Component Structure
// Main scaffold with drawer
@Composable
fun HomeyApp() {
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
val navController = rememberNavController()
ModalNavigationDrawer(
drawerState = drawerState,
drawerContent = {
HomeyDrawerContent(
currentRoute = currentRoute,
onNavigate = { route ->
navController.navigate(route)
scope.launch { drawerState.close() }
}
)
}
) {
Scaffold(
topBar = {
HomeyTopBar(
title = currentScreenTitle,
onMenuClick = { scope.launch { drawerState.open() } }
)
}
) { padding ->
NavHost(navController, startDestination = Screen.Locations.route) {
// ... routes
}
}
}
}
4.3 Drawer Content Design
@Composable
fun HomeyDrawerContent(
currentRoute: String?,
onNavigate: (String) -> Unit
) {
ModalDrawerSheet {
// Header
DrawerHeader()
HorizontalDivider()
// Home
NavigationDrawerItem(
label = { Text("Home") },
icon = { Icon(Icons.Default.Home, null) },
selected = currentRoute == Screen.Locations.route,
onClick = { onNavigate(Screen.Locations.route) }
)
HorizontalDivider()
// Ingestion
NavigationDrawerItem(
label = { Text("Add Items") },
icon = { Icon(Icons.Default.Add, null) },
selected = currentRoute == Screen.IngestHub.route,
onClick = { onNavigate(Screen.IngestHub.route) }
)
HorizontalDivider()
// Planning section
Text("Planning", modifier = Modifier.padding(16.dp))
NavigationDrawerItem(...) // Recipes
NavigationDrawerItem(...) // Menu Planner
NavigationDrawerItem(...) // Shopping List
HorizontalDivider()
// Execution section
Text("Missions", modifier = Modifier.padding(16.dp))
NavigationDrawerItem(...) // Blueprints
NavigationDrawerItem(...) // Active Missions
Spacer(modifier = Modifier.weight(1f))
HorizontalDivider()
// Settings at bottom
NavigationDrawerItem(...) // Settings
}
}
4.4 Screen-Level Changes
Each screen will:
-
Remove its own TopAppBar (unless it needs custom actions)
-
Receive
onOpenDrawer: () → Unitcallback if needed -
Keep its FAB without bottom padding concerns
For nested screens (e.g., BlueprintDetail, RecipeEdit):
-
Use standard back navigation (arrow in top bar)
-
Drawer is still accessible via swipe
-
These screens may have their own TopAppBar with back arrow
4.5 File Structure
app/src/main/kotlin/dev/sysout/homey/app/
├── MainActivity.kt # Updated: Add drawer scaffold
├── navigation/
│ ├── Screen.kt # Unchanged
│ ├── NavGraph.kt # Updated: Remove redundant scaffolds
│ └── HomeyDrawer.kt # NEW: Drawer content component
└── ui/
└── components/
└── HomeyTopBar.kt # NEW: Shared top bar with menu icon
5. Migration Plan
Phase 1: Core Drawer Infrastructure
-
Create
HomeyDrawer.ktwith drawer content -
Create
HomeyTopBar.ktshared component -
Update
MainActivity.ktwith ModalNavigationDrawer -
Update
NavGraph.ktto work within drawer scaffold
6. Visual Reference
6.1 Drawer Closed State
┌─────────────────────────────────────┐
│ [☰] Locations │
├─────────────────────────────────────┤
│ │
│ Kitchen [>] │
│ └── Fridge │
│ └── Pantry │
│ │
│ Bedroom [>] │
│ │
│ Storage [>] │
│ │
│ │
│ [+] │ ← FAB (no overlap!)
└─────────────────────────────────────┘
6.2 Drawer Open State
┌─────────────────────┬───────────────┐
│ │ │
│ ┌─────────────┐ │ Locations │
│ │ Homey │ │ │
│ │ ───────── │ │ Kitchen │
│ └─────────────┘ │ └── Frid... │
│ │ │
│ 🏠 Home ● │ │ ← ● = selected
│ ─────────────── │ │
│ 📦 Add Items │ │
│ ─────────────── │ │
│ Planning │ │
│ 🍳 Recipes │ │
│ 📅 Menu Planner │ │
│ 🛒 Shopping List │ │
│ ─────────────── │ │
│ Missions │ │
│ 📋 Blueprints │ │
│ 🚀 Active │ │
│ ─────────────── │ │
│ │ │
│ ⚙️ Settings │ │
│ │ │
└─────────────────────┴───────────────┘
7. Success Criteria
-
No FAB Overlap: FAB visible on all screens without manual padding
-
All Features Accessible: Every feature reachable from drawer
-
Consistent UX: Same navigation pattern on every screen
-
Swipe Works: Left-edge swipe opens drawer from any screen
-
Back Navigation: Hardware back closes drawer if open, otherwise navigates back
-
Selected State: Current screen highlighted in drawer
8. Future Enhancements
-
Badges: Show notification counts on drawer items (e.g., "3 items expiring")
-
User Header: Show household name/avatar in drawer header
-
Quick Actions: Add frequently used actions at top of drawer
-
Adaptive Layout: On tablets, use permanent drawer or rail navigation
Document Version: 1.0 Created: 2026-01-25 Status: Approved for Implementation