# Pages with Aside Sidebar Pattern

Complete guide to building pages with persistent sidebar using AwPageAside for forms, configuration, and detail pages with contextual information.

## When to Use AwPageAside

Use `AwPageAside` for:
- **Edit pages with summary** - Forms with pricing, totals, or status sidebar
- **Configuration pages** - Settings with marketing/info in sidebar
- **Booking/order pages** - Main content with summary and actions in sidebar
- **Detail pages with actions** - View details with related info and quick actions
- **Complex workflows** - Multi-step processes with progress or help in sidebar

**Key characteristics:**
- Fixed sidebar on desktop (right side)
- Responsive layout (sidebar becomes card on mobile)
- Sticky action buttons at bottom of sidebar
- Pass-through support for all AwPage props
- `isDesktop` prop available in slots for responsive content

## Basic Page with Aside

### Minimal Example

```markup
<template>
    <AwPageAside title="Edit Booking">
        <template #default>
            <AwCard title="Booking Details">
                <AwGrid>
                    <AwDate
                        v-model="booking.date"
                        label="Date"
                        :error="booking.errors.date"
                        required
                    />

                    <AwInput
                        v-model="booking.client_name"
                        label="Client Name"
                        :error="booking.errors.client_name"
                        required
                    />

                    <AwSelect
                        v-model="booking.service_id"
                        :options="services"
                        track-by="id"
                        option-text="name"
                        label="Service"
                        :error="booking.errors.service_id"
                        required
                    />
                </AwGrid>
            </AwCard>
        </template>

        <template #aside>
            <h3 class="text-lg font-semibold mb-4">Summary</h3>
            <div class="space-y-4">
                <div class="flex justify-between">
                    <span class="text-secondary">Service</span>
                    <span class="font-semibold">{{ selectedService?.name }}</span>
                </div>
                <div class="flex justify-between">
                    <span class="text-secondary">Price</span>
                    <span class="font-semibold">{{ formatPrice(selectedService?.price) }}</span>
                </div>
                <hr />
                <div class="flex justify-between text-lg">
                    <span class="font-semibold">Total</span>
                    <span class="font-bold text-accent">{{ formatPrice(total) }}</span>
                </div>
            </div>
        </template>

        <template #aside-buttons>
            <AwButton
                @click="save"
                :loading="booking.saving"
                cta
                block
            >
                Save Booking
            </AwButton>
        </template>
    </AwPageAside>
</template>

<script>
import Booking from '~/models/Booking'

export default {
    middleware: 'auth',

    data() {
        return {
            booking: new Booking(
                { id: this.$route.params.id },
                null,
                { shop_uuid: this.$route.params.shop_uuid }
            ),
            services: []
        }
    },

    computed: {
        selectedService() {
            return this.services.find(s => s.id === this.booking.service_id)
        },

        total() {
            return this.selectedService?.price || 0
        }
    },

    async mounted() {
        await this.loadServices()

        if (!this.booking.isNew()) {
            await this.booking.fetch()
        }
    },

    methods: {
        async loadServices() {
            const shopUuid = this.$route.params.shop_uuid
            const response = await this.$axios.get(`/api/shops/${shopUuid}/services`)
            this.services = response.data.data
        },

        formatPrice(price) {
            return new Intl.NumberFormat('en-US', {
                style: 'currency',
                currency: 'USD'
            }).format(price || 0)
        },

        async save() {
            try {
                await this.booking.save()

                if (Object.keys(this.booking.errors).length > 0) {
                    this.$notify({
                        message: 'Please fix validation errors',
                        type: 'error'
                    })
                    return
                }

                this.$notify({
                    message: 'Booking saved successfully',
                    type: 'success'
                })

                this.$router.push(`/${this.$route.params.shop_uuid}/bookings`)
            } catch (error) {
                this.$notify({
                    message: 'Failed to save booking',
                    type: 'error'
                })
            }
        },

        cancel() {
            this.$router.back()
        }
    }
}
</script>
```

**What happens:**
1. ✅ Main content area shows booking form
2. ✅ Aside shows pricing summary
3. ✅ Action buttons fixed at bottom of aside
4. ✅ Responsive: sidebar becomes card below content on mobile
5. ✅ Total updates when service changes

## Common Patterns

### 1. Booking/Order Page with Dynamic Summary

Form with services, client info, and total in sidebar:

