feat(unified-mobile-material-design): Complete US-101a - Creare MobileTopBar.vue component
Implemented by Ralph autonomous loop. Iteration: 1 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
218
src/shared/components/mobile/MobileTopBar.vue
Normal file
218
src/shared/components/mobile/MobileTopBar.vue
Normal file
@@ -0,0 +1,218 @@
|
||||
<template>
|
||||
<header class="mobile-top-bar" :class="{ 'selection-active': selectionActive }">
|
||||
<!-- Left section -->
|
||||
<div class="top-bar-left">
|
||||
<Button
|
||||
v-if="showBack"
|
||||
icon="pi pi-arrow-left"
|
||||
text
|
||||
rounded
|
||||
class="top-bar-btn"
|
||||
@click="$emit('back-click')"
|
||||
aria-label="Înapoi"
|
||||
/>
|
||||
<Button
|
||||
v-else-if="showMenu"
|
||||
icon="pi pi-bars"
|
||||
text
|
||||
rounded
|
||||
class="top-bar-btn"
|
||||
@click="$emit('menu-click')"
|
||||
aria-label="Meniu"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Title section -->
|
||||
<h1 class="top-bar-title">{{ title }}</h1>
|
||||
|
||||
<!-- Right section - actions -->
|
||||
<div class="top-bar-right">
|
||||
<Button
|
||||
v-for="(action, index) in actions"
|
||||
:key="index"
|
||||
:icon="action.icon"
|
||||
text
|
||||
rounded
|
||||
class="top-bar-btn"
|
||||
:class="{ 'active': action.active }"
|
||||
@click="$emit('action-click', action)"
|
||||
:aria-label="action.label || action.icon"
|
||||
v-tooltip.bottom="action.tooltip"
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import Button from 'primevue/button'
|
||||
|
||||
/**
|
||||
* MobileTopBar - Material Design 3 inspired top navigation bar for mobile views
|
||||
*
|
||||
* Props:
|
||||
* - title: The text displayed in the center of the bar
|
||||
* - showBack: Shows back arrow button on the left
|
||||
* - showMenu: Shows hamburger menu button on the left (ignored if showBack is true)
|
||||
* - actions: Array of action buttons for the right side
|
||||
* - selectionActive: Whether selection mode is active (changes background)
|
||||
*
|
||||
* Events:
|
||||
* - menu-click: Emitted when menu button is clicked
|
||||
* - back-click: Emitted when back button is clicked
|
||||
* - action-click: Emitted when any action button is clicked, passes action object
|
||||
*/
|
||||
|
||||
defineProps({
|
||||
/**
|
||||
* Title displayed in the center of the top bar
|
||||
*/
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* Whether to show the back arrow button
|
||||
*/
|
||||
showBack: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
/**
|
||||
* Whether to show the hamburger menu button
|
||||
* (ignored if showBack is true)
|
||||
*/
|
||||
showMenu: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
/**
|
||||
* Array of action buttons for the right side
|
||||
* Each action should have: { icon: string, label?: string, tooltip?: string, active?: boolean }
|
||||
*/
|
||||
actions: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
/**
|
||||
* Whether selection mode is active (changes background color)
|
||||
*/
|
||||
selectionActive: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
defineEmits(['menu-click', 'back-click', 'action-click'])
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* ================================================
|
||||
MobileTopBar Component Styles
|
||||
Material Design 3 inspired mobile navigation
|
||||
================================================ */
|
||||
|
||||
.mobile-top-bar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 56px;
|
||||
background: var(--surface-card);
|
||||
border-bottom: 1px solid var(--surface-border);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 var(--space-xs);
|
||||
z-index: 1000;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
/* Selection mode active state */
|
||||
.mobile-top-bar.selection-active {
|
||||
background: var(--blue-50);
|
||||
border-bottom-color: var(--blue-200);
|
||||
}
|
||||
|
||||
/* Left and right button containers */
|
||||
.top-bar-left,
|
||||
.top-bar-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-xs);
|
||||
/* Ensure minimum width for consistent layout */
|
||||
min-width: 48px;
|
||||
}
|
||||
|
||||
/* Individual action buttons */
|
||||
.top-bar-btn {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: var(--radius-full);
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
/* Active state for buttons (e.g., filter active) */
|
||||
.top-bar-btn.active {
|
||||
color: var(--color-primary);
|
||||
background: var(--blue-50);
|
||||
}
|
||||
|
||||
/* Title in the center */
|
||||
.top-bar-title {
|
||||
font-size: var(--text-lg);
|
||||
font-weight: var(--font-semibold);
|
||||
color: var(--text-color);
|
||||
margin: 0;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* ================================================
|
||||
Dark Mode Support
|
||||
================================================ */
|
||||
|
||||
/* Manual dark mode via data-theme attribute */
|
||||
[data-theme="dark"] .mobile-top-bar {
|
||||
background: var(--surface-card);
|
||||
border-bottom-color: var(--surface-border);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mobile-top-bar.selection-active {
|
||||
background: var(--blue-900);
|
||||
border-bottom-color: var(--blue-700);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .top-bar-btn {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .top-bar-btn.active {
|
||||
color: var(--blue-400);
|
||||
background: var(--blue-900);
|
||||
}
|
||||
|
||||
/* Auto dark mode (when no manual theme is set) */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root:not([data-theme]) .mobile-top-bar {
|
||||
background: var(--surface-card);
|
||||
border-bottom-color: var(--surface-border);
|
||||
}
|
||||
|
||||
:root:not([data-theme]) .mobile-top-bar.selection-active {
|
||||
background: var(--blue-900);
|
||||
border-bottom-color: var(--blue-700);
|
||||
}
|
||||
|
||||
:root:not([data-theme]) .top-bar-btn {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
:root:not([data-theme]) .top-bar-btn.active {
|
||||
color: var(--blue-400);
|
||||
background: var(--blue-900);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user