Files
tp/main_dc/yalarba/easySite/app/components/layout/HamburgerMenu.vue
T
valitovgaziz 2941b14b38 flatten easySite directory: remove extra easySite/easySite nesting
- Moved contents of main_dc/yalarba/easySite/easySite/ up to easySite/
- Updated docker-compose.yml build context path
- Deleted empty nested easySite/ directory
2026-06-12 11:16:15 +05:00

501 lines
11 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="hamburger-menu">
<!-- Кнопка гамбургера -->
<button
class="hamburger-button"
:class="{ 'active': isOpen }"
aria-label="Меню"
@click="toggleMenu">
<span class="hamburger-line"/>
<span class="hamburger-line"/>
<span class="hamburger-line"/>
</button>
<!-- Затемнение фона -->
<div v-if="isOpen" class="menu-overlay" @click="closeMenu"/>
<!-- Само меню -->
<transition name="slide-left">
<div v-if="isOpen" class="menu-content">
<!-- Заголовок меню -->
<div class="menu-header">
<div v-if="false" class="user-info"> <!-- Можно добавить позже -->
<div class="user-avatar">👤</div>
<div class="user-details">
<div class="user-name">Гость</div>
<div class="user-status">Не авторизован</div>
</div>
</div>
<h3 class="menu-title">Меню</h3>
<button class="close-button" aria-label="Закрыть" @click="closeMenu">
</button>
</div>
<!-- Настройки тем -->
<div class="menu-section">
<h4 class="menu-section-title">Настройки</h4>
<!-- Переключатель темы -->
<div class="menu-item toggle-item">
<div class="toggle-label">
<span class="toggle-icon">🌙</span>
<span class="toggle-text">Темная тема</span>
</div>
<button
aria-label="Переключить тему"
class="theme-toggle"
:class="{ 'active': theme === 'dark' }"
@click="toggleTheme">
<span class="toggle-slider"/>
</button>
</div>
<!-- Переключатель шрифтов -->
<div class="menu-item toggle-item">
<div class="toggle-label">
<span class="toggle-icon">🔤</span>
<span class="toggle-text">Элегантный шрифт</span>
</div>
<button
class="font-toggle"
:class="{ 'active': fontSet === 'elegant' }"
aria-label="Переключить шрифт"
@click="toggleFontSet">
<span class="toggle-slider"/>
</button>
</div>
</div>
<!-- Навигация -->
<div class="menu-section">
<h4 class="menu-section-title">Аккаунт</h4>
<NuxtLink to="/profile" class="menu-item" @click="closeMenu">
<span class="menu-icon">👤</span>
<span class="menu-text">Профиль</span>
</NuxtLink>
<NuxtLink to="/auth/register" class="menu-item" @click="closeMenu">
<span class="menu-icon">📝</span>
<span class="menu-text">Регистрация</span>
</NuxtLink>
<NuxtLink to="/auth/login" class="menu-item" @click="closeMenu">
<span class="menu-icon">🔑</span>
<span class="menu-text">Вход</span>
</NuxtLink>
</div>
<!-- Дополнительные ссылки -->
<div class="menu-section">
<h4 class="menu-section-title">Навигация</h4>
<NuxtLink to="/" class="menu-item" @click="closeMenu">
<span class="menu-icon">🏠</span>
<span class="menu-text">Главная</span>
</NuxtLink>
<NuxtLink to="/objects" class="menu-item" @click="closeMenu">
<span class="menu-icon">🔍</span>
<span class="menu-text">Все объекты</span>
</NuxtLink>
<NuxtLink to="/objects/create" class="menu-item" @click="closeMenu">
<span class="menu-icon"></span>
<span class="menu-text">Добавить объект</span>
</NuxtLink>
<!-- В секции "Навигация" добавьте: -->
<NuxtLink to="/about" class="menu-item" @click="closeMenu">
<span class="menu-icon"></span>
<span class="menu-text">О компании</span>
</NuxtLink>
<a href="/support" class="menu-item" @click="closeMenu">
<span class="menu-icon"></span>
<span class="menu-text">Помощь</span>
</a>
<a href="/contact" class="menu-item" @click="closeMenu">
<span class="menu-icon">📞</span>
<span class="menu-text">Контакты</span>
</a>
</div>
<!-- Футер меню -->
<div class="menu-footer">
<div class="menu-version">v1.0.0</div>
<div class="menu-copyright">© 2024 EasySite</div>
</div>
</div>
</transition>
</div>
</template>
<script setup lang="ts">
const isOpen = ref(false)
const { theme, toggleTheme, fontSet, toggleFontSet } = useTheme()
const toggleMenu = () => {
isOpen.value = !isOpen.value
}
const closeMenu = () => {
isOpen.value = false
}
// Закрытие меню при нажатии ESC
const handleEscape = (event: KeyboardEvent) => {
if (event.key === 'Escape' && isOpen.value) {
closeMenu()
}
}
// Закрытие меню при изменении размера окна на десктоп
const handleResize = () => {
if (window.innerWidth >= 1024 && isOpen.value) {
closeMenu()
}
}
onMounted(() => {
document.addEventListener('keydown', handleEscape)
window.addEventListener('resize', handleResize)
})
onUnmounted(() => {
document.removeEventListener('keydown', handleEscape)
window.removeEventListener('resize', handleResize)
})
</script>
<style scoped>
.hamburger-menu {
position: relative;
}
/* Кнопка гамбургера */
.hamburger-button {
display: flex;
flex-direction: column;
justify-content: space-between;
width: 2rem;
height: 1.5rem;
background: none;
border: none;
cursor: pointer;
padding: 0;
transition: all 0.3s ease;
}
.hamburger-button:hover {
opacity: 0.8;
transform: scale(1.05);
}
.hamburger-line {
width: 100%;
height: 2px;
background: var(--text-primary);
transition: all 0.3s ease;
border-radius: 1px;
}
.hamburger-button.active .hamburger-line:nth-child(1) {
transform: rotate(45deg) translate(6px, 6px);
}
.hamburger-button.active .hamburger-line:nth-child(2) {
opacity: 0;
}
.hamburger-button.active .hamburger-line:nth-child(3) {
transform: rotate(-45deg) translate(6px, -6px);
}
/* Затемнение фона */
.menu-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 998;
}
/* Контент меню */
.menu-content {
position: fixed;
top: 0;
right: 0;
bottom: 0;
width: 380px;
max-width: 90vw;
background: var(--bg-primary);
box-shadow: -4px 0 16px rgba(0, 0, 0, 0.1);
z-index: 999;
display: flex;
flex-direction: column;
overflow-y: auto;
border-left: 1px solid var(--border-light);
}
/* Анимация появления */
.slide-left-enter-active,
.slide-left-leave-active {
transition: transform 0.3s ease;
}
.slide-left-enter-from,
.slide-left-leave-to {
transform: translateX(100%);
}
/* Заголовок меню */
.menu-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1.5rem;
border-bottom: 1px solid var(--border-light);
background: var(--bg-secondary);
}
.user-info {
display: flex;
align-items: center;
gap: 0.75rem;
}
.user-avatar {
width: 2.5rem;
height: 2.5rem;
background: var(--primary-500);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2rem;
}
.user-details {
display: flex;
flex-direction: column;
}
.user-name {
font-weight: 600;
color: var(--text-primary);
font-size: 0.95rem;
}
.user-status {
font-size: 0.8rem;
color: var(--text-tertiary);
}
.menu-title {
font-family: var(--font-heading);
font-size: 1.25rem;
font-weight: 600;
color: var(--text-primary);
margin: 0;
}
.close-button {
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
color: var(--text-secondary);
padding: 0.25rem;
border-radius: var(--radius-sm);
transition: all 0.2s ease;
width: 2rem;
height: 2rem;
display: flex;
align-items: center;
justify-content: center;
}
.close-button:hover {
color: var(--text-primary);
background: var(--bg-tertiary);
}
/* Секции меню */
.menu-section {
padding: 1.5rem;
border-bottom: 1px solid var(--border-light);
}
.menu-section:last-child {
border-bottom: none;
}
.menu-section-title {
font-family: var(--font-primary);
font-size: 0.875rem;
font-weight: 600;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 1rem;
}
/* Элементы меню */
.menu-item {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.75rem 0;
text-decoration: none;
color: var(--text-primary);
transition: all 0.2s ease;
border-radius: var(--radius-md);
cursor: pointer;
}
.menu-item:hover {
background: var(--bg-secondary);
color: var(--primary-600);
padding-left: 0.5rem;
padding-right: 0.5rem;
}
.menu-icon {
font-size: 1.25rem;
width: 1.5rem;
text-align: center;
}
.menu-text {
font-family: var(--font-primary);
font-weight: 500;
font-size: 0.95rem;
flex: 1;
}
/* Переключатели */
.toggle-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.75rem 0;
}
.toggle-label {
display: flex;
align-items: center;
gap: 0.75rem;
flex: 1;
}
.toggle-icon {
font-size: 1.25rem;
width: 1.5rem;
text-align: center;
}
.toggle-text {
font-family: var(--font-primary);
font-weight: 500;
font-size: 0.95rem;
color: var(--text-primary);
}
/* Стили для тогглов */
.theme-toggle,
.font-toggle {
position: relative;
width: 3rem;
height: 1.5rem;
background: var(--gray-300);
border: none;
border-radius: 0.75rem;
cursor: pointer;
transition: all 0.3s ease;
padding: 0;
flex-shrink: 0;
}
.theme-toggle:hover,
.font-toggle:hover {
transform: scale(1.05);
}
.theme-toggle.active,
.font-toggle.active {
background: var(--primary-500);
}
.toggle-slider {
position: absolute;
top: 0.125rem;
left: 0.125rem;
width: 1.25rem;
height: 1.25rem;
background: white;
border-radius: 50%;
transition: all 0.3s ease;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
.theme-toggle.active .toggle-slider,
.font-toggle.active .toggle-slider {
transform: translateX(1.5rem);
}
/* Футер меню */
.menu-footer {
margin-top: auto;
padding: 1.5rem;
border-top: 1px solid var(--border-light);
text-align: center;
background: var(--bg-secondary);
}
.menu-version {
font-size: 0.75rem;
color: var(--text-tertiary);
margin-bottom: 0.25rem;
}
.menu-copyright {
font-size: 0.75rem;
color: var(--text-tertiary);
}
/* Адаптивность для десктопа */
@media (min-width: 1024px) {
.menu-content {
width: 400px;
}
.hamburger-button {
width: 2.25rem;
height: 1.75rem;
}
}
@media (max-width: 480px) {
.menu-content {
width: 300px;
}
.menu-section {
padding: 1rem;
}
.menu-header {
padding: 1rem;
}
.menu-footer {
padding: 1rem;
}
}
</style>