```markup
<template>
    <AwPageAside
        title="New Booking"
        :breadcrumb="{ href: `/bookings`, title: 'Bookings' }"
    >
        <template #default>
            <!-- Service Selection -->
            <AwCard title="Services">
                <div class="space-y-4">
                    <div
                        v-for="service in services"
                        :key="service.id"
                        class="border rounded-lg p-4 cursor-pointer hover:border-accent"
                        :class="{ 'border-accent bg-accent-50': isSelected(service) }"
                        @click="toggleService(service)"
                    >
                        <div class="flex justify-between items-start">
                            <div>
                                <h3 class="font-semibold">{{ service.name }}</h3>
                                <p class="text-sm text-secondary">{{ service.description }}</p>
                                <p class="text-sm text-secondary mt-1">{{ service.duration }} min</p>
                            </div>
                            <div class="text-right">
                                <p class="font-semibold text-accent">{{ formatPrice(service.price) }}</p>
                            </div>
                        </div>
                    </div>
                </div>
            </AwCard>

            <!-- Client Information -->
            <AwCard title="Client Information">
                <AwGrid>
                    <AwInput
                        v-model="booking.client_name"
                        label="Name"
                        :error="booking.errors.client_name"
                        required
                    />

                    <AwInput
                        v-model="booking.client_email"
                        label="Email"
                        type="email"
                        :error="booking.errors.client_email"
                        required
                    />

                    <AwTel
                        v-model="booking.client_phone"
                        label="Phone"
                        :error="booking.errors.client_phone"
                    />
                </AwGrid>
            </AwCard>

            <!-- Date & Time -->
            <AwCard title="Date & Time">
                <AwGrid>
                    <AwDate
                        v-model="booking.date"
                        label="Date"
                        :error="booking.errors.date"
                        required
                    />

                    <AwSelect
                        v-model="booking.time_slot"
                        :options="availableSlots"
                        label="Time"
                        :error="booking.errors.time_slot"
                        required
                    />
                </AwGrid>
            </AwCard>

            <!-- Notes -->
            <AwCard title="Additional Notes">
                <AwTextarea
                    v-model="booking.notes"
                    label="Notes"
                    :error="booking.errors.notes"
                    :rows="4"
                    placeholder="Any special requests or notes..."
                />
            </AwCard>
        </template>

        <template #aside>
            <h3 class="text-lg font-semibold mb-4">Booking Summary</h3>

            <!-- Client Info -->
            <div class="mb-6">
                <h4 class="text-sm font-semibold text-secondary mb-2">Client</h4>
                <p class="font-medium">{{ booking.client_name || 'Not specified' }}</p>
                <p class="text-sm text-secondary">{{ booking.client_email || '-' }}</p>
                <p class="text-sm text-secondary">{{ booking.client_phone || '-' }}</p>
            </div>

            <!-- Date & Time -->
            <div class="mb-6" v-if="booking.date">
                <h4 class="text-sm font-semibold text-secondary mb-2">Date & Time</h4>
                <p class="font-medium">{{ formatDate(booking.date) }}</p>
                <p class="text-sm text-secondary">{{ booking.time_slot || '-' }}</p>
            </div>

            <!-- Selected Services -->
            <div class="mb-6">
                <h4 class="text-sm font-semibold text-secondary mb-2">Services</h4>
                <div v-if="selectedServices.length === 0" class="text-sm text-secondary">
                    No services selected
                </div>
                <div v-else class="space-y-3">
                    <div
                        v-for="service in selectedServices"
                        :key="service.id"
                        class="flex justify-between items-start"
                    >
                        <div class="flex-1">
                            <p class="font-medium">{{ service.name }}</p>
                            <p class="text-xs text-secondary">{{ service.duration }} min</p>
                        </div>
                        <div class="text-right">
                            <p class="font-medium">{{ formatPrice(service.price) }}</p>
                            <button
                                @click="removeService(service)"
                                class="text-xs text-error hover:underline"
                            >
                                Remove
                            </button>
                        </div>
                    </div>
                </div>
            </div>

            <!-- Totals -->
            <hr class="my-4" />
            <div class="space-y-2">
                <div class="flex justify-between text-sm">
                    <span class="text-secondary">Subtotal</span>
                    <span>{{ formatPrice(subtotal) }}</span>
                </div>
                <div class="flex justify-between text-sm">
                    <span class="text-secondary">Duration</span>
                    <span>{{ totalDuration }} min</span>
                </div>
                <hr class="my-2" />
                <div class="flex justify-between items-center">
                    <span class="text-lg font-semibold">Total</span>
                    <span class="text-2xl font-bold text-accent">{{ formatPrice(total) }}</span>
                </div>
            </div>
        </template>

        <template #aside-buttons>
            <AwButton
                @click="save"
                :loading="booking.saving"
                :disabled="!canSave"
                cta
                block
            >
                Confirm Booking
            </AwButton>
            <AwButton
                @click="cancel"
                theme="outline"
                block
            >
                Cancel
            </AwButton>
        </template>
    </AwPageAside>
</template>

<script>
import Booking from '~/models/Booking'

export default {
    middleware: 'auth',

    data() {
        return {
            booking: new Booking({}, null, {
                shop_uuid: this.$route.params.shop_uuid
            }),
            services: [],
            selectedServiceIds: [],
            availableSlots: []
        }
    },

    computed: {
        selectedServices() {
            return this.services.filter(s => this.selectedServiceIds.includes(s.id))
        },

        subtotal() {
            return this.selectedServices.reduce((sum, s) => sum + s.price, 0)
        },

        total() {
            return this.subtotal
        },

        totalDuration() {
            return this.selectedServices.reduce((sum, s) => sum + s.duration, 0)
        },

        canSave() {
            return this.selectedServices.length > 0 &&
                   this.booking.client_name &&
                   this.booking.client_email &&
                   this.booking.date &&
                   this.booking.time_slot
        }
    },

    async mounted() {
        await this.loadServices()
        await this.loadAvailableSlots()
    },

    methods: {
        async loadServices() {
            const shopUuid = this.$route.params.shop_uuid
            const response = await this.$axios.get(`/api/shops/${shopUuid}/services`)
            this.services = response.data.data
        },

        async loadAvailableSlots() {
            const shopUuid = this.$route.params.shop_uuid
            const response = await this.$axios.get(`/api/shops/${shopUuid}/time-slots`)
            this.availableSlots = response.data.data
        },

        isSelected(service) {
            return this.selectedServiceIds.includes(service.id)
        },

        toggleService(service) {
            const index = this.selectedServiceIds.indexOf(service.id)
            if (index > -1) {
                this.selectedServiceIds.splice(index, 1)
            } else {
                this.selectedServiceIds.push(service.id)
            }
        },

        removeService(service) {
            const index = this.selectedServiceIds.indexOf(service.id)
            if (index > -1) {
                this.selectedServiceIds.splice(index, 1)
            }
        },

        formatPrice(price) {
            return new Intl.NumberFormat('en-US', {
                style: 'currency',
                currency: 'USD'
            }).format(price || 0)
        },

        formatDate(date) {
            return this.$dayjs(date).format('MMMM D, YYYY')
        },

        async save() {
            this.booking.service_ids = this.selectedServiceIds

            try {
                await this.booking.save()

                if (Object.keys(this.booking.errors).length > 0) {
                    this.$notify({
                        message: 'Please fix validation errors',
                        type: 'error'
                    })
                    return
                }

                this.$notify({
                    message: 'Booking created successfully',
                    type: 'success'
                })

                this.$router.push(`/${this.$route.params.shop_uuid}/bookings`)
            } catch (error) {
                this.$notify({
                    message: 'Failed to create booking',
                    type: 'error'
                })
            }
        },

        cancel() {
            this.$router.back()
        }
    }
}
</script>
```

