Add a mobile-responsive layout and mirrored call controls
- Sidebar (channel list + nickname) becomes an off-canvas drawer below 860px, opened via a new fixed top bar (hamburger + live status) and closed by tapping the backdrop or picking a channel. - Mic/deafen/share get an always-visible bottom control bar so they're reachable mid-call without opening the drawer; updateMicButton/ updateDeafenButton and their click wiring now target both the sidebar and mirror buttons via shared NodeLists instead of single elements. - Per-user volume popup (previously hover-only) now also toggles on tap, and repositions below the row instead of to the side, which would overflow a narrow drawer. - Screen-share tiles stack full-width, touch targets are enlarged, and the spatial map panel shrinks to leave room for the stage. Also includes the working tree's prior swap of the spatial view from Konva to Cytoscape.js (drag, scroll-to-zoom, fit-to-view, distance edges) — not authored in this change, carried along since it was already uncommitted. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
664417c6da
commit
7795cf84a3
5 files changed
+467
-185
No files matched your search
+99
-6
@@ -218,7 +218,8 @@ body {
|
||||
z-index: 100;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.channel-user-item:hover .volume-popup {
|
||||
.channel-user-item:hover .volume-popup,
|
||||
.channel-user-item.show-vol .volume-popup {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
@@ -245,12 +246,36 @@ body {
|
||||
border-top: 1px solid rgba(0,0,0,.35); display: flex; flex-direction: column;
|
||||
}
|
||||
.spatial-label {
|
||||
padding: 8px 16px 0; font-size: 11px; font-weight: 700; color: var(--text-2);
|
||||
letter-spacing: .5px; display: flex; gap: 16px;
|
||||
padding: 8px 16px; font-size: 11px; font-weight: 700; color: var(--text-2);
|
||||
letter-spacing: .5px; display: flex; align-items: center; gap: 16px;
|
||||
}
|
||||
.spatial-label .hint { font-weight: 400; letter-spacing: 0; text-transform: none; flex: 1; }
|
||||
.spatial-action-btn {
|
||||
background: var(--bg-2);
|
||||
border: 1px solid var(--bg-4);
|
||||
color: var(--text-1);
|
||||
padding: 3px 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 11px;
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
transition: background 0.15s, color 0.15s;
|
||||
}
|
||||
.spatial-action-btn:hover {
|
||||
background: var(--bg-3);
|
||||
color: var(--text-0);
|
||||
}
|
||||
#spatial {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: radial-gradient(circle, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
|
||||
background-size: 24px 24px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.spatial-label .hint { font-weight: 400; letter-spacing: 0; text-transform: none; }
|
||||
#spatial { flex: 1; width: 100%; cursor: grab; touch-action: none; }
|
||||
#spatial.dragging { cursor: grabbing; }
|
||||
|
||||
/* modal */
|
||||
#modal-backdrop {
|
||||
@@ -391,3 +416,71 @@ body {
|
||||
|
||||
.hint { color: var(--text-2); font-size: 12px; }
|
||||
code { font-family: ui-monospace, monospace; font-size: 12px; }
|
||||
|
||||
/* mobile chrome — hidden on desktop, shown/positioned in the breakpoint below */
|
||||
#mobile-topbar, #sidebar-backdrop, #mobile-controls { display: none; }
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
mobile layout
|
||||
- rail is dropped (decorative only in this POC)
|
||||
- sidebar becomes an off-canvas drawer opened from #mobile-topbar
|
||||
- mic/deafen/share get an always-visible mirror bar pinned to the bottom
|
||||
--------------------------------------------------------------------------- */
|
||||
@media (max-width: 860px) {
|
||||
#app { padding-top: 48px; } /* room for the fixed topbar */
|
||||
#rail { display: none; }
|
||||
|
||||
#mobile-topbar {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
position: fixed; top: 0; left: 0; right: 0; height: 48px; z-index: 55;
|
||||
background: var(--bg-0); padding: 0 12px; box-shadow: 0 1px 0 rgba(0,0,0,.3);
|
||||
}
|
||||
#mobile-topbar button {
|
||||
background: transparent; border: none; color: var(--text-0); font-size: 20px;
|
||||
width: 36px; height: 36px; border-radius: 6px; cursor: pointer;
|
||||
}
|
||||
#mobile-topbar button:active { background: var(--bg-3); }
|
||||
#mobile-title { font-weight: 700; font-size: 14px; }
|
||||
#mobile-status-row {
|
||||
display: flex; align-items: center; gap: 5px; margin-left: auto;
|
||||
font-size: 12px; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
#sidebar-backdrop.show {
|
||||
display: block; position: fixed; inset: 0; top: 48px; z-index: 65; background: rgba(0,0,0,.55);
|
||||
}
|
||||
#sidebar {
|
||||
position: fixed; top: 48px; bottom: 0; left: 0; z-index: 66; width: 82vw; max-width: 320px;
|
||||
transform: translateX(-100%); transition: transform .2s ease; box-shadow: 8px 0 24px rgba(0,0,0,.5);
|
||||
}
|
||||
#sidebar.open { transform: translateX(0); }
|
||||
|
||||
#main { width: 100%; padding-bottom: 64px; } /* room for the fixed bottom controls */
|
||||
#stage { padding: 10px; gap: 10px; }
|
||||
#screens { flex-direction: column; }
|
||||
#screens .screen-card, #screens.multi .screen-card { flex: 1 1 auto; width: 100%; min-height: 220px; }
|
||||
|
||||
#spatial-wrap { height: 26vh; min-height: 160px; }
|
||||
.spatial-label { flex-wrap: wrap; gap: 6px; padding: 6px 10px; }
|
||||
.spatial-label .hint { display: none; } /* the drag/zoom hint doesn't fit — controls are still discoverable by touch */
|
||||
|
||||
/* bigger touch targets everywhere controls are tapped directly */
|
||||
.ctl { width: 40px; height: 40px; font-size: 18px; }
|
||||
|
||||
#mobile-controls {
|
||||
display: flex; justify-content: center; gap: 10px;
|
||||
position: fixed; bottom: 0; left: 0; right: 0; z-index: 55;
|
||||
background: var(--bg-0); padding: 8px; box-shadow: 0 -1px 0 rgba(0,0,0,.3);
|
||||
}
|
||||
#mobile-controls .ctl { width: 48px; height: 48px; font-size: 20px; background: var(--bg-2); }
|
||||
|
||||
/* volume popup: side placement would run off a narrow drawer */
|
||||
.volume-popup { left: 0; right: 0; top: 100%; transform: none; width: auto; margin-top: 4px; }
|
||||
|
||||
/* modals already clamp to 92vw; just tighten padding a bit */
|
||||
#settings-modal, #welcome-modal { padding: 16px; }
|
||||
|
||||
#mx-panel { width: 100vw; }
|
||||
|
||||
#toasts { left: 12px; right: 12px; max-width: none; }
|
||||
}
|
||||
Reference in new issue
Block a user