From 737f0a9623a80334a69107bf05a2d36cbb3f3ece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B3=D0=BE=D1=80=D1=8C=20=D0=9D=D0=B0=D0=B4=D0=B5?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Tue, 28 Oct 2025 10:03:31 +0300 Subject: [PATCH] refactor: Extract sidebar and navbar CSS components - Created static/css/components/sidebar.css (200 lines) * Navigation layout, active states, badges * Theme switcher button - Created static/css/components/navbar.css (30 lines) * Menu toggle button * Dropdown avatar customization - Removed ~95 lines of inline styles from sidebar.html - Removed ~23 lines of inline styles from navbar.html - All tests passing (17 OK) --- backend/static/css/components/navbar.css | 29 ++++ backend/static/css/components/sidebar.css | 194 ++++++++++++++++++++++ backend/templates/includes/navbar.html | 22 +-- backend/templates/includes/sidebar.html | 97 +---------- 4 files changed, 225 insertions(+), 117 deletions(-) create mode 100644 backend/static/css/components/navbar.css create mode 100644 backend/static/css/components/sidebar.css diff --git a/backend/static/css/components/navbar.css b/backend/static/css/components/navbar.css new file mode 100644 index 00000000..8b1bdee7 --- /dev/null +++ b/backend/static/css/components/navbar.css @@ -0,0 +1,29 @@ +/** + * navbar.css + * Стили навбара: меню-тогглер, поиск, уведомления + */ + +/* ───────────────────────────────────────────────────────────── + MENU TOGGLE (гамбургер) +────────────────────────────────────────────────────────────── */ +/* Кнопка «гамбургера» — без круга/рамки */ +.menu-toggle { + padding: 0; + border: 0; + background: transparent; + line-height: 1; + color: #fff; +} + +.menu-toggle:focus { + outline: none; + box-shadow: none; +} + +/* ───────────────────────────────────────────────────────────── + DROPDOWN AVATAR +────────────────────────────────────────────────────────────── */ +/* Спрятать стрелочку у dropdown-аватара */ +.dropdown-toggle.no-caret::after { + display: none !important; +} diff --git a/backend/static/css/components/sidebar.css b/backend/static/css/components/sidebar.css new file mode 100644 index 00000000..9e224333 --- /dev/null +++ b/backend/static/css/components/sidebar.css @@ -0,0 +1,194 @@ +/** + * sidebar.css + * Стили левого сайдбара: навигация, активные элементы, переключатель темы + */ + +/* ───────────────────────────────────────────────────────────── + SIDEBAR LAYOUT +────────────────────────────────────────────────────────────── */ +/* Offcanvas остаётся как есть (липкий ≥ lg) */ +#sidebar { + --bs-offcanvas-border-color: transparent; + --bs-offcanvas-border-width: 0; + --bs-offcanvas-border-radius: 0; + border: 0 !important; + border-radius: 0 !important; + box-shadow: none !important; + background: var(--bs-body-bg); +} + +@media (min-width: 992px) { + #sidebar.offcanvas-lg { + position: sticky; + top: var(--navbar-h, 60px); + height: calc(100dvh - var(--navbar-h, 60px)); + align-self: start; + overflow: auto; + border-right: .5px solid var(--bs-border-color); + transform: none !important; + visibility: visible !important; + } +} + +/* ───────────────────────────────────────────────────────────── + NAVIGATION SECTIONS +────────────────────────────────────────────────────────────── */ +.side-section { + margin: .6rem 0 1rem; +} + +.side-hd { + font-size: .78rem; + font-weight: 800; + letter-spacing: .03em; + text-transform: uppercase; + color: var(--bs-secondary-color); + padding: .25rem .5rem; + margin: 0 0 .35rem .25rem; +} + +.side-nav { + display: flex; + flex-direction: column; + gap: .15rem; +} + +/* ───────────────────────────────────────────────────────────── + NAV LINKS +────────────────────────────────────────────────────────────── */ +.side-nav .nav-link { + position: relative; + display: flex; + align-items: center; + gap: .6rem; + padding: .48rem .55rem; + border-radius: 12px; + color: var(--bs-body-color); + text-decoration: none; + border: 0; + background: transparent !important; + line-height: 1.15; + transition: background .15s ease, color .15s ease, transform .05s ease, box-shadow .15s ease; + outline: none; +} + +/* мягкий ховер */ +.side-nav .nav-link:hover { + color: var(--bs-primary); + background: color-mix(in srgb, var(--bs-primary) 10%, transparent); +} + +/* видимая клавиатурная фокусировка */ +.side-nav .nav-link:focus-visible { + box-shadow: 0 0 0 2px rgba(var(--bs-primary-rgb), .25); +} + +/* активная «пилюля» + тонкий индикатор слева */ +.side-nav .nav-link.active { + color: var(--bs-primary); + font-weight: 800; + background: color-mix(in srgb, var(--bs-primary) 16%, transparent); +} + +.side-nav .nav-link.active::before { + content: ""; + position: absolute; + left: -6px; + top: 8px; + bottom: 8px; + width: 3px; + border-radius: 2px; + background: var(--bs-primary); +} + +/* «отключённый» пункт выглядит реально disabled */ +.side-nav .nav-link.disabled { + opacity: .5; + pointer-events: none; +} + +/* ───────────────────────────────────────────────────────────── + ICONS & BADGES +────────────────────────────────────────────────────────────── */ +.side-icon { + width: 1.35rem; + height: 1.35rem; + display: inline-grid; + place-items: center; + flex: 0 0 auto; +} + +.side-icon > i { + font-size: 1.1rem; + line-height: 1; +} + +.icon-wrap { + position: relative; + display: inline-grid; + place-items: center; +} + +.nav-unread { + position: absolute; + top: -4px; + right: -8px; + min-width: 16px; + height: 16px; + padding: 0 4px; + border-radius: 9999px; + font-size: 10px; + line-height: 16px; + font-weight: 700; + background: var(--bs-danger); + color: #fff; + border: 1px solid rgba(255, 255, 255, .6); +} + +[data-bs-theme="dark"] .nav-unread { + border-color: rgba(0, 0, 0, .25); +} + +/* ───────────────────────────────────────────────────────────── + THEME SWITCHER BUTTON +────────────────────────────────────────────────────────────── */ +.btn-theme { + display: inline-flex; + align-items: center; + gap: .5rem; + min-height: 36px; + padding: .35rem .75rem; + border-radius: 999px; + background: var(--bs-tertiary-bg); + color: var(--bs-body-color); + border: 1px solid var(--bs-border-color); + transition: transform .08s ease, background-color .25s ease, border-color .25s ease; +} + +.btn-theme:hover { + transform: translateY(-1px); + background: color-mix(in srgb, var(--bs-tertiary-bg) 90%, var(--bs-primary) 10%); + border-color: color-mix(in srgb, var(--bs-border-color), var(--bs-primary) 30%); +} + +.btn-theme:focus-visible { + outline: 0; + box-shadow: 0 0 0 2px rgba(var(--bs-primary-rgb), .25); +} + +.btn-theme .bi { + font-size: 1rem; + line-height: 1; +} + +.btn-theme .mode-label { + font-weight: 700; + font-size: .85rem; + opacity: .9; +} + +@media (max-width: 576px) { + .btn-theme .mode-label { + display: none; + } +} diff --git a/backend/templates/includes/navbar.html b/backend/templates/includes/navbar.html index 9e684290..1785444d 100644 --- a/backend/templates/includes/navbar.html +++ b/backend/templates/includes/navbar.html @@ -1,25 +1,5 @@ {% load static %} - +