### 2. Widget Configuration with Marketing Info

Configuration form with promotional content in sidebar:

```markup
<template>
    <AwPageAside
        title="Configure Widget"
        :breadcrumb="{ href: `/widgets`, title: 'Widgets' }"
    >
        <template #default>
            <!-- Widget Preview -->
            <AwCard title="Widget Preview">
                <div class="border rounded-lg p-6 bg-gray-50">
                    <div
                        class="widget-preview"
                        :style="{
                            backgroundColor: widget.background_color,
                            color: widget.text_color,
                            fontSize: `${widget.font_size}px`
                        }"
                    >
                        <h3>{{ widget.title || 'Widget Title' }}</h3>
                        <p>{{ widget.message || 'Widget message will appear here' }}</p>
                    </div>
                </div>
            </AwCard>

            <!-- Appearance Settings -->
            <AwCard title="Appearance">
                <AwGrid>
                    <AwInput
                        v-model="widget.title"
                        label="Title"
                        :error="widget.errors.title"
                        required
                    />

                    <AwTextarea
                        v-model="widget.message"
                        label="Message"
                        :error="widget.errors.message"
                        :rows="3"
                        required
                    />

                    <AwInput
                        v-model="widget.background_color"
                        label="Background Color"
                        type="color"
                        :error="widget.errors.background_color"
                    />

                    <AwInput
                        v-model="widget.text_color"
                        label="Text Color"
                        type="color"
                        :error="widget.errors.text_color"
                    />

                    <AwSlider
                        v-model="widget.font_size"
                        label="Font Size"
                        :min="12"
                        :max="24"
                        :error="widget.errors.font_size"
                    />
                </AwGrid>
            </AwCard>

            <!-- Behavior Settings -->
            <AwCard title="Behavior">
                <AwGrid>
                    <AwSelect
                        v-model="widget.position"
                        :options="['top-left', 'top-right', 'bottom-left', 'bottom-right']"
                        label="Position"
                        :error="widget.errors.position"
                    />

                    <AwNumber
                        v-model="widget.delay"
                        label="Delay (seconds)"
                        :min="0"
                        :max="60"
                        :error="widget.errors.delay"
                    />

                    <AwSwitcher
                        v-model="widget.show_close_button"
                        label="Show Close Button"
                    />

                    <AwSwitcher
                        v-model="widget.auto_hide"
                        label="Auto Hide"
                    />

                    <AwNumber
                        v-if="widget.auto_hide"
                        v-model="widget.auto_hide_delay"
                        label="Auto Hide Delay (seconds)"
                        :min="1"
                        :max="60"
                        :error="widget.errors.auto_hide_delay"
                    />
                </AwGrid>
            </AwCard>

            <!-- Targeting -->
            <AwCard title="Targeting">
                <AwGrid>
                    <AwSelect
                        v-model="widget.pages"
                        :options="pageOptions"
                        label="Show on Pages"
                        multiple
                        :error="widget.errors.pages"
                    />

                    <AwSelect
                        v-model="widget.devices"
                        :options="['desktop', 'tablet', 'mobile']"
                        label="Show on Devices"
                        multiple
                        :error="widget.errors.devices"
                    />
                </AwGrid>
            </AwCard>
        </template>

        <template #aside>
            <!-- Marketing Info -->
            <div class="mb-6">
                <h3 class="text-lg font-semibold mb-4">Why Use Widgets?</h3>
                <div class="space-y-4 text-sm">
                    <div class="flex items-start gap-3">
                        <AwIcon name="awesio/check-circle" class="text-success mt-0.5" />
                        <div>
                            <h4 class="font-semibold mb-1">Increase Engagement</h4>
                            <p class="text-secondary">
                                Capture visitor attention with timely, personalized messages
                            </p>
                        </div>
                    </div>

                    <div class="flex items-start gap-3">
                        <AwIcon name="awesio/check-circle" class="text-success mt-0.5" />
                        <div>
                            <h4 class="font-semibold mb-1">Boost Conversions</h4>
                            <p class="text-secondary">
                                Drive actions with targeted calls-to-action and special offers
                            </p>
                        </div>
                    </div>

                    <div class="flex items-start gap-3">
                        <AwIcon name="awesio/check-circle" class="text-success mt-0.5" />
                        <div>
                            <h4 class="font-semibold mb-1">Easy to Customize</h4>
                            <p class="text-secondary">
                                Match your brand with flexible design options
                            </p>
                        </div>
                    </div>

                    <hr class="my-4" />

                    <div class="bg-accent-50 rounded-lg p-4">
                        <h4 class="font-semibold text-accent mb-2">Pro Tip</h4>
                        <p class="text-secondary text-xs">
                            Widgets with a delay of 3-5 seconds have 40% higher engagement
                            than immediate popups.
                        </p>
                    </div>
                </div>
            </div>

            <!-- Stats (if editing) -->
            <div v-if="!widget.isNew()">
                <h3 class="text-lg font-semibold mb-4">Performance</h3>
                <div class="space-y-3">
                    <div class="flex justify-between items-center">
                        <span class="text-sm text-secondary">Impressions</span>
                        <span class="font-semibold">{{ widget.stats?.impressions || 0 }}</span>
                    </div>
                    <div class="flex justify-between items-center">
                        <span class="text-sm text-secondary">Clicks</span>
                        <span class="font-semibold">{{ widget.stats?.clicks || 0 }}</span>
                    </div>
                    <div class="flex justify-between items-center">
                        <span class="text-sm text-secondary">Conversion Rate</span>
                        <span class="font-semibold text-accent">
                            {{ formatPercentage(widget.stats?.conversion_rate) }}
                        </span>
                    </div>
                </div>
            </div>
        </template>

        <template #aside-buttons>
            <AwButton
                @click="save"
                :loading="widget.saving"
                cta
                block
            >
                {{ widget.isNew() ? 'Create Widget' : 'Update Widget' }}
            </AwButton>
            <AwButton
                v-if="!widget.isNew()"
                @click="testWidget"
                theme="outline"
                block
            >
                Test Widget
            </AwButton>
        </template>
    </AwPageAside>
</template>

<script>
import Widget from '~/models/Widget'

export default {
    middleware: 'auth',

    data() {
        return {
            widget: new Widget(
                { id: this.$route.params.id },
                null,
                { shop_uuid: this.$route.params.shop_uuid }
            ),
            pageOptions: [
                'home',
                'products',
                'checkout',
                'cart',
                'account'
            ]
        }
    },

    async mounted() {
        if (!this.widget.isNew()) {
            await this.widget.fetch()
        } else {
            // Set defaults for new widget
            this.widget.background_color = '#3B82F6'
            this.widget.text_color = '#FFFFFF'
            this.widget.font_size = 16
            this.widget.position = 'bottom-right'
            this.widget.delay = 3
            this.widget.show_close_button = true
            this.widget.devices = ['desktop', 'tablet', 'mobile']
        }
    },

    methods: {
        async save() {
            try {
                await this.widget.save()

                if (Object.keys(this.widget.errors).length > 0) {
                    this.$notify({
                        message: 'Please fix validation errors',
                        type: 'error'
                    })
                    return
                }

                this.$notify({
                    message: `Widget ${this.widget.isNew() ? 'created' : 'updated'} successfully`,
                    type: 'success'
                })

                this.$router.push(`/${this.$route.params.shop_uuid}/widgets`)
            } catch (error) {
                this.$notify({
                    message: 'Failed to save widget',
                    type: 'error'
                })
            }
        },

        testWidget() {
            // Open test preview in new window
            const url = `/${this.$route.params.shop_uuid}/widgets/${this.widget.id}/preview`
            window.open(url, '_blank')
        },

        formatPercentage(value) {
            return `${(value || 0).toFixed(1)}%`
        }
    }
}
</script>
```

