diff --git a/neode-ui/src/views/dashboard/DashboardMobileNav.vue b/neode-ui/src/views/dashboard/DashboardMobileNav.vue index 285bcd64..d6721dad 100644 --- a/neode-ui/src/views/dashboard/DashboardMobileNav.vue +++ b/neode-ui/src/views/dashboard/DashboardMobileNav.vue @@ -188,9 +188,17 @@ defineExpose({ function updateTabBarHeight() { if (typeof window === 'undefined') return - if (mobileTabBar.value) { - const height = mobileTabBar.value.offsetHeight - document.documentElement.style.setProperty('--mobile-tab-bar-height', `${height}px`) + const el = mobileTabBar.value + // offsetHeight is 0 when the bar is hidden (desktop `md:hidden`) or not yet + // laid out. Writing `--mobile-tab-bar-height: 0px` would DEFEAT the `, 88px` + // fallback baked into the `.mobile-scroll-pad` clearance calc (an explicit + // 0px is still "set"), so the fixed tab bar ends up covering the last row of + // content — the Cloud/files "bottom elements cut off" bug. Only write a real + // measured height; otherwise remove the var so the fallback applies. + if (el && el.offsetHeight > 0) { + document.documentElement.style.setProperty('--mobile-tab-bar-height', `${el.offsetHeight}px`) + } else { + document.documentElement.style.removeProperty('--mobile-tab-bar-height') } } @@ -201,10 +209,15 @@ function onResize() { onMounted(() => { updateTabBarHeight() + // Re-measure after the first paint: on mount the bar may not have its final + // laid-out height yet (fonts/safe-area padding still settling), which would + // leave the clearance var short. + requestAnimationFrame(updateTabBarHeight) readSafeAreaTop() window.addEventListener('resize', onResize) - // Re-read after WebView injection has had time to run - setTimeout(readSafeAreaTop, 500) + // Re-read after WebView injection has had time to run. The injected + // safe-area-bottom padding changes the bar's height, so re-measure too. + setTimeout(() => { readSafeAreaTop(); updateTabBarHeight() }, 500) }) onBeforeUnmount(() => {