feat(mobile-navigation-improvements): Complete US-214 - Actualizare Documentație MOBILE_PATTERNS.md
Implemented by Ralph autonomous loop. Iteration: 14 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# ROA2WEB Mobile Patterns Library
|
||||
|
||||
**Version:** 1.0.0
|
||||
**Version:** 2.0.0
|
||||
**Last Updated:** 2026-01-12
|
||||
**Status:** ✅ Complete
|
||||
|
||||
@@ -10,14 +10,17 @@
|
||||
|
||||
1. [Quick Start](#quick-start)
|
||||
2. [Mobile Layout Overview](#mobile-layout-overview)
|
||||
3. [MobileTopBar](#mobiletopbar)
|
||||
4. [MobileBottomNav](#mobilebottomnav)
|
||||
5. [MobileSelectionFooter](#mobileselectionfooter)
|
||||
6. [BottomSheet](#bottomsheet)
|
||||
7. [SwipeableCards](#swipeablecards)
|
||||
8. [Design Tokens for Mobile](#design-tokens-for-mobile)
|
||||
9. [Best Practices](#best-practices)
|
||||
10. [Troubleshooting](#troubleshooting)
|
||||
3. [Navigation Architecture](#navigation-architecture)
|
||||
4. [MobileTopBar](#mobiletopbar)
|
||||
5. [MobileBottomNav](#mobilebottomnav)
|
||||
6. [MobileDrawerMenu](#mobiledrawermenu) *(NEW)*
|
||||
7. [MobileActionBar](#mobileactionbar) *(NEW)*
|
||||
8. [MobileSelectionFooter](#mobileselectionfooter)
|
||||
9. [BottomSheet](#bottomsheet)
|
||||
10. [SwipeableCards](#swipeablecards)
|
||||
11. [Design Tokens for Mobile](#design-tokens-for-mobile)
|
||||
12. [Best Practices](#best-practices)
|
||||
13. [Troubleshooting](#troubleshooting)
|
||||
|
||||
---
|
||||
|
||||
@@ -35,32 +38,43 @@ Get a mobile view running in **5 minutes**:
|
||||
title="My View"
|
||||
:showMenu="true"
|
||||
:actions="topBarActions"
|
||||
@menu-click="toggleSidebar"
|
||||
@menu-click="showDrawer = true"
|
||||
@action-click="handleAction"
|
||||
/>
|
||||
|
||||
<!-- 2. Main Content (with padding for fixed bars) -->
|
||||
<!-- 2. Drawer Menu (hamburger navigation) -->
|
||||
<MobileDrawerMenu
|
||||
v-model="showDrawer"
|
||||
:user="currentUser"
|
||||
@logout="handleLogout"
|
||||
/>
|
||||
|
||||
<!-- 3. Main Content (with padding for fixed bars) -->
|
||||
<main class="mobile-content">
|
||||
<!-- Your content here -->
|
||||
</main>
|
||||
|
||||
<!-- 3. Bottom Navigation -->
|
||||
<MobileBottomNav :items="navItems" />
|
||||
<!-- 4. Bottom Navigation -->
|
||||
<MobileBottomNav />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import MobileTopBar from '@shared/components/mobile/MobileTopBar.vue'
|
||||
import MobileBottomNav from '@shared/components/mobile/MobileBottomNav.vue'
|
||||
import MobileDrawerMenu from '@shared/components/mobile/MobileDrawerMenu.vue'
|
||||
|
||||
const showDrawer = ref(false)
|
||||
const currentUser = { username: 'John Doe' }
|
||||
|
||||
const topBarActions = [
|
||||
{ icon: 'pi pi-filter', label: 'Filter', tooltip: 'Filtrează' }
|
||||
]
|
||||
|
||||
const navItems = [
|
||||
{ to: '/data-entry', icon: 'pi pi-receipt', label: 'Bonuri' },
|
||||
{ to: '/reports', icon: 'pi pi-chart-bar', label: 'Rapoarte' }
|
||||
]
|
||||
const handleLogout = () => {
|
||||
// Handle logout
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -79,6 +93,8 @@ All mobile components are located in `src/shared/components/mobile/`:
|
||||
```javascript
|
||||
import MobileTopBar from '@shared/components/mobile/MobileTopBar.vue'
|
||||
import MobileBottomNav from '@shared/components/mobile/MobileBottomNav.vue'
|
||||
import MobileDrawerMenu from '@shared/components/mobile/MobileDrawerMenu.vue'
|
||||
import MobileActionBar from '@shared/components/mobile/MobileActionBar.vue'
|
||||
import MobileSelectionFooter from '@shared/components/mobile/MobileSelectionFooter.vue'
|
||||
import BottomSheet from '@shared/components/mobile/BottomSheet.vue'
|
||||
import SwipeableCards from '@shared/components/mobile/SwipeableCards.vue'
|
||||
@@ -107,11 +123,32 @@ import SwipeableCards from '@shared/components/mobile/SwipeableCards.vue'
|
||||
│ │
|
||||
├─────────────────────────────────────────┤
|
||||
│ MobileBottomNav (56px) │
|
||||
│ 🏠 📋 📊 ⚙️ │
|
||||
│ Home Upload Reports Settings │
|
||||
│ 📋 ☁️ 📊 ⚙️ │
|
||||
│ Bonuri Upload Rapoarte Setări │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### ASCII Diagram: Drawer Menu Open
|
||||
|
||||
```
|
||||
┌──────────────────┬──────────────────────┐
|
||||
│ MobileDrawer │ ░░░░░░░░░░░░░░░░░░░░ │
|
||||
│ Menu (280px) │ ░░░░░░░░░░░░░░░░░░░░ │
|
||||
├──────────────────┤ ░░░ OVERLAY ░░░░░░░░ │
|
||||
│ 🏢 ROA2WEB │ ░░ (tap to close) ░░ │
|
||||
├──────────────────┤ ░░░░░░░░░░░░░░░░░░░░ │
|
||||
│ 🏠 Dashboard │ ░░░░░░░░░░░░░░░░░░░░ │
|
||||
│ 📋 Bonuri │ ░░░░░░░░░░░░░░░░░░░░ │
|
||||
│ 📄 Facturi │ ░░░░░░░░░░░░░░░░░░░░ │
|
||||
│ 🔢 Balanță │ ░░░░░░░░░░░░░░░░░░░░ │
|
||||
│ 💰 Trezorerie │ ░░░░░░░░░░░░░░░░░░░░ │
|
||||
│ ⚙️ Setări │ ░░░░░░░░░░░░░░░░░░░░ │
|
||||
├──────────────────┤ ░░░░░░░░░░░░░░░░░░░░ │
|
||||
│ 👤 Username │ ░░░░░░░░░░░░░░░░░░░░ │
|
||||
│ 🚪 Deconectare │ ░░░░░░░░░░░░░░░░░░░░ │
|
||||
└──────────────────┴──────────────────────┘
|
||||
```
|
||||
|
||||
### ASCII Diagram: Selection Mode Layout
|
||||
|
||||
```
|
||||
@@ -135,6 +172,32 @@ import SwipeableCards from '@shared/components/mobile/SwipeableCards.vue'
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### ASCII Diagram: Action Bar Layout (Edit/Create Views)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ MobileTopBar (56px) │
|
||||
│ [←] Editare Bon [⋮] │
|
||||
├─────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Form Fields... │
|
||||
│ │
|
||||
│ ┌─────────────────────────────┐ │
|
||||
│ │ Furnizor: LIDL │ │
|
||||
│ │ Total: 125.50 RON │ │
|
||||
│ │ Data: 2026-01-12 │ │
|
||||
│ └─────────────────────────────┘ │
|
||||
│ │
|
||||
├─────────────────────────────────────────┤
|
||||
│ MobileActionBar (context-aware) │
|
||||
│ ┌──────────┐ ┌──────────────────┐ │
|
||||
│ │ Salvează │ │ Trimite aprobare │ │
|
||||
│ └──────────┘ └──────────────────┘ │
|
||||
├─────────────────────────────────────────┤
|
||||
│ MobileBottomNav (56px) │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### ASCII Diagram: BottomSheet Open
|
||||
|
||||
```
|
||||
@@ -180,6 +243,120 @@ import SwipeableCards from '@shared/components/mobile/SwipeableCards.vue'
|
||||
|
||||
---
|
||||
|
||||
## Navigation Architecture
|
||||
|
||||
### Route Map
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ / (root) │
|
||||
│ Redirects to /reports/dashboard │
|
||||
└───────────────┬─────────────────────┘
|
||||
│
|
||||
┌───────────────────────────┼───────────────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌───────────────────┐ ┌───────────────────────┐ ┌─────────────────┐
|
||||
│ /data-entry │ │ /reports │ │ /settings │
|
||||
│ │ │ │ │ │
|
||||
│ 📋 Bonuri List │ │ 📊 dashboard │ │ ⚙️ Settings Hub │
|
||||
│ 📝 Bon Create │ │ 📄 invoices │ │ (centralized │
|
||||
│ ✏️ Bon Edit │ │ 💰 bank-cash │ │ settings) │
|
||||
│ 📊 OCR Metrics │ │ 🔢 trial-balance │ │ │
|
||||
│ │ │ 📉 maturity-analysis │ │ Links to: │
|
||||
│ │ │ 📋 detailed-invoices │ │ - OCR Settings │
|
||||
│ │ │ 📈 cache-stats │ │ - Cache Stats │
|
||||
│ │ │ 📝 server-logs │ │ - Server Logs │
|
||||
│ │ │ 📱 telegram │ │ - Telegram │
|
||||
└───────────────────┘ └───────────────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
### Navigation Flow: Settings Hub Pattern
|
||||
|
||||
The Settings Hub (`/settings`) is the centralized entry point for all administrative pages:
|
||||
|
||||
```
|
||||
MobileBottomNav "Setări" button
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────────┐
|
||||
│ Settings Hub │
|
||||
│ /settings │
|
||||
│ │
|
||||
│ ┌─────────┐ ┌─────────┐ │
|
||||
│ │ OCR │ │ Cache │ │
|
||||
│ │ Setări │ │ Stats │ │
|
||||
│ └────┬────┘ └────┬────┘ │
|
||||
│ │ │ │
|
||||
│ ┌────┴────┐ ┌────┴────┐ │
|
||||
│ │ Server │ │Telegram │ │
|
||||
│ │ Logs │ │ Bot │ │
|
||||
│ └─────────┘ └─────────┘ │
|
||||
└───────────────────────────────────┘
|
||||
│
|
||||
▼ (click on card)
|
||||
┌───────────────────────────────────┐
|
||||
│ /data-entry/ocr-metrics │
|
||||
│ /reports/cache-stats │
|
||||
│ /reports/server-logs │
|
||||
│ /reports/telegram │
|
||||
└───────────────────────────────────┘
|
||||
```
|
||||
|
||||
### MobileBottomNav Default Items (Updated)
|
||||
|
||||
```javascript
|
||||
// Default navigation items
|
||||
[
|
||||
{ to: '/data-entry', icon: 'pi pi-receipt', label: 'Bonuri' },
|
||||
{ icon: 'pi pi-cloud-upload', label: 'Upload' }, // Action button
|
||||
{ to: '/reports/dashboard', icon: 'pi pi-chart-bar', label: 'Rapoarte' },
|
||||
{ to: '/settings', icon: 'pi pi-cog', label: 'Setări' } // → Settings Hub
|
||||
]
|
||||
```
|
||||
|
||||
### MobileDrawerMenu Navigation Links
|
||||
|
||||
```javascript
|
||||
// Drawer menu navigation items
|
||||
[
|
||||
{ to: '/reports/dashboard', icon: 'pi pi-home', label: 'Dashboard' },
|
||||
{ to: '/data-entry', icon: 'pi pi-receipt', label: 'Bonuri' },
|
||||
{ to: '/reports/invoices', icon: 'pi pi-file', label: 'Facturi' },
|
||||
{ to: '/reports/trial-balance', icon: 'pi pi-calculator', label: 'Balanță' },
|
||||
{ to: '/reports/bank-cash', icon: 'pi pi-money-bill', label: 'Trezorerie' },
|
||||
{ to: '/settings', icon: 'pi pi-cog', label: 'Setări' }
|
||||
]
|
||||
```
|
||||
|
||||
### Dashboard Mobile Quick Links
|
||||
|
||||
On mobile, Dashboard shows KPI cards plus quick-link cards:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ MobileTopBar: Dashboard │
|
||||
├─────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────┐ │
|
||||
│ │ SwipeableCards (KPIs) │ │
|
||||
│ │ ← Swipe → │ │
|
||||
│ └─────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ 📉 Analiză │ │ 📋 Facturi │ │
|
||||
│ │ Scadențe → │ │ Detaliate → │ │
|
||||
│ └─────────────┘ └─────────────┘ │
|
||||
│ │
|
||||
│ (Quick links to dedicated pages) │
|
||||
│ │
|
||||
├─────────────────────────────────────────┤
|
||||
│ MobileBottomNav │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MobileTopBar
|
||||
|
||||
Material Design 3 inspired top navigation bar for mobile views.
|
||||
@@ -310,7 +487,7 @@ interface NavItem {
|
||||
{ to: '/data-entry', icon: 'pi pi-receipt', label: 'Bonuri' },
|
||||
{ icon: 'pi pi-cloud-upload', label: 'Upload' }, // Action button
|
||||
{ to: '/reports/dashboard', icon: 'pi pi-chart-bar', label: 'Rapoarte' },
|
||||
{ to: '/data-entry/ocr-metrics', icon: 'pi pi-cog', label: 'Setări' }
|
||||
{ to: '/settings', icon: 'pi pi-cog', label: 'Setări' } // → Settings Hub
|
||||
]
|
||||
```
|
||||
|
||||
@@ -359,6 +536,282 @@ const handleNavClick = (item) => {
|
||||
|
||||
---
|
||||
|
||||
## MobileDrawerMenu
|
||||
|
||||
Material Design 3 inspired navigation drawer that slides in from the left. Replaces the desktop sidebar on mobile devices.
|
||||
|
||||
### Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `modelValue` | Boolean | `false` | Controls visibility (v-model support) |
|
||||
| `user` | Object | `null` | User object for profile display `{ username: string }` |
|
||||
| `onLogout` | Function | `null` | Optional logout callback; emits `logout` event if not provided |
|
||||
|
||||
### Events
|
||||
|
||||
| Event | Payload | Description |
|
||||
|-------|---------|-------------|
|
||||
| `update:modelValue` | `boolean` | v-model update when visibility changes |
|
||||
| `logout` | - | Emitted when logout is clicked (if no `onLogout` prop) |
|
||||
|
||||
### Navigation Items (Built-in)
|
||||
|
||||
The drawer contains the following navigation links:
|
||||
|
||||
```javascript
|
||||
[
|
||||
{ to: '/reports/dashboard', icon: 'pi pi-home', label: 'Dashboard' },
|
||||
{ to: '/data-entry', icon: 'pi pi-receipt', label: 'Bonuri' },
|
||||
{ to: '/reports/invoices', icon: 'pi pi-file', label: 'Facturi' },
|
||||
{ to: '/reports/trial-balance', icon: 'pi pi-calculator', label: 'Balanță' },
|
||||
{ to: '/reports/bank-cash', icon: 'pi pi-money-bill', label: 'Trezorerie' },
|
||||
{ to: '/settings', icon: 'pi pi-cog', label: 'Setări' }
|
||||
]
|
||||
```
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<MobileTopBar
|
||||
title="Dashboard"
|
||||
:showMenu="true"
|
||||
@menu-click="showDrawer = true"
|
||||
/>
|
||||
|
||||
<MobileDrawerMenu
|
||||
v-model="showDrawer"
|
||||
:user="authStore.user"
|
||||
@logout="handleLogout"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import MobileDrawerMenu from '@shared/components/mobile/MobileDrawerMenu.vue'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
|
||||
const showDrawer = ref(false)
|
||||
const authStore = useAuthStore()
|
||||
|
||||
const handleLogout = async () => {
|
||||
await authStore.logout()
|
||||
router.push('/login')
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
### With Logout Callback
|
||||
|
||||
```vue
|
||||
<MobileDrawerMenu
|
||||
v-model="showDrawer"
|
||||
:user="{ username: 'John Doe' }"
|
||||
:onLogout="async () => {
|
||||
await api.logout()
|
||||
router.push('/login')
|
||||
}"
|
||||
/>
|
||||
```
|
||||
|
||||
### Features
|
||||
|
||||
| Feature | Description |
|
||||
|---------|-------------|
|
||||
| **Slide Animation** | Slides in from left with overlay fade |
|
||||
| **Close on Tap Outside** | Tapping the overlay closes the drawer |
|
||||
| **Close on Navigation** | Drawer closes automatically when a link is clicked |
|
||||
| **Active State** | Current route is highlighted |
|
||||
| **Profile Section** | Displays username and logout button at bottom |
|
||||
| **Teleported** | Rendered to `<body>` to avoid z-index issues |
|
||||
| **Dark Mode** | Full support for light/dark themes |
|
||||
|
||||
### CSS Classes
|
||||
|
||||
| Class | Description |
|
||||
|-------|-------------|
|
||||
| `.drawer-overlay` | Full-screen backdrop (50% black) |
|
||||
| `.drawer-menu` | Main drawer container (280px, max 85vw) |
|
||||
| `.drawer-header` | Header with logo |
|
||||
| `.drawer-section` | Navigation links container |
|
||||
| `.drawer-link` | Individual navigation link (48px min-height) |
|
||||
| `.drawer-link.active` | Active route styling (blue background) |
|
||||
| `.drawer-profile` | Profile section at bottom |
|
||||
| `.logout-link` | Red logout button styling |
|
||||
|
||||
### Animation
|
||||
|
||||
Uses Vue `<Transition name="drawer">`:
|
||||
- Overlay fades in/out
|
||||
- Drawer slides from left (`translateX(-100%)` → `translateX(0)`)
|
||||
- Duration: `var(--transition-normal)` (250ms)
|
||||
|
||||
---
|
||||
|
||||
## MobileActionBar
|
||||
|
||||
Context-aware bottom action bar for forms and edit views. Positions above MobileBottomNav and displays action buttons based on current state.
|
||||
|
||||
### Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `visible` | Boolean | `false` | Controls visibility (triggers slide-up animation) |
|
||||
| `actions` | Array | `[]` | Array of action buttons to display |
|
||||
|
||||
### Action Object Structure
|
||||
|
||||
```typescript
|
||||
interface ActionBarAction {
|
||||
label: string // Button text (e.g., 'Salvează')
|
||||
icon: string // PrimeIcons class (e.g., 'pi pi-save')
|
||||
severity?: string // PrimeVue severity ('primary', 'secondary', 'danger', etc.)
|
||||
handler: () => void // Click handler function
|
||||
disabled?: boolean // Disable the button
|
||||
}
|
||||
```
|
||||
|
||||
### Layout Behavior
|
||||
|
||||
| Actions Count | Layout |
|
||||
|---------------|--------|
|
||||
| 1 button | Full-width |
|
||||
| 2 buttons | Side-by-side, equal width |
|
||||
| 3+ buttons | Equal distribution |
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<MobileActionBar
|
||||
:visible="isMobile"
|
||||
:actions="formActions"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import MobileActionBar from '@shared/components/mobile/MobileActionBar.vue'
|
||||
|
||||
const formActions = [
|
||||
{
|
||||
label: 'Salvează',
|
||||
icon: 'pi pi-save',
|
||||
severity: 'primary',
|
||||
handler: handleSave
|
||||
},
|
||||
{
|
||||
label: 'Anulează',
|
||||
icon: 'pi pi-times',
|
||||
severity: 'secondary',
|
||||
handler: handleCancel
|
||||
}
|
||||
]
|
||||
</script>
|
||||
```
|
||||
|
||||
### Context-Aware Actions (Receipt Edit Example)
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<MobileActionBar
|
||||
:visible="isMobile"
|
||||
:actions="contextAwareActions"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
|
||||
const receiptStatus = ref('draft') // 'draft' | 'pending' | 'approved' | 'rejected'
|
||||
|
||||
const contextAwareActions = computed(() => {
|
||||
switch (receiptStatus.value) {
|
||||
case 'draft':
|
||||
return [
|
||||
{ label: 'Salvează', icon: 'pi pi-save', severity: 'secondary', handler: handleSave },
|
||||
{ label: 'Trimite', icon: 'pi pi-send', severity: 'primary', handler: handleSubmit }
|
||||
]
|
||||
case 'pending':
|
||||
return [
|
||||
{ label: 'Salvează', icon: 'pi pi-save', severity: 'secondary', handler: handleSave },
|
||||
{ label: 'Aprobă', icon: 'pi pi-check', severity: 'success', handler: handleApprove },
|
||||
{ label: 'Respinge', icon: 'pi pi-times', severity: 'danger', handler: handleReject }
|
||||
]
|
||||
case 'approved':
|
||||
return [] // No actions for approved receipts
|
||||
case 'rejected':
|
||||
return [
|
||||
{ label: 'Salvează', icon: 'pi pi-save', severity: 'secondary', handler: handleSave },
|
||||
{ label: 'Re-trimite', icon: 'pi pi-refresh', severity: 'primary', handler: handleResubmit }
|
||||
]
|
||||
default:
|
||||
return []
|
||||
}
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
### Hiding During Overlays
|
||||
|
||||
Hide the action bar when BottomSheet or other overlays are open:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<MobileActionBar
|
||||
:visible="isMobile && !isBottomSheetOpen"
|
||||
:actions="formActions"
|
||||
/>
|
||||
|
||||
<BottomSheet v-model="isBottomSheetOpen">
|
||||
<!-- Filter content -->
|
||||
</BottomSheet>
|
||||
</template>
|
||||
```
|
||||
|
||||
### CSS Classes
|
||||
|
||||
| Class | Description |
|
||||
|-------|-------------|
|
||||
| `.mobile-action-bar` | Base container (fixed, bottom: 56px) |
|
||||
| `.action-bar-content` | Button container (max-width: 500px) |
|
||||
| `.layout-single` | Single button layout (full-width) |
|
||||
| `.layout-dual` | Two button layout (50% each) |
|
||||
| `.layout-multi` | Three+ button layout (equal distribution) |
|
||||
| `.action-bar-btn` | Individual button (48px min-height) |
|
||||
|
||||
### Animation
|
||||
|
||||
Uses Vue `<Transition name="slide-up">`:
|
||||
- Slides up from below screen (`translateY(100%)` → `translateY(0)`)
|
||||
- Duration: `var(--transition-normal)` (250ms)
|
||||
- Fades in/out simultaneously
|
||||
|
||||
### Positioning
|
||||
|
||||
```css
|
||||
.mobile-action-bar {
|
||||
position: fixed;
|
||||
bottom: 56px; /* Above MobileBottomNav */
|
||||
left: 0;
|
||||
right: 0;
|
||||
/* Safe area support for iPhone X+ */
|
||||
bottom: calc(56px + env(safe-area-inset-bottom));
|
||||
}
|
||||
```
|
||||
|
||||
### Content Padding Adjustment
|
||||
|
||||
When MobileActionBar is visible, increase bottom padding:
|
||||
|
||||
```css
|
||||
.mobile-content {
|
||||
padding-bottom: 120px; /* 56px (nav) + 64px (action bar) */
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MobileSelectionFooter
|
||||
|
||||
Slide-up action bar for batch operations on selected items.
|
||||
@@ -900,6 +1353,23 @@ Check that `data-theme` attribute is set correctly.
|
||||
|
||||
---
|
||||
|
||||
## Changelog
|
||||
|
||||
### Version 2.0.0 (2026-01-12)
|
||||
|
||||
- **NEW**: Added `MobileDrawerMenu` component documentation
|
||||
- **NEW**: Added `MobileActionBar` component documentation
|
||||
- **NEW**: Added Navigation Architecture section with route maps
|
||||
- **UPDATED**: MobileBottomNav default items now point to Settings Hub (`/settings`)
|
||||
- **UPDATED**: ASCII diagrams with new routes and component layouts
|
||||
- **UPDATED**: Quick Start section to include drawer menu integration
|
||||
|
||||
### Version 1.0.0 (2026-01-11)
|
||||
|
||||
- Initial release with MobileTopBar, MobileBottomNav, MobileSelectionFooter, BottomSheet, SwipeableCards
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2026-01-12
|
||||
**Version:** 1.0.0
|
||||
**Version:** 2.0.0
|
||||
**Maintained By:** Frontend Team
|
||||
|
||||
@@ -246,8 +246,8 @@
|
||||
"Diagrame ASCII actualizate cu noile rute",
|
||||
"npm run build passes (doar pentru validare că nu s-a stricat nimic)"
|
||||
],
|
||||
"passes": false,
|
||||
"notes": ""
|
||||
"passes": true,
|
||||
"notes": "Completed in iteration 14"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -82,3 +82,9 @@ User Stories: 14 (US-201 to US-214)
|
||||
[2026-01-12 12:40:31] Working on story: US-211
|
||||
[2026-01-12 12:40:31] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_13_US-211.log)
|
||||
[2026-01-12 12:42:01] SUCCESS: Story US-211 passed!
|
||||
[2026-01-12 12:42:01] Changes committed
|
||||
[2026-01-12 12:42:01] Progress: 13/14 stories completed
|
||||
[2026-01-12 12:42:03] === Iteration 14/100 ===
|
||||
[2026-01-12 12:42:03] Working on story: US-214
|
||||
[2026-01-12 12:42:03] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_14_US-214.log)
|
||||
[2026-01-12 12:45:42] SUCCESS: Story US-214 passed!
|
||||
|
||||
Reference in New Issue
Block a user