### 3. Edit Form with Dynamic Aside Content

Form where aside content changes based on interaction:

```markup
<template>
    <AwPageAside title="Edit Product">
        <template #default>
            <AwCard title="Product Details">
                <AwGrid>
                    <AwInput
                        v-model="product.name"
                        label="Name"
                        :error="product.errors.name"
                        required
                    />

                    <AwInput
                        v-model="product.sku"
                        label="SKU"
                        :error="product.errors.sku"
                    />

                    <AwSelect
                        v-model="product.category_id"
                        :options="categories"
                        track-by="id"
                        option-text="name"
                        label="Category"
                        :error="product.errors.category_id"
                        @input="onCategoryChange"
                    />

                    <AwTextarea
                        v-model="product.description"
                        label="Description"
                        :error="product.errors.description"
                        :rows="4"
                        class="col-span-2"
                    />
                </AwGrid>
            </AwCard>

            <AwCard title="Pricing">
                <AwGrid>
                    <AwMoney
                        v-model="product.price"
                        label="Price"
                        :error="product.errors.price"
                        required
                        @input="onPriceChange"
                    />

                    <AwMoney
                        v-model="product.cost"
                        label="Cost"
                        :error="product.errors.cost"
                        @input="onPriceChange"
                    />
                </AwGrid>
            </AwCard>
        </template>

        <template #aside>
            <!-- Dynamic aside based on editMode -->
            <div v-if="editMode === null">
                <h3 class="text-lg font-semibold mb-4">Product Info</h3>
                <div class="space-y-4">
                    <div>
                        <span class="text-sm text-secondary">Category</span>
                        <p class="font-medium">{{ selectedCategory?.name || '-' }}</p>
                        <AwButton
                            @click="editMode = 'category'"
                            theme="text"
                            size="sm"
                            class="mt-1"
                        >
                            Change Category
                        </AwButton>
                    </div>

                    <hr />

                    <div>
                        <span class="text-sm text-secondary">Pricing</span>
                        <div class="mt-2 space-y-2">
                            <div class="flex justify-between">
                                <span class="text-sm">Price</span>
                                <span class="font-medium">{{ formatPrice(product.price) }}</span>
                            </div>
                            <div class="flex justify-between">
                                <span class="text-sm">Cost</span>
                                <span class="font-medium">{{ formatPrice(product.cost) }}</span>
                            </div>
                            <div class="flex justify-between text-accent">
                                <span class="text-sm font-semibold">Profit</span>
                                <span class="font-semibold">{{ formatPrice(profit) }}</span>
                            </div>
                            <div class="flex justify-between">
                                <span class="text-sm">Margin</span>
                                <span class="font-medium">{{ marginPercentage }}%</span>
                            </div>
                        </div>
                    </div>

                    <hr />

                    <div>
                        <span class="text-sm text-secondary">Status</span>
                        <div class="mt-2">
                            <AwLabel :color="product.is_active ? 'success' : 'mono'">
                                {{ product.is_active ? 'Active' : 'Inactive' }}
                            </AwLabel>
                        </div>
                    </div>
                </div>
            </div>

            <!-- Category Edit Mode -->
            <div v-else-if="editMode === 'category'">
                <h3 class="text-lg font-semibold mb-4">Select Category</h3>
                <div class="space-y-2">
                    <div
                        v-for="category in categories"
                        :key="category.id"
                        class="p-3 border rounded-lg cursor-pointer hover:border-accent"
                        :class="{
                            'border-accent bg-accent-50': product.category_id === category.id
                        }"
                        @click="selectCategory(category)"
                    >
                        <div class="font-medium">{{ category.name }}</div>
                        <div class="text-xs text-secondary">{{ category.description }}</div>
                    </div>
                </div>
            </div>
        </template>

        <template #aside-buttons>
            <AwButton
                v-if="editMode === null"
                @click="save"
                :loading="product.saving"
                cta
                block
            >
                Save Changes
            </AwButton>
            <AwButton
                v-else
                @click="editMode = null"
                theme="outline"
                block
            >
                Done
            </AwButton>
        </template>
    </AwPageAside>
</template>

<script>
import Product from '~/models/Product'

export default {
    middleware: 'auth',

    data() {
        return {
            product: new Product(
                { id: this.$route.params.id },
                null,
                { shop_uuid: this.$route.params.shop_uuid }
            ),
            categories: [],
            editMode: null // null, 'category', etc.
        }
    },

    computed: {
        selectedCategory() {
            return this.categories.find(c => c.id === this.product.category_id)
        },

        profit() {
            return (this.product.price || 0) - (this.product.cost || 0)
        },

        marginPercentage() {
            if (!this.product.price || this.product.price === 0) return 0
            return ((this.profit / this.product.price) * 100).toFixed(1)
        }
    },

    async mounted() {
        await this.loadCategories()
        if (!this.product.isNew()) {
            await this.product.fetch()
        }
    },

    methods: {
        async loadCategories() {
            const shopUuid = this.$route.params.shop_uuid
            const response = await this.$axios.get(`/api/shops/${shopUuid}/categories`)
            this.categories = response.data.data
        },

        selectCategory(category) {
            this.product.category_id = category.id
            this.editMode = null
        },

        onCategoryChange() {
            // Category changed in main form
        },

        onPriceChange() {
            // Prices changed, profit/margin will auto-update via computed
        },

        formatPrice(price) {
            return new Intl.NumberFormat('en-US', {
                style: 'currency',
                currency: 'USD'
            }).format(price || 0)
        },

        async save() {
            try {
                await this.product.save()

                if (Object.keys(this.product.errors).length > 0) {
                    this.$notify({
                        message: 'Please fix validation errors',
                        type: 'error'
                    })
                    return
                }

                this.$notify({
                    message: 'Product updated successfully',
                    type: 'success'
                })

                this.$router.push(`/${this.$route.params.shop_uuid}/products`)
            } catch (error) {
                this.$notify({
                    message: 'Failed to save product',
                    type: 'error'
                })
            }
        }
    }
}
</script>
```

