Skip to content
sysout.dev

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:

  1. 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.

  2. FAB Overlap: Bottom navigation causes FAB (Floating Action Button) to be hidden or require manual padding on multiple screens (Recipes, Blueprints, Missions, Items).

  3. Inconsistent Patterns: Some features are accessed via top bar icons, others via bottom nav, creating cognitive load for users.

  4. 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:

  1. Scalability: Homey has 5+ feature areas and growing. Drawer accommodates unlimited items with logical grouping via dividers.

  2. FAB Freedom: With no bottom navigation, FAB floats naturally at bottom-right without any overlap or padding hacks.

  3. Consistency: Every screen has the same navigation pattern - hamburger menu in top bar opens drawer.

  4. Material 3 Alignment: ModalNavigationDrawer is a first-class Material 3 component with built-in accessibility and animations.

  5. 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:

  1. Remove its own TopAppBar (unless it needs custom actions)

  2. Receive onOpenDrawer: () → Unit callback if needed

  3. 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

  1. Create HomeyDrawer.kt with drawer content

  2. Create HomeyTopBar.kt shared component

  3. Update MainActivity.kt with ModalNavigationDrawer

  4. Update NavGraph.kt to work within drawer scaffold

Phase 2: Screen Updates

  1. Update LocationScreen - remove top bar icons

  2. Update RecipeListScreen - use shared scaffold

  3. Update BlueprintListScreen - use shared scaffold

  4. Update other screens as needed

Phase 3: Polish

  1. Add drawer header with app branding

  2. Add section labels/dividers

  3. Ensure proper selected state highlighting

  4. Test swipe-to-open gesture

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

  1. No FAB Overlap: FAB visible on all screens without manual padding

  2. All Features Accessible: Every feature reachable from drawer

  3. Consistent UX: Same navigation pattern on every screen

  4. Swipe Works: Left-edge swipe opens drawer from any screen

  5. Back Navigation: Hardware back closes drawer if open, otherwise navigates back

  6. Selected State: Current screen highlighted in drawer

8. Future Enhancements

  1. Badges: Show notification counts on drawer items (e.g., "3 items expiring")

  2. User Header: Show household name/avatar in drawer header

  3. Quick Actions: Add frequently used actions at top of drawer

  4. Adaptive Layout: On tablets, use permanent drawer or rail navigation


Document Version: 1.0 Created: 2026-01-25 Status: Approved for Implementation