Compensate for visualViewport offset to keep navbar and chat aligned with keyboard
This commit is contained in:
@@ -42,10 +42,13 @@ export default function PageLayout({
|
||||
"flex flex-col bg-gradient-to-b from-background to-background/95",
|
||||
noPadding ? "h-[100dvh] overflow-hidden" : "min-h-screen",
|
||||
)}>
|
||||
<header className={cn(
|
||||
"border-b border-border bg-card/80 backdrop-blur-sm",
|
||||
noPadding && "fixed inset-x-0 top-0 z-50",
|
||||
)}>
|
||||
<header
|
||||
className={cn(
|
||||
"border-b border-border bg-card/80 backdrop-blur-sm",
|
||||
noPadding && "fixed inset-x-0 z-50",
|
||||
)}
|
||||
style={noPadding ? { top: 'var(--vv-offset, 0px)' } : undefined}
|
||||
>
|
||||
<div className="mx-auto flex h-14 max-w-4xl items-center justify-between px-4">
|
||||
<Link to="/" className="text-lg font-bold tracking-tight text-primary">
|
||||
Movie Loop
|
||||
|
||||
+12
-5
@@ -34,6 +34,7 @@ export default function Chat() {
|
||||
const [sending, setSending] = useState(false);
|
||||
const HEADER_HEIGHT = 56; // h-14 = 3.5rem = 56px
|
||||
const [containerHeight, setContainerHeight] = useState(window.innerHeight - HEADER_HEIGHT);
|
||||
const [viewportOffset, setViewportOffset] = useState(0);
|
||||
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
||||
@@ -86,17 +87,20 @@ export default function Chat() {
|
||||
|
||||
const update = () => {
|
||||
setContainerHeight(vv.height - HEADER_HEIGHT);
|
||||
// Prevent browser from scrolling the page behind fixed elements
|
||||
window.scrollTo(0, 0);
|
||||
setViewportOffset(vv.offsetTop);
|
||||
// Shift the fixed navbar down by the same offset
|
||||
document.documentElement.style.setProperty('--vv-offset', `${vv.offsetTop}px`);
|
||||
if (isAtBottom.current) {
|
||||
requestAnimationFrame(() => scrollToBottom('instant'));
|
||||
}
|
||||
};
|
||||
|
||||
vv.addEventListener('resize', update);
|
||||
vv.addEventListener('scroll', () => window.scrollTo(0, 0));
|
||||
vv.addEventListener('scroll', update);
|
||||
return () => {
|
||||
vv.removeEventListener('resize', update);
|
||||
vv.removeEventListener('scroll', update);
|
||||
document.documentElement.style.removeProperty('--vv-offset');
|
||||
};
|
||||
}, [scrollToBottom]);
|
||||
|
||||
@@ -133,8 +137,11 @@ export default function Chat() {
|
||||
Height is driven by visualViewport so it shrinks when the
|
||||
mobile keyboard opens, keeping input visible. */}
|
||||
<div
|
||||
className="fixed inset-x-0 top-14 flex flex-col"
|
||||
style={{ height: containerHeight }}
|
||||
className="fixed inset-x-0 flex flex-col"
|
||||
style={{
|
||||
top: HEADER_HEIGHT + viewportOffset,
|
||||
height: containerHeight,
|
||||
}}
|
||||
>
|
||||
{/* Chat header */}
|
||||
<div className="flex shrink-0 items-center gap-3 border-b border-border bg-background px-4 py-3">
|
||||
|
||||
Reference in New Issue
Block a user