## Responsive Content

### Using isDesktop Prop

All slots receive `isDesktop` prop for responsive rendering:

```markup
<template>
    <AwPageAside title="Responsive Page">
        <template #aside="{ isDesktop }">
            <!-- Desktop: Full details -->
            <div v-if="isDesktop">
                <h3 class="text-lg font-semibold mb-4">Details</h3>
                <div class="space-y-4">
                    <!-- Full details here -->
                </div>
            </div>

            <!-- Mobile: Compact accordion -->
            <AwAccordionFold v-else title="Details">
                <div class="space-y-2">
                    <!-- Compact details here -->
                </div>
            </AwAccordionFold>
        </template>
    </AwPageAside>
</template>
```

### Custom Mobile Aside Wrapper

```markup
<template>
    <AwPageAside title="Custom Mobile">
        <template #aside>
            <h3 class="text-lg font-semibold mb-4">Info</h3>
            <p>Content here</p>
        </template>

        <!-- Custom wrapper for mobile aside -->
        <template #mobile-aside="{ isDesktop }">
            <div v-if="!isDesktop" class="bg-gray-50 rounded-lg p-4">
                <slot name="aside" />
            </div>
        </template>
    </AwPageAside>
</template>
```

### Custom Desktop Breakpoint

```markup
<template>
    <AwPageAside
        title="Custom Breakpoint"
        desktop-from="xl"
    >
        <!-- Switches to desktop layout at xl breakpoint instead of lg -->
    </AwPageAside>
</template>
```

