feat(ui): mobile mesh tabs, AIUI-style audio player, cloud grid + map fixes
UI (this session): - Global audio player now scales the whole interface into the space above it on desktop (sidebar + main) and docks directly above the tab bar on mobile; it stays visible while navigating. - Mesh mobile redesign: floating Chat / BTC / Dead Man / AI / Map tab strip with a single fixed, internally-scrolling pane (page no longer scrolls); tabs hide while a conversation is open; floating back button; collapsible Device panel (starts collapsed); keyboard-aware conversation sizing via VisualViewport so the chat sits just above the keyboard. - Cloud file grid: uniform 4/3 card heights (folders + images match). - Swipe left/right switches tabs on the Apps and Web5 screens. - Map tool fills its pane (no bottom gap); fix skewed Share Location toggle on mobile (global min-height rule was deforming the switch). - Trim redundant helper copy from the mesh AI tab. Also bundles pre-existing in-progress work that was already in the tree: mesh listener/session + wallet + container + bitcoin-status backend changes, docker UI updates, and assorted other UI tweaks. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
c4855526fe
commit
1bce694ebb
+38
-10
@@ -130,19 +130,45 @@ select:focus-visible {
|
||||
}
|
||||
}
|
||||
|
||||
/* Scroll container bottom padding — desktop breathing room */
|
||||
/* Height of the global audio player bar — 0 unless it is visible. Set on
|
||||
<html> by GlobalAudioPlayer.vue. Scroll containers add it to their bottom
|
||||
padding so the fixed player pushes content up instead of covering it. */
|
||||
:root {
|
||||
--audio-player-height: 0px;
|
||||
}
|
||||
|
||||
/* Scroll container bottom padding — desktop breathing room. (On desktop the
|
||||
audio player instead shrinks the whole #main-content area — see the
|
||||
html.audio-active rule below — so no player offset is added here.) */
|
||||
.mobile-scroll-pad,
|
||||
.mobile-scroll-pad-back {
|
||||
padding-bottom: 6rem;
|
||||
}
|
||||
|
||||
/* Audio player docked: shrink the whole interface into the space above it so
|
||||
the entire view scales up (like the AIUI iframe) instead of just gaining
|
||||
scroll padding. On desktop the player spans full width and BOTH the sidebar
|
||||
and the main content scale into the reduced height above it. Mobile keeps the
|
||||
tab-bar + player handled via .mobile-scroll-pad padding. */
|
||||
@media (min-width: 768px) {
|
||||
html.audio-active .dashboard-view {
|
||||
height: calc(100dvh - var(--audio-player-height, 0px));
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
/* Sidebar uses h-screen (100vh) — pin it to the reduced container height. */
|
||||
html.audio-active .dashboard-view [data-controller-zone="sidebar"] {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile: override with tab bar clearance */
|
||||
@media (max-width: 767px) {
|
||||
.mobile-scroll-pad {
|
||||
padding-bottom: calc(var(--mobile-tab-bar-height, 88px) + var(--safe-area-bottom, env(safe-area-inset-bottom, 0px)) + 16px);
|
||||
padding-bottom: calc(var(--mobile-tab-bar-height, 88px) + var(--safe-area-bottom, env(safe-area-inset-bottom, 0px)) + var(--audio-player-height, 0px) + 16px);
|
||||
}
|
||||
.mobile-scroll-pad-back {
|
||||
padding-bottom: calc(var(--mobile-tab-bar-height, 88px) + var(--safe-area-bottom, env(safe-area-inset-bottom, 0px)) + 64px);
|
||||
padding-bottom: calc(var(--mobile-tab-bar-height, 88px) + var(--safe-area-bottom, env(safe-area-inset-bottom, 0px)) + var(--audio-player-height, 0px) + 64px);
|
||||
}
|
||||
|
||||
/* Safe area top padding for all mobile content views.
|
||||
@@ -174,11 +200,11 @@ select:focus-visible {
|
||||
}
|
||||
|
||||
.mobile-scroll-pad {
|
||||
padding-bottom: calc(var(--mobile-tab-bar-height, 88px) + var(--safe-area-bottom, env(safe-area-inset-bottom, 0px)) + 16px);
|
||||
padding-bottom: calc(var(--mobile-tab-bar-height, 88px) + var(--safe-area-bottom, env(safe-area-inset-bottom, 0px)) + var(--audio-player-height, 0px) + 16px);
|
||||
}
|
||||
|
||||
.mobile-scroll-pad-back {
|
||||
padding-bottom: calc(var(--mobile-tab-bar-height, 88px) + var(--safe-area-bottom, env(safe-area-inset-bottom, 0px)) + 64px);
|
||||
padding-bottom: calc(var(--mobile-tab-bar-height, 88px) + var(--safe-area-bottom, env(safe-area-inset-bottom, 0px)) + var(--audio-player-height, 0px) + 64px);
|
||||
}
|
||||
|
||||
.mobile-safe-top {
|
||||
@@ -525,6 +551,7 @@ input[type="radio"]:active + * {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
/* On mobile browsers, cap chat height to the dynamic viewport to prevent
|
||||
content extending behind browser chrome (address bar / toolbar). */
|
||||
@media (max-width: 767px) {
|
||||
@@ -555,8 +582,8 @@ input[type="radio"]:active + * {
|
||||
context) stay above the tab bar instead of sliding underneath it. */
|
||||
@media (max-width: 767px) {
|
||||
.chat-iframe-mobile {
|
||||
height: calc(100vh - var(--mobile-tab-bar-height, 72px) - var(--safe-area-top, env(safe-area-inset-top, 0px)) - 16px) !important;
|
||||
height: calc(100dvh - var(--mobile-tab-bar-height, 72px) - var(--safe-area-top, env(safe-area-inset-top, 0px)) - 16px) !important;
|
||||
height: calc(100vh - var(--mobile-tab-bar-height, 72px) - var(--safe-area-top, env(safe-area-inset-top, 0px)) - var(--audio-player-height, 0px) - 16px) !important;
|
||||
height: calc(100dvh - var(--mobile-tab-bar-height, 72px) - var(--safe-area-top, env(safe-area-inset-top, 0px)) - var(--audio-player-height, 0px) - 16px) !important;
|
||||
flex: none;
|
||||
}
|
||||
}
|
||||
@@ -1926,18 +1953,19 @@ html.modal-scroll-locked .dashboard-scroll-panel {
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
/* ── Mobile floating back/close button (always 8px above tab bar) ──── */
|
||||
/* ── Mobile floating back/close button (always 8px above tab bar — and above
|
||||
the audio player too when it is showing, so it never hides behind it) ── */
|
||||
.mobile-back-btn {
|
||||
position: fixed;
|
||||
left: 1rem;
|
||||
right: 1rem;
|
||||
bottom: calc(var(--mobile-tab-bar-height, 72px) + 8px);
|
||||
bottom: calc(var(--mobile-tab-bar-height, 72px) + var(--audio-player-height, 0px) + 8px);
|
||||
z-index: 40;
|
||||
filter: drop-shadow(0 10px 25px rgba(0, 0, 0, 0.5));
|
||||
}
|
||||
|
||||
.mobile-filter-btn {
|
||||
bottom: calc(var(--mobile-tab-bar-height, 72px) + var(--safe-area-bottom, env(safe-area-inset-bottom, 0px)) + 12px);
|
||||
bottom: calc(var(--mobile-tab-bar-height, 72px) + var(--safe-area-bottom, env(safe-area-inset-bottom, 0px)) + var(--audio-player-height, 0px) + 12px);
|
||||
filter: drop-shadow(0 10px 25px rgba(0, 0, 0, 0.5));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user