feat(ui): adattamento mobile responsive
- Hamburger button (☰) nell'header per aprire sidebar - Sidebar come drawer overlay su mobile (<768px) - Sidebar backdrop con chiusura al tap - Swipe a sinistra per chiudere sidebar - Safe-area per iPhone notch - Font-size 16px su input (previene zoom iOS) - dvh per altezza viewport mobile - Auto-focus input solo su desktop
This commit is contained in:
1 parent
886df7429f
commit
33ba2a78b2
1 file changed
+124
-2
+124
-2
@@ -621,6 +621,103 @@ html, body {
|
||||
margin-right: 12px;
|
||||
}
|
||||
@keyframes spin { to { transform: rotate(360deg); } }
|
||||
|
||||
/* Hamburger menu button */
|
||||
#btn-menu {
|
||||
display: none;
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-secondary);
|
||||
font-size: 22px;
|
||||
cursor: pointer;
|
||||
padding: 4px 6px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* Sidebar backdrop (mobile) */
|
||||
#sidebar-backdrop {
|
||||
display: none;
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0,0,0,0.5);
|
||||
z-index: 8;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
Mobile Responsive
|
||||
============================================================ */
|
||||
@media (max-width: 768px) {
|
||||
#btn-menu { display: block; }
|
||||
|
||||
#sidebar {
|
||||
position: fixed;
|
||||
left: -320px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 300px;
|
||||
min-width: 300px;
|
||||
z-index: 9;
|
||||
transition: left 0.25s ease;
|
||||
box-shadow: 4px 0 20px rgba(0,0,0,0.5);
|
||||
}
|
||||
#sidebar.open { left: 0; }
|
||||
#sidebar-backdrop.open { display: block; }
|
||||
|
||||
#app { flex-direction: column; }
|
||||
#main {
|
||||
width: 100%;
|
||||
height: 100dvh;
|
||||
}
|
||||
|
||||
#header {
|
||||
padding: 0 12px;
|
||||
gap: 10px;
|
||||
min-height: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
#header h1 { font-size: 14px; letter-spacing: 1px; }
|
||||
#header .turn-badge { font-size: 11px; }
|
||||
|
||||
#chat {
|
||||
padding: 12px;
|
||||
gap: 10px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
#input-area {
|
||||
padding: 8px 10px;
|
||||
padding-bottom: max(8px, env(safe-area-inset-bottom));
|
||||
}
|
||||
#input-area input {
|
||||
font-size: 16px; /* prevent zoom on iOS */
|
||||
padding: 10px 12px;
|
||||
}
|
||||
#btn-send {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
/* Welcome screen */
|
||||
#welcome h1 { font-size: 28px; }
|
||||
#welcome .subtitle { font-size: 14px; }
|
||||
.camp-list { max-width: 100%; padding: 0 12px; }
|
||||
#new-camp-form { width: 100%; max-width: 100%; padding: 0 12px; }
|
||||
|
||||
/* Sidebar content */
|
||||
.sidebar-section { padding: 10px 12px; }
|
||||
.sidebar-section h2 { font-size: 10px; }
|
||||
.char-name { font-size: 14px; }
|
||||
.stat-grid { gap: 3px; }
|
||||
.stat-row { font-size: 12px; }
|
||||
.area-item { font-size: 12px; }
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
#sidebar { width: 260px; min-width: 260px; left: -260px; }
|
||||
#header h1 { font-size: 12px; }
|
||||
.msg-bubble { font-size: 14px; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -651,7 +748,7 @@ html, body {
|
||||
<div id="area-display"><div class="empty-state">Nessuna area</div></div>
|
||||
</div>
|
||||
<div class="sidebar-section" id="dm-section">
|
||||
<h2 class="dm-toggle" onclick="toggleDM()">DM ◥</h2>
|
||||
<h2 class="dm-toggle" onclick="toggleDM()">DM +</h2>
|
||||
<div id="dm-panel" class="dm-panel hidden">
|
||||
<select id="dm-cmd" onchange="onDMCommand()">
|
||||
<option value="narrate">Narrate (testo)</option>
|
||||
@@ -666,10 +763,12 @@ html, body {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="sidebar-backdrop" class="hidden" onclick="toggleSidebar()"></div>
|
||||
|
||||
<!-- MAIN -->
|
||||
<div id="main">
|
||||
<div id="header">
|
||||
<button id="btn-menu" onclick="toggleSidebar()">☰</button>
|
||||
<div id="conn-indicator" class="conn-status disconnected"></div>
|
||||
<h1>Tomba del Mago Guerriero</h1>
|
||||
<div class="turn-badge">Turno <span id="turn-counter">0</span></div>
|
||||
@@ -802,7 +901,7 @@ function connectWS() {
|
||||
connIndicator.className = 'conn-status connected';
|
||||
input.disabled = false;
|
||||
btnSend.disabled = false;
|
||||
input.focus();
|
||||
if (window.innerWidth > 768) input.focus();
|
||||
if (reconnectTimer) { clearInterval(reconnectTimer); reconnectTimer = null; }
|
||||
};
|
||||
|
||||
@@ -953,6 +1052,29 @@ function renderAreas(areas) {
|
||||
}).join('');
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// Mobile sidebar
|
||||
// ================================================================
|
||||
function toggleSidebar() {
|
||||
const sb = document.getElementById('sidebar');
|
||||
const backdrop = document.getElementById('sidebar-backdrop');
|
||||
const open = !sb.classList.contains('open');
|
||||
sb.classList.toggle('open', open);
|
||||
backdrop.classList.toggle('open', open);
|
||||
backdrop.classList.toggle('hidden', !open);
|
||||
}
|
||||
|
||||
// Close sidebar when swiping left on mobile
|
||||
let touchStartX = 0;
|
||||
document.addEventListener('touchstart', e => { touchStartX = e.touches[0].clientX; });
|
||||
document.addEventListener('touchend', e => {
|
||||
const sb = document.getElementById('sidebar');
|
||||
if (!sb.classList.contains('open')) return;
|
||||
const dx = touchStartX - e.changedTouches[0].clientX;
|
||||
if (dx > 80) toggleSidebar();
|
||||
});
|
||||
|
||||
|
||||
// ================================================================
|
||||
// DM Override
|
||||
// ================================================================
|
||||
|
||||
Reference in new issue
Block a user