## Best Practices

### 1. Use Aside for Contextual Information

**Good:**
```markup
<!-- Summary, totals, status, quick actions -->
<template #aside>
    <h3 class="text-lg font-semibold mb-4">Order Summary</h3>
    <div>Total: {{ total }}</div>
</template>
```

**Avoid:**
```markup
<!-- Don't put primary form fields in aside -->
<template #aside>
    <AwInput v-model="product.name" label="Name" />
</template>
```

### 2. Sticky Buttons for Primary Actions

```markup
<template #aside-buttons>
    <AwButton @click="save" cta block>Save</AwButton>
    <AwButton @click="cancel" theme="outline" block>Cancel</AwButton>
</template>
```

### 3. Update Aside Reactively

```markup
<script>
export default {
    computed: {
        total() {
            // Reactive calculation
            return this.items.reduce((sum, item) => sum + item.price, 0)
        }
    }
}
</script>

<template>
    <template #aside>
        <div>Total: {{ total }}</div> <!-- Updates automatically -->
    </template>
</template>
```

### 4. Hide Mobile Aside When Not Needed

```markup
<AwPageAside
    title="Desktop Only Sidebar"
    hide-mobile-aside
>
    <!-- Aside only shows on desktop -->
</AwPageAside>
```

### 5. Visual Separator on Desktop

```markup
<AwPageAside
    title="Page Title"
    modifiers="line"
>
    <!-- Adds vertical line between main and aside on desktop -->
</AwPageAside>
```

## Complete Example: Order Edit Page

```markup
<template>
    <AwPageAside
        :title="`Order #${order.order_number || 'New'}`"
        :breadcrumb="{ href: '/orders', title: 'Orders' }"
        modifiers="line"
    >
        <template #default>
            <!-- Order Items -->
            <AwCard title="Order Items">
                <AwTableBuilder
                    :collection="order.items"
                    :fields="itemFields"
                />
                <AwButton
                    @click="addItem"
                    theme="text"
                    icon="awesio/plus"
                    class="mt-4"
                >
                    Add Item
                </AwButton>
            </AwCard>

            <!-- Customer Information -->
            <AwCard title="Customer">
                <AwGrid>
                    <AwInput
                        v-model="order.customer_name"
                        label="Name"
                        :error="order.errors.customer_name"
                        required
                    />
                    <AwInput
                        v-model="order.customer_email"
                        label="Email"
                        :error="order.errors.customer_email"
                        required
                    />
                    <AwTel
                        v-model="order.customer_phone"
                        label="Phone"
                        :error="order.errors.customer_phone"
                    />
                </AwGrid>
            </AwCard>

            <!-- Shipping Address -->
            <AwCard title="Shipping Address">
                <AwAddress
                    v-model="order.shipping_address"
                    :error="order.errors.shipping_address"
                />
            </AwCard>
        </template>

        <template #aside>
            <div class="mb-6">
                <h3 class="text-lg font-semibold mb-4">Order Summary</h3>

                <!-- Items -->
                <div class="space-y-3 mb-4">
                    <div
                        v-for="item in order.items"
                        :key="item.id"
                        class="flex justify-between text-sm"
                    >
                        <div>
                            <div class="font-medium">{{ item.name }}</div>
                            <div class="text-secondary">Qty: {{ item.quantity }}</div>
                        </div>
                        <div class="text-right">
                            {{ formatPrice(item.price * item.quantity) }}
                        </div>
                    </div>
                </div>

                <!-- Totals -->
                <hr class="my-4" />
                <div class="space-y-2">
                    <div class="flex justify-between text-sm">
                        <span class="text-secondary">Subtotal</span>
                        <span>{{ formatPrice(subtotal) }}</span>
                    </div>
                    <div class="flex justify-between text-sm">
                        <span class="text-secondary">Tax</span>
                        <span>{{ formatPrice(tax) }}</span>
                    </div>
                    <div class="flex justify-between text-sm">
                        <span class="text-secondary">Shipping</span>
                        <span>{{ formatPrice(shipping) }}</span>
                    </div>
                    <hr class="my-2" />
                    <div class="flex justify-between">
                        <span class="font-semibold">Total</span>
                        <span class="text-xl font-bold text-accent">
                            {{ formatPrice(total) }}
                        </span>
                    </div>
                </div>
            </div>

            <!-- Status -->
            <div>
                <h3 class="text-lg font-semibold mb-4">Status</h3>
                <AwSelect
                    v-model="order.status"
                    :options="['pending', 'processing', 'shipped', 'delivered', 'cancelled']"
                    label="Order Status"
                    :error="order.errors.status"
                />
            </div>
        </template>

        <template #aside-buttons>
            <AwButton
                @click="save"
                :loading="order.saving"
                cta
                block
            >
                {{ order.isNew() ? 'Create Order' : 'Update Order' }}
            </AwButton>
            <AwButton
                v-if="!order.isNew()"
                @click="printInvoice"
                theme="outline"
                block
            >
                Print Invoice
            </AwButton>
        </template>
    </AwPageAside>
</template>

<script>
import Order from '~/models/Order'

export default {
    middleware: 'auth',

    data() {
        return {
            order: new Order(
                { id: this.$route.params.id },
                null,
                { shop_uuid: this.$route.params.shop_uuid }
            ),
            itemFields: [
                { key: 'name', label: 'Product' },
                { key: 'quantity', label: 'Qty' },
                { key: 'price', label: 'Price', format: this.formatPrice }
            ]
        }
    },

    computed: {
        subtotal() {
            return this.order.items?.reduce((sum, item) =>
                sum + (item.price * item.quantity), 0
            ) || 0
        },

        tax() {
            return this.subtotal * 0.1 // 10% tax
        },

        shipping() {
            return 10 // Fixed shipping
        },

        total() {
            return this.subtotal + this.tax + this.shipping
        }
    },

    async mounted() {
        if (!this.order.isNew()) {
            await this.order.fetch()
        }
    },

    methods: {
        formatPrice(price) {
            return new Intl.NumberFormat('en-US', {
                style: 'currency',
                currency: 'USD'
            }).format(price || 0)
        },

        addItem() {
            // Open modal to add item
        },

        async save() {
            try {
                await this.order.save()

                if (Object.keys(this.order.errors).length > 0) {
                    this.$notify({
                        message: 'Please fix validation errors',
                        type: 'error'
                    })
                    return
                }

                this.$notify({
                    message: `Order ${this.order.isNew() ? 'created' : 'updated'} successfully`,
                    type: 'success'
                })

                this.$router.push(`/${this.$route.params.shop_uuid}/orders`)
            } catch (error) {
                this.$notify({
                    message: 'Failed to save order',
                    type: 'error'
                })
            }
        },

        printInvoice() {
            window.print()
        }
    }
}
</script>
```

## See Also

- [Detail Pages](./detail-pages.md) - Single-focus edit pages with AwPageSingle
- [List Pages](./list-pages.md) - Table-based list pages
- [AwPageAside](../../components/pages/aw-page-aside.md) - Component reference
- [AwPage](../../components/pages/aw-page.md) - Base page component
- [Forms Guide](../forms-guide.md) - Form patterns and validation
