fix(layout): swap 100vh/h-screen for dvh so bottom navs survive browser chrome
In non-PWA browser tabs (especially iOS Safari), 100vh is the largest possible viewport — it doesn't shrink when the bottom URL bar slides in, so fixed-bottom navs get occluded. 100dvh tracks the dynamic viewport, so layouts reflow and nav stays clickable. Safe-area-inset-bottom padding on the navs themselves is already in place.
This commit is contained in:
parent
8303b0981b
commit
a2c4cfd955
19 changed files with 29 additions and 29 deletions
|
|
@ -26,8 +26,8 @@ async function handleLoginSuccess() {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen bg-background font-sans antialiased">
|
<div class="min-h-dvh bg-background font-sans antialiased">
|
||||||
<div class="relative flex min-h-screen flex-col"
|
<div class="relative flex min-h-dvh flex-col"
|
||||||
style="padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom)">
|
style="padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom)">
|
||||||
|
|
||||||
<div v-if="!isLoginPage && !isAuthenticated" class="fixed top-0 right-0 z-50 p-3" style="padding-top: env(safe-area-inset-top)">
|
<div v-if="!isLoginPage && !isAuthenticated" class="fixed top-0 right-0 z-50 p-3" style="padding-top: env(safe-area-inset-top)">
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,8 @@ async function handleLoginSuccess() {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen bg-background font-sans antialiased">
|
<div class="min-h-dvh bg-background font-sans antialiased">
|
||||||
<div class="relative flex min-h-screen flex-col"
|
<div class="relative flex min-h-dvh flex-col"
|
||||||
style="padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom)">
|
style="padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom)">
|
||||||
|
|
||||||
<!-- Top bar with login -->
|
<!-- Top bar with login -->
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,8 @@ async function handleLoginSuccess() {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen bg-background font-sans antialiased">
|
<div class="min-h-dvh bg-background font-sans antialiased">
|
||||||
<div class="relative flex min-h-screen flex-col"
|
<div class="relative flex min-h-dvh flex-col"
|
||||||
style="padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom)">
|
style="padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom)">
|
||||||
|
|
||||||
<!-- Main content (with bottom padding for nav bar) -->
|
<!-- Main content (with bottom padding for nav bar) -->
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@ async function handleLoginSuccess() {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen bg-background font-sans antialiased">
|
<div class="min-h-dvh bg-background font-sans antialiased">
|
||||||
<div class="relative flex min-h-screen flex-col"
|
<div class="relative flex min-h-dvh flex-col"
|
||||||
style="padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom)">
|
style="padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom)">
|
||||||
|
|
||||||
<div v-if="!isLoginPage && !isAuthenticated" class="fixed top-0 right-0 z-50 p-3" style="padding-top: env(safe-area-inset-top)">
|
<div v-if="!isLoginPage && !isAuthenticated" class="fixed top-0 right-0 z-50 p-3" style="padding-top: env(safe-area-inset-top)">
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ const openSidebar = () => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen bg-background">
|
<div class="min-h-dvh bg-background">
|
||||||
<!-- Mobile Drawer -->
|
<!-- Mobile Drawer -->
|
||||||
<MobileDrawer v-model:open="sidebarOpen" />
|
<MobileDrawer v-model:open="sidebarOpen" />
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,8 @@ async function handleLoginSuccess() {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen bg-background font-sans antialiased">
|
<div class="min-h-dvh bg-background font-sans antialiased">
|
||||||
<div class="relative flex min-h-screen flex-col"
|
<div class="relative flex min-h-dvh flex-col"
|
||||||
style="padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom)">
|
style="padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom)">
|
||||||
|
|
||||||
<div v-if="!isLoginPage && !isAuthenticated" class="fixed top-0 right-0 z-50 p-3" style="padding-top: env(safe-area-inset-top)">
|
<div v-if="!isLoginPage && !isAuthenticated" class="fixed top-0 right-0 z-50 p-3" style="padding-top: env(safe-area-inset-top)">
|
||||||
|
|
|
||||||
|
|
@ -69,8 +69,8 @@ async function handleLoginSuccess() {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen bg-background font-sans antialiased">
|
<div class="min-h-dvh bg-background font-sans antialiased">
|
||||||
<div class="relative flex min-h-screen flex-col"
|
<div class="relative flex min-h-dvh flex-col"
|
||||||
style="padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom)">
|
style="padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom)">
|
||||||
|
|
||||||
<main class="flex-1" :class="{ 'pb-16': !isLoginPage }">
|
<main class="flex-1" :class="{ 'pb-16': !isLoginPage }">
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ onMounted(() => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col h-[calc(100vh-3.5rem)]">
|
<div class="flex flex-col h-[calc(100dvh-3.5rem)]">
|
||||||
<!-- Loading overlay -->
|
<!-- Loading overlay -->
|
||||||
<div v-if="isLoading && geoActivities.length === 0" class="flex-1 flex items-center justify-center">
|
<div v-if="isLoading && geoActivities.length === 0" class="flex-1 flex items-center justify-center">
|
||||||
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-primary" />
|
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-primary" />
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<!-- Loading State -->
|
<!-- Loading State -->
|
||||||
<div v-if="isLoading" class="flex flex-col items-center justify-center min-h-screen">
|
<div v-if="isLoading" class="flex flex-col items-center justify-center min-h-dvh">
|
||||||
<div class="flex flex-col items-center space-y-4">
|
<div class="flex flex-col items-center space-y-4">
|
||||||
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-primary"></div>
|
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-primary"></div>
|
||||||
<div class="text-center space-y-2">
|
<div class="text-center space-y-2">
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Error State -->
|
<!-- Error State -->
|
||||||
<div v-else-if="error" class="flex flex-col items-center justify-center min-h-screen">
|
<div v-else-if="error" class="flex flex-col items-center justify-center min-h-dvh">
|
||||||
<div class="text-center space-y-4">
|
<div class="text-center space-y-4">
|
||||||
<h2 class="text-xl font-semibold text-red-600">Failed to load chat</h2>
|
<h2 class="text-xl font-semibold text-red-600">Failed to load chat</h2>
|
||||||
<p class="text-muted-foreground">{{ error }}</p>
|
<p class="text-muted-foreground">{{ error }}</p>
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Chat Content - Only render when module is ready -->
|
<!-- Chat Content - Only render when module is ready -->
|
||||||
<div v-else class="h-[calc(100vh-3.5rem)] lg:h-[calc(100vh-4rem)] xl:h-[calc(100vh-5rem)] w-full">
|
<div v-else class="h-[calc(100dvh-3.5rem)] lg:h-[calc(100dvh-4rem)] xl:h-[calc(100dvh-5rem)] w-full">
|
||||||
<ChatComponent />
|
<ChatComponent />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -275,7 +275,7 @@ watch(comments, (newComments) => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen bg-background">
|
<div class="min-h-dvh bg-background">
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<header class="sticky top-0 z-30 bg-background/95 backdrop-blur border-b">
|
<header class="sticky top-0 z-30 bg-background/95 backdrop-blur border-b">
|
||||||
<div class="max-w-4xl mx-auto px-4 py-3">
|
<div class="max-w-4xl mx-auto px-4 py-3">
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ function onSubmissionClick(submission: SubmissionWithMeta) {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col h-screen bg-background">
|
<div class="flex flex-col h-dvh bg-background">
|
||||||
<div class="sticky top-0 z-30 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border-b">
|
<div class="sticky top-0 z-30 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border-b">
|
||||||
<div class="max-w-4xl mx-auto flex items-center justify-between px-4 py-2 sm:px-6">
|
<div class="max-w-4xl mx-auto flex items-center justify-between px-4 py-2 sm:px-6">
|
||||||
<h1 class="text-lg font-semibold">Forum</h1>
|
<h1 class="text-lg font-semibold">Forum</h1>
|
||||||
|
|
|
||||||
|
|
@ -275,7 +275,7 @@ watch(comments, (newComments) => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen bg-background">
|
<div class="min-h-dvh bg-background">
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<header class="sticky top-0 z-30 bg-background/95 backdrop-blur border-b">
|
<header class="sticky top-0 z-30 bg-background/95 backdrop-blur border-b">
|
||||||
<div class="max-w-4xl mx-auto px-4 py-3">
|
<div class="max-w-4xl mx-auto px-4 py-3">
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col h-screen bg-background">
|
<div class="flex flex-col h-dvh bg-background">
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="sticky top-0 z-40 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border-b">
|
<div class="sticky top-0 z-40 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border-b">
|
||||||
<div class="flex items-center justify-between px-4 py-2 sm:px-6">
|
<div class="flex items-center justify-between px-4 py-2 sm:px-6">
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col h-screen bg-background">
|
<div class="flex flex-col h-dvh bg-background">
|
||||||
<PWAInstallPrompt auto-show />
|
<PWAInstallPrompt auto-show />
|
||||||
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ function notImplemented() {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="relative h-screen flex flex-col text-foreground overflow-hidden bg-background"
|
<div class="relative h-dvh flex flex-col text-foreground overflow-hidden bg-background"
|
||||||
style="
|
style="
|
||||||
background-image:
|
background-image:
|
||||||
linear-gradient(to bottom,
|
linear-gradient(to bottom,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen flex items-center justify-center p-4 bg-gradient-to-br from-background via-background to-muted/20">
|
<div class="min-h-dvh flex items-center justify-center p-4 bg-gradient-to-br from-background via-background to-muted/20">
|
||||||
<div class="w-full max-w-md space-y-8">
|
<div class="w-full max-w-md space-y-8">
|
||||||
<!-- Logo and Title -->
|
<!-- Logo and Title -->
|
||||||
<div class="text-center space-y-6">
|
<div class="text-center space-y-6">
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="min-h-screen flex items-start sm:items-center justify-center px-4 sm:px-6 lg:px-8 xl:px-12 2xl:px-16 py-8 sm:py-12">
|
class="min-h-dvh flex items-start sm:items-center justify-center px-4 sm:px-6 lg:px-8 xl:px-12 2xl:px-16 py-8 sm:py-12">
|
||||||
<div class="flex flex-col items-center justify-center space-y-3 sm:space-y-6 max-w-4xl mx-auto w-full mt-8 sm:mt-0">
|
<div class="flex flex-col items-center justify-center space-y-3 sm:space-y-6 max-w-4xl mx-auto w-full mt-8 sm:mt-0">
|
||||||
<!-- Welcome Section -->
|
<!-- Welcome Section -->
|
||||||
<div class="text-center space-y-2 sm:space-y-4">
|
<div class="text-center space-y-2 sm:space-y-4">
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@ async function handleLoginSuccess() {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen bg-background font-sans antialiased">
|
<div class="min-h-dvh bg-background font-sans antialiased">
|
||||||
<div class="relative flex min-h-screen flex-col"
|
<div class="relative flex min-h-dvh flex-col"
|
||||||
style="padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom)">
|
style="padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom)">
|
||||||
|
|
||||||
<div v-if="!isLoginPage && !isAuthenticated" class="fixed top-0 right-0 z-50 p-3" style="padding-top: env(safe-area-inset-top)">
|
<div v-if="!isLoginPage && !isAuthenticated" class="fixed top-0 right-0 z-50 p-3" style="padding-top: env(safe-area-inset-top)">
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@ async function handleLoginSuccess() {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen bg-background font-sans antialiased">
|
<div class="min-h-dvh bg-background font-sans antialiased">
|
||||||
<div class="relative flex min-h-screen flex-col"
|
<div class="relative flex min-h-dvh flex-col"
|
||||||
style="padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom)">
|
style="padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom)">
|
||||||
|
|
||||||
<!-- Top bar with login -->
|
<!-- Top bar with login -->
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue