---
metaTitle: Mobile Subnavigation Pattern | AwesCode UI
meta:
  - name: description
    content: Guide to implementing mobile-only subnavigation hubs with AwSubnav component in AwesCode UI.
title: Mobile Subnavigation Pattern
---

# Mobile Subnavigation Pattern

**Pattern Type:** Navigation | **Use Case:** Sections with multiple child pages

This guide explains how to create sections with submenu items that provide a mobile navigation hub while redirecting desktop users directly to content pages.

## When to Use This Pattern

Use this pattern when:
- ✅ You have a menu section with **multiple child pages** (3+ pages)
- ✅ Mobile users need a **navigation hub** to discover all pages
- ✅ Desktop users should skip the hub and **go directly to content**
- ✅ The section has a natural **"Overview" or first page** for desktop users

**Examples:** Filter components, Settings sections, Documentation categories, Product features

## Overview

When you have a menu item with children (submenu), you can create a mobile-only subnavigation hub that:

- **On Mobile**: Shows a dedicated navigation page with `AwSubnav` listing all child pages
- **On Desktop**: Automatically redirects users to the first child page (typically "Overview")

This pattern improves mobile UX by providing a clear navigation hub, while desktop users go directly to content.

## Complete Example: Filters Section

Let's walk through creating a "Filters" section with multiple filter component pages.

### Step 1: Configure Menu Item

In your menu plugin (e.g., `plugins/menu.js`), add a menu item with:

1. A unique `key` identifier
2. A dynamic `href` function that returns different routes based on screen size
3. `children` array with all submenu items

```javascript
// plugins/menu.js
export default function({ store, app }) {
    const menuItems = [
        {
            text: 'Filters',
            icon: 'duotone/analytics',
            key: 'filters', // Unique identifier for finding this menu item
            href: (state) => 
                state.awesIo.screen.lg 
                    ? '/filters/overview'  // Desktop: go to first child
                    : '/filters',          // Mobile: go to hub
            children: [
                { text: 'Overview', href: '/filters/overview' },
                { text: 'AwFilterChosen', href: '/filters/aw-filter-chosen' },
                { text: 'AwFilterSelect', href: '/filters/aw-filter-select' },
                { text: 'AwFilterDateRange', href: '/filters/aw-filter-date-range' },
                { text: 'AwFilterMonth', href: '/filters/aw-filter-month' }
            ]
        }
    ]

    store.commit('awesIo/SET_MENU_ITEMS', { main: menuItems })
}
```

**Key Points:**
- `key: 'filters'` - Used to find this menu item in the store
- `href` function - Evaluates screen size and returns appropriate route
- `children` - All submenu items that will appear in the subnav

### Step 2: Create Index Page (Navigation Hub)

Create an index page at the root route (e.g., `pages/filters/index.vue`) that:

1. Finds the menu item by `key` from the Vuex store
2. Renders `AwSubnav` with the menu item's children
3. Redirects desktop users to the first child route

```markup
<template>
    <AwPage :title="headline">
        <AwSubnav
            v-if="items.length"
            :title="subnavTitle"
            :children="items"
        />
    </AwPage>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
    name: 'FiltersIndex',

    computed: {
        ...mapGetters('awesIo', ['mainMenu']),

        filtersMenu() {
            return (
                this.mainMenu.find(
                    (item) => item.key === 'filters' || item.href === '/filters'
                ) || {}
            )
        },

        items() {
            return Array.isArray(this.filtersMenu.children)
                ? this.filtersMenu.children
                : []
        },

        firstChildHref() {
            const first = this.items[0]
            return first && first.href ? first.href : null
        },

        subnavTitle() {
            return this.filtersMenu.text || 'Filters'
        },

        headline() {
            return this._getTitle(this.subnavTitle)
        }
    },

    mounted() {
        this.redirectDesktop()
    },

    watch: {
        '$screen.lg'(isDesktop) {
            if (isDesktop) this.redirectDesktop()
        }
    },

    methods: {
        redirectDesktop() {
            if (!process.client) return
            if (!this.$screen?.lg) return
            if (this.firstChildHref) {
                this.$router.replace(this.firstChildHref)
            }
        }
    }
}
</script>
```

**How It Works:**
- `filtersMenu` - Finds the menu item by `key` or fallback to `href`
- `items` - Extracts children array from menu item
- `firstChildHref` - Gets the first child's href for desktop redirect
- `redirectDesktop()` - Redirects desktop users on mount and when screen size changes
- `$screen.lg` watcher - Handles screen size changes dynamically

### Step 3: Add Breadcrumbs to Child Pages

Each child page should have a breadcrumb that only shows on mobile, linking back to the hub:

```markup
<template>
    <AwPage
        :title="headline"
        :breadcrumb="$screen.lg ? undefined : { href: '/filters', title: 'Filters' }"
    >
        <AwHeadline>AwFilterChosen</AwHeadline>
        <!-- Page content -->
    </AwPage>
</template>

<script>
export default {
    name: 'AwFilterChosenPage',

    data() {
        return {
            title: 'AwFilterChosen',
            headline: this._getTitle('AwFilterChosen')
        }
    }
}
</script>
```

**Key Points:**
- `$screen.lg ? undefined : { ... }` - Breadcrumb only shows on mobile
- Links back to `/filters` (the hub route)
- Desktop users don't see breadcrumbs since they're already on the content page

## How It Works

### User Flow

**Mobile User:**
1. Clicks "Filters" in menu → Goes to `/filters`
2. Sees `AwSubnav` with list of all filter pages
3. Clicks a page → Navigates to child page with breadcrumb back to hub

**Desktop User:**
1. Clicks "Filters" in menu → Automatically redirected to `/filters/overview`
2. Sees content directly, no hub page
3. Can navigate between child pages via sidebar menu

### Technical Details

- **Menu Item `href` Function**: Evaluated at navigation time, checks `state.awesIo.screen.lg`
- **Index Page Redirect**: Uses `$router.replace()` to avoid adding to history
- **Screen Size Watcher**: Handles dynamic screen size changes (e.g., window resize)
- **Breadcrumb Conditional**: Uses `$screen.lg` to show/hide based on viewport

## Benefits

✅ **Better Mobile UX** - Dedicated navigation hub makes it easy to discover all pages  
✅ **Desktop Efficiency** - Desktop users go directly to content  
✅ **Single Source of Truth** - Menu configuration drives everything  
✅ **Automatic Updates** - Adding/removing menu items automatically updates navigation  
✅ **Responsive** - Handles screen size changes dynamically  

## Common Patterns

### Finding Menu Item

You can find menu items by:
- `key` (recommended) - Most reliable
- `href` - Fallback option
- `text` - Less reliable if text changes

```javascript
// Recommended
const menuItem = this.mainMenu.find(item => item.key === 'filters')

// Fallback
const menuItem = this.mainMenu.find(
    item => item.key === 'filters' || item.href === '/filters'
)
```

### Handling First Child

The first child is typically the "Overview" page, but you can customize:

```javascript
firstChildHref() {
    // Default: first child
    const first = this.items[0]
    return first?.href || null
    
    // Or find specific child
    const overview = this.items.find(item => item.href.includes('overview'))
    return overview?.href || this.items[0]?.href || null
}
```

### Custom Redirect Logic

You can customize the redirect behavior:

```javascript
redirectDesktop() {
    if (!process.client) return
    if (!this.$screen?.lg) return
    
    // Always redirect to first child
    if (this.firstChildHref) {
        this.$router.replace(this.firstChildHref)
        return
    }
    
    // Or handle missing children
    console.warn('No children found for subnav')
}
```

## Quick Reference for AI Implementation

When asked to "create a section with submenu items" or "add a filters section", follow these steps:

### Step 1: Add Menu Item with Dynamic href
```javascript
// plugins/menu.js
{
    text: 'Section Name',
    icon: 'icon-name',
    key: 'unique-key',
    href: (state) => state.awesIo.screen.lg ? '/section/overview' : '/section',
    children: [
        { text: 'Overview', href: '/section/overview' },
        { text: 'Page 1', href: '/section/page-1' },
        // ... more children
    ]
}
```

### Step 2: Create Index Page (pages/section/index.vue)
```markup
<template>
    <AwPage :title="headline">
        <AwSubnav v-if="items.length" :title="subnavTitle" :children="items" />
    </AwPage>
</template>

<script>
import { mapGetters } from 'vuex'
export default {
    computed: {
        ...mapGetters('awesIo', ['mainMenu']),
        menuItem() {
            return this.mainMenu.find(item => item.key === 'unique-key') || {}
        },
        items() { return this.menuItem.children || [] },
        firstChildHref() { return this.items[0]?.href || null },
        subnavTitle() { return this.menuItem.text || 'Section' },
        headline() { return this._getTitle(this.subnavTitle) }
    },
    mounted() { this.redirectDesktop() },
    watch: { '$screen.lg'(isDesktop) { if (isDesktop) this.redirectDesktop() } },
    methods: {
        redirectDesktop() {
            if (process.client && this.$screen?.lg && this.firstChildHref) {
                this.$router.replace(this.firstChildHref)
            }
        }
    }
}
</script>
```

### Step 3: Add Breadcrumb to Child Pages
```markup
<AwPage
    :title="headline"
    :breadcrumb="$screen.lg ? undefined : { href: '/section', title: 'Section' }"
>
```

### Checklist
- [ ] Menu item has `key` property
- [ ] Menu item has dynamic `href` function
- [ ] Menu item has `children` array
- [ ] Index page finds menu by `key`
- [ ] Index page redirects desktop users
- [ ] Index page watches `$screen.lg` for resize
- [ ] Child pages have mobile-only breadcrumbs

## Related Documentation

- [Menu Configuration Reference](../reference/menu.md) - Complete menu setup guide
- [AwSubnav Component](../components/organisms/aw-subnav.md) - Component API reference
- [AwPage Component](../components/pages/aw-page.md) - Page component with breadcrumb support
- [Getting Started - Menu Setup](../getting-started.md#menu-items) - Basic menu configuration
- [Page Patterns](./page-patterns/) - Other page layout patterns

