Skip to content

Commit 1532738

Browse files
committed
feat: add mobile responsive layout with collapsible sidebar
- Sidebar becomes a slide-out panel on screens < 768px with hamburger toggle - Avatar grid switches to horizontal scroll on mobile - Video container fills full width - Input bar fixed to bottom with safe-area padding - Overlay backdrop for sidebar dismiss - Auto-close sidebar on avatar selection
1 parent 7f0a08b commit 1532738

3 files changed

Lines changed: 128 additions & 3 deletions

File tree

static/app.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,35 @@ ta.addEventListener("keydown", (e) => {
275275
});
276276
$("#send-btn").addEventListener("click", generate);
277277

278+
// Hamburger menu (mobile)
279+
(() => {
280+
const hamburger = $("#hamburger");
281+
const sidebar = $("#sidebar");
282+
const overlay = $("#sidebar-overlay");
283+
if (!hamburger || !sidebar) return;
284+
285+
function openSidebar() {
286+
sidebar.classList.add("open");
287+
overlay.classList.add("open");
288+
}
289+
function closeSidebar() {
290+
sidebar.classList.remove("open");
291+
overlay.classList.remove("open");
292+
}
293+
294+
hamburger.addEventListener("click", () => {
295+
sidebar.classList.contains("open") ? closeSidebar() : openSidebar();
296+
});
297+
overlay.addEventListener("click", closeSidebar);
298+
299+
// Close sidebar when avatar is selected (mobile convenience)
300+
document.addEventListener("click", (e) => {
301+
if (e.target.closest(".avatar-card") && window.innerWidth < 768) {
302+
setTimeout(closeSidebar, 150);
303+
}
304+
});
305+
})();
306+
278307
// Init
279308
(async () => {
280309
await loadVoices();

static/index.html

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,17 @@
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<title>数字人直播</title>
7-
<link rel="stylesheet" href="style.css?v=8">
7+
<link rel="stylesheet" href="style.css?v=9">
88
<link rel="preconnect" href="https://fonts.googleapis.com">
99
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;600&display=swap" rel="stylesheet">
1010
</head>
1111
<body>
1212
<div class="app">
13-
<aside class="sidebar">
13+
<button id="hamburger" class="hamburger" aria-label="菜单">
14+
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
15+
</button>
16+
<div id="sidebar-overlay" class="sidebar-overlay"></div>
17+
<aside class="sidebar" id="sidebar">
1418
<div class="logo">
1519
<div class="logo-icon">
1620
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="5"/><path d="M20 21a8 8 0 0 0-16 0"/></svg>
@@ -86,6 +90,6 @@
8690

8791
<div id="toast" class="toast hidden"></div>
8892

89-
<script src="app.js?v=8"></script>
93+
<script src="app.js?v=9"></script>
9094
</body>
9195
</html>

static/style.css

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,3 +371,95 @@ body {
371371
transform: translateX(-50%) translateY(0);
372372
}
373373
.toast.hidden { display: none; }
374+
375+
/* ── Hamburger (hidden on desktop) ── */
376+
.hamburger {
377+
display: none;
378+
position: fixed;
379+
top: 12px; left: 12px;
380+
z-index: 200;
381+
width: 40px; height: 40px;
382+
background: var(--bg-card);
383+
border: 1px solid var(--border);
384+
border-radius: 10px;
385+
cursor: pointer;
386+
align-items: center; justify-content: center;
387+
box-shadow: var(--shadow2);
388+
color: var(--accent);
389+
transition: background 0.15s;
390+
}
391+
.hamburger:hover { background: var(--accent-light); }
392+
393+
.sidebar-overlay {
394+
display: none;
395+
position: fixed; inset: 0;
396+
background: rgba(0,0,0,0.3);
397+
z-index: 99;
398+
}
399+
400+
/* ── Mobile ── */
401+
@media (max-width: 767px) {
402+
.hamburger { display: flex; }
403+
404+
.app { flex-direction: column; height: 100vh; }
405+
406+
.sidebar {
407+
position: fixed;
408+
top: 0; left: 0;
409+
width: 280px;
410+
height: 100vh;
411+
z-index: 100;
412+
transform: translateX(-100%);
413+
transition: transform 0.25s ease;
414+
overflow-y: auto;
415+
padding-top: 56px;
416+
}
417+
.sidebar.open {
418+
transform: translateX(0);
419+
}
420+
.sidebar-overlay.open {
421+
display: block;
422+
}
423+
424+
.avatar-grid {
425+
display: flex;
426+
flex-wrap: nowrap;
427+
overflow-x: auto;
428+
overflow-y: hidden;
429+
max-height: none;
430+
gap: 8px;
431+
padding: 4px 2px;
432+
-webkit-overflow-scrolling: touch;
433+
}
434+
.avatar-card {
435+
flex: 0 0 68px;
436+
min-width: 68px;
437+
}
438+
439+
.main {
440+
flex: 1;
441+
min-height: 0;
442+
padding-top: 48px;
443+
}
444+
445+
.tabs { padding: 8px 14px 0; }
446+
447+
.stage {
448+
padding: 12px 14px;
449+
justify-content: flex-start;
450+
}
451+
452+
.video-wrap { max-width: 100%; min-height: 200px; }
453+
454+
.input-bar {
455+
position: fixed;
456+
bottom: 0; left: 0; right: 0;
457+
padding: 10px 12px calc(env(safe-area-inset-bottom, 8px) + 8px);
458+
background: var(--bg-sidebar);
459+
border-top: 1px solid var(--border);
460+
z-index: 50;
461+
}
462+
.input-bar textarea { max-width: none; flex: 1; }
463+
464+
.llm-box, .samples { max-width: 100%; }
465+
}

0 commit comments

Comments
 (0)