Implement useHideBottomNavOnKeyboard hook: hide bottom nav on keyboard open for private messages, adjust layout logic, and update styles.

This commit is contained in:
MartinBraquet
2026-07-29 16:48:15 +02:00
parent cc68b0652a
commit b55ba93bfe
4 changed files with 38 additions and 5 deletions

View File

@@ -41,7 +41,7 @@ export function BottomNavBar(props: {navigationOptions: Item[]; sidebarNavigatio
<Col>
<nav
className={clsx(
'border-ink-200 dark:border-ink-300 text-ink-700 bg-canvas-50 fixed inset-x-0 bottom-0 z-50 flex select-none items-center justify-between border-t-2 text-xs lg:hidden sidebar-nav',
'border-ink-200 dark:border-ink-300 text-ink-700 bg-canvas-50 fixed inset-x-0 bottom-0 z-50 flex select-none items-center justify-between border-t-2 text-xs lg:hidden sidebar-nav bottom-nav',
'safe-bottom',
)}
>
@@ -68,7 +68,7 @@ export function BottomNavBar(props: {navigationOptions: Item[]; sidebarNavigatio
</nav>
<div
className="fixed inset-x-0 bg-canvas-50"
className="fixed inset-x-0 bg-canvas-50 bottom-nav"
style={{
bottom: 0,
height: 'env(safe-area-inset-bottom)',

View File

@@ -0,0 +1,20 @@
import {useEffect} from 'react'
/**
* Hides the mobile bottom nav bar while the on-screen keyboard is open, for as long as the calling
* component is mounted.
*
* On a page whose composer is pinned to the bottom (private messages), the nav bar gets pushed up by
* the keyboard and wedges itself between the keyboard and the input — eating a row of screen height
* for navigation nobody is using mid-message.
*
* The keyboard state itself is tracked in `_app.tsx`, which toggles `keyboard-open` on `<body>` from
* the Capacitor keyboard events; the rules live in `globals.css` so showing/hiding costs no re-render.
* Zeroing `--bnv` there also reclaims the bar's height for the page below it.
*/
export const useHideBottomNavOnKeyboard = () => {
useEffect(() => {
document.body.classList.add('hide-bottom-nav')
return () => document.body.classList.remove('hide-bottom-nav')
}, [])
}

View File

@@ -29,6 +29,7 @@ import {Avatar} from 'web/components/widgets/avatar'
import {useTextEditor} from 'web/components/widgets/editor'
import {CompassLoadingIndicator} from 'web/components/widgets/loading-indicator'
import {BannedBadge, UserAvatarAndBadge} from 'web/components/widgets/user-link'
import {useHideBottomNavOnKeyboard} from 'web/hooks/use-hide-bottom-nav-on-keyboard'
import {useIsMobile} from 'web/hooks/use-is-mobile'
import {
usePrivateMessages,
@@ -117,6 +118,7 @@ export const PrivateChat = (props: {
}) => {
const {user, channel, memberIds} = props
const t = useT()
useHideBottomNavOnKeyboard()
const channelId = channel.channel_id
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
const isMobile = useIsMobile()
@@ -436,7 +438,7 @@ export const PrivateChat = (props: {
</Modal>
)}
</Row>
<Col className="relative h-[calc(100dvh-210px-var(--hloss))] lg:h-[calc(100dvh-184px-var(--hloss))] xl:px-0">
<Col className="relative h-[calc(100dvh-149px-var(--bnv)-var(--hloss))] lg:h-[calc(100dvh-184px-var(--hloss))] xl:px-0">
<div
ref={outerDiv}
className="relative h-full overflow-y-auto"

View File

@@ -6,6 +6,7 @@
/*--font-main: "Crimson Pro", "EB Garamond", Georgia, "Times New Roman", Times, serif;*/
--font-main: 'Atkinson Hyperlegible Next', Georgia, 'Times New Roman', Times, serif;
--bnh: env(safe-area-inset-bottom); /* native bottom nav height */
--bnv: 61px; /* our own mobile bottom nav bar height */
--tnh: env(safe-area-inset-top); /* native top nav height */
--hloss: calc(var(--bnh) + var(--tnh)); /* mobile height loss due to native top and bottom bars */
--filter-offset: 0px; /* padding for filters on mobile */
@@ -30,15 +31,25 @@
}
.keyboard-open .pb-page-base {
padding-bottom: calc(61px);
padding-bottom: var(--bnv);
}
.pb-page-base {
padding-bottom: calc(61px + env(safe-area-inset-bottom));
padding-bottom: calc(var(--bnv) + env(safe-area-inset-bottom));
/*bottom: calc(48px);*/
/*padding-bottom: env(safe-area-inset-bottom);*/
}
/* Pages that opt in via useHideBottomNavOnKeyboard() (e.g. private messages): while the keyboard is
up the bar would sit between the keyboard and the composer, so drop it and reclaim its height. */
.keyboard-open.hide-bottom-nav {
--bnv: 0px;
}
.keyboard-open.hide-bottom-nav .bottom-nav {
display: none;
}
/* When keyboard is open, remove safe area offset */
.keyboard-open .safe-bottom {
bottom: 0;