UI: compact sidebar, dashboard header with nav, expanded hero text

- Sidebar: smaller icons (36px), reduced gaps, overflow scroll for nav area
- Dashboard header: fixed top bar with logo, nav links, user name, logout
- Expanded hero description with tool overview text
- Sidebar fits on all screen heights without overflow
This commit is contained in:
treamz 2026-03-21 23:34:03 +03:00
parent 44c85f6e44
commit 90e318b245
3 changed files with 58 additions and 13 deletions

View File

@ -10,6 +10,24 @@
<link href="/vendor/fonts.css" rel="stylesheet"> <link href="/vendor/fonts.css" rel="stylesheet">
<link href="/shared.css" rel="stylesheet"> <link href="/shared.css" rel="stylesheet">
<style> <style>
/* Dashboard header */
.dash-header { position:fixed; top:0; left:56px; right:0; height:52px; background:var(--surface-800); border-bottom:1px solid var(--surface-600); display:flex; align-items:center; padding:0 24px; z-index:40; backdrop-filter:blur(12px); }
.dash-logo { font-size:16px; font-weight:800; color:var(--text-primary); text-decoration:none; display:flex; align-items:center; gap:8px; flex-shrink:0; }
.dash-logo span { color:var(--accent); }
.dash-nav { display:flex; align-items:center; gap:4px; margin-left:28px; }
.dash-nav-link { font-size:13px; color:var(--text-muted); text-decoration:none; padding:6px 12px; border-radius:8px; transition:all .15s; font-weight:500; }
.dash-nav-link:hover { color:var(--text-secondary); background:rgba(255,255,255,.04); }
.dash-nav-link.active { color:var(--accent); background:var(--accent-bg); }
.dash-right { margin-left:auto; display:flex; align-items:center; gap:12px; }
.dash-user { font-size:13px; color:var(--text-muted); font-family:'JetBrains Mono',monospace; }
.dash-logout { color:var(--text-muted); transition:color .15s; }
.dash-logout:hover { color:var(--danger, #ff5252); }
@media(max-width:768px) {
.dash-header { left:0; }
.dash-nav { display:none; }
.dash-logo svg { display:none; }
}
@keyframes fadeUp { from { opacity:0; transform:translateY(12px); } to { opacity:1; transform:translateY(0); } } @keyframes fadeUp { from { opacity:0; transform:translateY(12px); } to { opacity:1; transform:translateY(0); } }
.fade-up { animation: fadeUp .4s ease-out forwards; } .fade-up { animation: fadeUp .4s ease-out forwards; }
.fade-d1 { animation: fadeUp .4s ease-out .05s forwards; opacity:0; } .fade-d1 { animation: fadeUp .4s ease-out .05s forwards; opacity:0; }
@ -48,15 +66,38 @@
</head> </head>
<body class="font-sans antialiased"> <body class="font-sans antialiased">
<!-- Top header -->
<header class="dash-header">
<a href="/dashboard" class="dash-logo">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5"/></svg>
WA Dev <span>Tools</span>
</a>
<nav class="dash-nav">
<a href="/dashboard" class="dash-nav-link active">Инструменты</a>
<a href="/compress" class="dash-nav-link">Сжатие</a>
<a href="/video" class="dash-nav-link">Видео</a>
<a href="/httpclient" class="dash-nav-link">HTTP</a>
</nav>
<div class="dash-right">
<span class="dash-user" id="headerUser"></span>
<a href="/auth/logout" class="dash-logout" title="Выйти">
<svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15m3 0l3-3m0 0l-3-3m3 3H9"/></svg>
</a>
</div>
</header>
<div class="main-content"> <div class="main-content">
<div class="tool-container relative z-10 max-w-5xl mx-auto"> <div class="tool-container relative z-10 max-w-5xl mx-auto" style="padding-top:72px;">
<!-- Greeting --> <!-- Greeting -->
<div class="fade-up" style="margin-bottom:28px;"> <div class="fade-up" style="margin-bottom:28px;">
<h1 style="font-size:1.75rem;font-weight:800;color:var(--text-primary);letter-spacing:-0.025em;" id="greeting"> <h1 style="font-size:1.75rem;font-weight:800;color:var(--text-primary);letter-spacing:-0.025em;" id="greeting">
Добро пожаловать Добро пожаловать
</h1> </h1>
<p style="font-size:13px;color:var(--text-muted);margin-top:6px;font-family:'JetBrains Mono',monospace;">Выберите инструмент для работы</p> <p style="font-size:14px;color:var(--text-secondary);margin-top:8px;line-height:1.6;max-width:600px;">
14 бесплатных инструментов для веб-разработки: сжатие картинок и видео,
форматирование кода, тестирование API, генерация паролей и многое другое.
</p>
</div> </div>
<!-- Category: Images --> <!-- Category: Images -->
@ -188,11 +229,14 @@
</div> </div>
<script> <script>
// Personalized greeting // Personalized greeting + header user
fetch('/auth/me').then(r => r.ok ? r.json() : null).then(user => { fetch('/auth/me').then(r => r.ok ? r.json() : null).then(user => {
if (!user) return; if (!user) return;
const name = user.name || user.email.split('@')[0];
const el = document.getElementById('greeting'); const el = document.getElementById('greeting');
if (el) el.textContent = 'Привет, ' + (user.name || user.email.split('@')[0]); if (el) el.textContent = 'Привет, ' + name;
const hu = document.getElementById('headerUser');
if (hu) hu.textContent = name;
}).catch(() => {}); }).catch(() => {});
</script> </script>
</body> </body>

View File

@ -46,21 +46,22 @@ body {
} }
/* Sidebar */ /* Sidebar */
.sidebar { position:fixed;top:0;left:0;width:56px;height:100vh;display:flex;flex-direction:column;align-items:center;padding:16px 0 12px;z-index:50;border-right:1px solid var(--surface-600);background:var(--surface-800);backdrop-filter:blur(12px);transition:background .3s,border-color .3s } .sidebar { position:fixed;top:0;left:0;width:56px;height:100vh;display:flex;flex-direction:column;align-items:center;padding:10px 0 8px;z-index:50;border-right:1px solid var(--surface-600);background:var(--surface-800);backdrop-filter:blur(12px);transition:background .3s,border-color .3s }
.sidebar-logo { margin-bottom:24px;color:var(--text-muted);font-size:10px;font-weight:700;letter-spacing:.08em;font-family:'JetBrains Mono',monospace } .sidebar-logo { margin-bottom:12px;color:var(--text-muted);font-size:10px;font-weight:700;letter-spacing:.08em;font-family:'JetBrains Mono',monospace;flex-shrink:0 }
.sidebar-nav { display:flex;flex-direction:column;gap:6px;flex:1 } .sidebar-nav { display:flex;flex-direction:column;gap:3px;flex:1;overflow-y:auto;overflow-x:hidden;scrollbar-width:none;-ms-overflow-style:none;padding:2px 0 }
.sidebar-link { width:40px;height:40px;border-radius:10px;display:flex;align-items:center;justify-content:center;color:var(--text-muted);transition:all .2s;text-decoration:none;position:relative } .sidebar-nav::-webkit-scrollbar { display:none }
.sidebar-link { width:36px;height:36px;border-radius:8px;display:flex;align-items:center;justify-content:center;color:var(--text-muted);transition:all .2s;text-decoration:none;position:relative;flex-shrink:0 }
.sidebar-link:hover { color:var(--text-secondary);background:rgba(255,255,255,.04) } .sidebar-link:hover { color:var(--text-secondary);background:rgba(255,255,255,.04) }
.sidebar-link.active { color:var(--accent);background:var(--accent-bg) } .sidebar-link.active { color:var(--accent);background:var(--accent-bg) }
.sidebar-link.active::before { content:'';position:absolute;left:-8px;top:50%;transform:translateY(-50%);width:3px;height:20px;border-radius:0 3px 3px 0;background:var(--accent) } .sidebar-link.active::before { content:'';position:absolute;left:-8px;top:50%;transform:translateY(-50%);width:3px;height:16px;border-radius:0 3px 3px 0;background:var(--accent) }
.sidebar-bottom { margin-top:auto;display:flex;flex-direction:column;align-items:center;gap:8px } .sidebar-bottom { margin-top:auto;display:flex;flex-direction:column;align-items:center;gap:6px;flex-shrink:0;padding-top:6px }
.main-content { margin-left:56px } .main-content { margin-left:56px }
/* Sidebar dividers */ /* Sidebar dividers */
.sidebar-divider { width:24px;height:1px;background:var(--surface-600);margin:4px 0 } .sidebar-divider { width:20px;height:1px;background:var(--surface-600);margin:2px 0;flex-shrink:0 }
/* Sidebar user avatar */ /* Sidebar user avatar */
.sidebar-avatar { width:32px;height:32px;border-radius:50%;background:var(--accent);color:#fff;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;font-family:'Manrope',sans-serif;cursor:pointer;transition:opacity .2s } .sidebar-avatar { width:30px;height:30px;border-radius:50%;background:var(--accent);color:#fff;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;font-family:'Manrope',sans-serif;cursor:pointer;transition:opacity .2s }
.sidebar-avatar:hover { opacity:.8 } .sidebar-avatar:hover { opacity:.8 }
/* Theme toggle */ /* Theme toggle */

View File

@ -55,7 +55,7 @@ const WA_TOOLS = [
/* Build sidebar SVG icon */ /* Build sidebar SVG icon */
function _svgIcon(innerPath) { function _svgIcon(innerPath) {
return `<svg width="22" height="22" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">${innerPath}</svg>`; return `<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">${innerPath}</svg>`;
} }
/* Inject sidebar into the page */ /* Inject sidebar into the page */