From 9eed6b578b61da3aa04596c03a673ba1df7e1caf Mon Sep 17 00:00:00 2001 From: NikDizell Date: Fri, 24 Apr 2026 14:55:23 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A1=D0=BE=D0=B1=D1=80=D0=B0=D0=BB=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BB=D0=BB=D0=B5=D0=BA=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/programmer/css/styles.css | 258 +++++++++++++++++++++++++++- static/programmer/js/mobile-menu.js | 13 +- 2 files changed, 266 insertions(+), 5 deletions(-) diff --git a/static/programmer/css/styles.css b/static/programmer/css/styles.css index d539e73..91a41ef 100644 --- a/static/programmer/css/styles.css +++ b/static/programmer/css/styles.css @@ -125,7 +125,7 @@ body { .nav { display: flex; align-items: center; - justify-content: space-between; + justify-content: flex-start; padding: 1rem 0; gap: 2rem; } @@ -160,16 +160,190 @@ body { .nav-menu { display: flex; + align-items: center; list-style: none; gap: 2.5rem; margin: 0; flex-wrap: wrap; } +/* ===== DROPDOWN MENU (DESKTOP) ===== */ +.nav-menu .has-dropdown { + position: relative; +} + +/* Родительский пункт (span или ссылка) */ +.nav-menu .has-dropdown > a, +.nav-menu .has-dropdown > span { + text-decoration: none; + color: var(--text-secondary); + font-weight: 600; + padding: 0.75rem 0; + position: relative; + font-size: 1rem; + display: inline-block; + cursor: default; + transition: var(--transition); +} + +/* Выпадающий список */ +.nav-menu .dropdown { + position: absolute; + top: 100%; + left: 0; + min-width: 200px; + background: var(--bg-card); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-xl); + border: 1px solid var(--border-light); + opacity: 0; + visibility: hidden; + transform: translateY(-10px); + transition: opacity 0.2s ease, visibility 0.2s ease, transform 0.2s ease; + list-style: none; + padding: 0.5rem 0; + z-index: 1000; +} + +/* Показываем dropdown при наведении на родительский li */ +.nav-menu .has-dropdown:hover .dropdown { + opacity: 1; + visibility: visible; + transform: translateY(0); +} + +/* Элементы dropdown */ +.nav-menu .dropdown li { + margin: 0; +} + +.nav-menu .dropdown a { + display: block; + padding: 0.6rem 1.2rem; + color: var(--text-primary); + text-decoration: none; + transition: var(--transition); + font-weight: 500; + white-space: nowrap; +} + +.nav-menu .dropdown a:hover { + background: var(--bg-secondary); + color: var(--primary); + padding-left: 1.5rem; +} + +/* Небольшой треугольник (опционально) */ +.nav-menu .has-dropdown > span::after, +.nav-menu .has-dropdown > a::after { + /* content: '▼'; */ + font-size: 0.75em; + margin-left: 6px; + opacity: 0.7; + vertical-align: middle; + transition: transform 0.2s ease; +} + +.nav-menu .has-dropdown:hover > span::after, +.nav-menu .has-dropdown:hover > a::after { + transform: rotate(180deg); +} + +/* ===== USER MENU DROPDOWN (DESKTOP) ===== */ +.user-menu { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.user-menu-item { + position: relative; +} + +.user-menu-parent { + cursor: default; + display: inline-block; + padding: 0.5rem 1rem; /* соответствие .nav-link */ +} + +.user-menu .has-dropdown > a, +.user-menu .has-dropdown > span { + cursor: default; +} + +.user-menu .dropdown { + position: absolute; + top: 100%; + right: 0; /* выравнивание по правому краю */ + min-width: 180px; + background: var(--bg-card); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-xl); + border: 1px solid var(--border-light); + opacity: 0; + visibility: hidden; + transform: translateY(-10px); + transition: opacity 0.2s ease, visibility 0.2s ease, transform 0.2s ease; + list-style: none; + padding: 0.5rem 0; + z-index: 1001; +} + +.user-menu .has-dropdown:hover .dropdown { + opacity: 1; + visibility: visible; + transform: translateY(0); +} + +.user-menu .dropdown li { + margin: 0; +} + +.user-menu .dropdown-link, +.user-menu .dropdown-link-btn { + display: block; + width: 100%; + padding: 0.6rem 1.2rem; + color: var(--text-primary); + text-decoration: none; + transition: var(--transition); + font-weight: 500; + white-space: nowrap; + background: none; + border: none; + text-align: left; + font: inherit; + cursor: pointer; +} + +.user-menu .dropdown-link:hover, +.user-menu .dropdown-link-btn:hover { + background: var(--bg-secondary); + color: var(--primary); + padding-left: 1.5rem; +} + +/* Стрелка для родительского пункта (опционально) */ +.user-menu .has-dropdown > span::after, +.user-menu .has-dropdown > a::after { + /* content: '▼'; */ + font-size: 0.75em; + margin-left: 6px; + opacity: 0.7; + vertical-align: middle; + transition: transform 0.2s ease; +} + +.user-menu .has-dropdown:hover > span::after, +.user-menu .has-dropdown:hover > a::after { + transform: rotate(180deg); +} + .nav-actions { display: flex; align-items: center; gap: 1rem; + margin-left: auto; } .nav-link { @@ -1346,6 +1520,53 @@ body { margin-bottom: 0.5rem; } +/* ===== MOBILE SUBMENU ===== */ +.mobile-nav-item.has-submenu { + position: relative; +} + +/* Родительский пункт в мобильном меню (может быть span или ссылка) */ +.mobile-nav-parent { + cursor: pointer; + display: flex; + align-items: center; + justify-content: space-between; +} + +/* Стрелочка для родительского пункта */ +.mobile-nav-parent::after { + content: '▼'; + font-size: 0.8rem; + opacity: 0.7; + transition: transform 0.2s ease; +} + +.has-submenu.submenu-open .mobile-nav-parent::after { + transform: rotate(180deg); +} + +/* Вложенный список */ +.mobile-submenu { + list-style: none; + margin-left: 1rem; + padding-left: 0.5rem; + border-left: 2px solid var(--primary); + display: none; +} + +.has-submenu.submenu-open .mobile-submenu { + display: block; +} + +.mobile-submenu .mobile-nav-item { + margin-bottom: 0; +} + +.mobile-submenu .mobile-nav-link { + padding: 0.75rem 1rem; + font-size: 0.95rem; +} + .mobile-nav-link { display: block; padding: 1rem; @@ -1752,4 +1973,39 @@ body { .floating-btn .btn.pulse { animation: pulse 1.5s infinite; will-change: transform; +} + +/* Стили для
/ */ +details { + margin: 1rem 0; +} + +summary { + display: inline-block; + padding: 0.5rem 1rem; + background: var(--bg-primary); + border: 1px solid var(--border-light); + border-radius: var(--radius-md); + transition: var(--transition); + user-select: none; +} + +summary:hover { + background: var(--primary); + color: white; + border-color: var(--primary); +} + +details[open] summary { + background: var(--primary); + color: white; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +details[open] { + border: 1px solid var(--border-light); + border-radius: var(--radius-md); + padding: 1rem; + background: var(--bg-primary); } \ No newline at end of file diff --git a/static/programmer/js/mobile-menu.js b/static/programmer/js/mobile-menu.js index c0b299e..24263d0 100644 --- a/static/programmer/js/mobile-menu.js +++ b/static/programmer/js/mobile-menu.js @@ -49,11 +49,16 @@ document.addEventListener('DOMContentLoaded', function() { } // Закрытие меню при клике на ссылку - const mobileNavLinks = document.querySelectorAll('.mobile-nav-link'); - mobileNavLinks.forEach(link => { - link.addEventListener('click', closeMobileMenu); + document.querySelectorAll('.mobile-nav-item.has-submenu > .mobile-nav-link, .mobile-nav-item.has-submenu > .mobile-nav-parent').forEach(item => { + item.addEventListener('click', function(e) { + if (window.innerWidth <= 768) { // или ваш брейкпоинт + e.preventDefault(); + const parent = this.closest('.has-submenu'); + parent.classList.toggle('submenu-open'); + } + }); }); - + // Синхронизация переключателей темы function syncThemeToggles() { if (mobileThemeToggle && mainThemeToggle) {