Content was drawing under the iOS status bar and home indicator because the app uses viewport-fit=cover + black-translucent but the fixed/sticky chrome didn't reserve the safe areas. - bottom nav (MyLayout): move the 50px row into an inner box and let the bar extend by env(safe-area-inset-bottom) so icons sit above the home indicator (previously the fixed height clipped the inset padding). - top headers gain env(safe-area-inset-top): HomePageTopBar, ExploreTopBar, SearchTopBar, CartHeader, ChatHeader, and wrapper-padded HeaderWithSupport / ProfilePagesHeader (so their absolutely-positioned buttons shift too). - chat input pads bottom by the inset; chat scroll area height accounts for the taller header/input. - _index.tsx no longer overrides the viewport meta (it was dropping viewport-fit=cover on the home page); the global one in root.tsx wins. env(safe-area-inset-*) is 0 on non-notch devices, so desktop/Android render identically — only iOS gains the padding. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
73 lines
2.0 KiB
TypeScript
73 lines
2.0 KiB
TypeScript
import { useState, memo, useCallback, useMemo } from "react";
|
|
import { ArrowRight, Headset } from "lucide-react";
|
|
import CallDialog from "./CallDialog";
|
|
|
|
interface HeaderWithSupportProps {
|
|
title: string;
|
|
onBack: () => void;
|
|
hideSupportButton?: boolean;
|
|
}
|
|
|
|
const HeaderWithSupport = memo(function HeaderWithSupport({
|
|
title,
|
|
onBack,
|
|
hideSupportButton,
|
|
}: HeaderWithSupportProps) {
|
|
const [isCallModalOpen, setIsCallModalOpen] = useState(false);
|
|
const supportPhone = useMemo(
|
|
() => import.meta.env.VITE_SUPPORT_PHONE || "",
|
|
[]
|
|
);
|
|
|
|
const handleSupportClick = useCallback(() => {
|
|
setIsCallModalOpen(true);
|
|
}, []);
|
|
|
|
const handleCallConfirm = useCallback(() => {
|
|
window.location.href = `tel:${supportPhone}`;
|
|
setIsCallModalOpen(false);
|
|
}, [supportPhone]);
|
|
|
|
const handleKeyDown = useCallback(
|
|
(e: React.KeyboardEvent) => {
|
|
if (e.key === "Enter") {
|
|
handleSupportClick();
|
|
}
|
|
},
|
|
[handleSupportClick]
|
|
);
|
|
|
|
return (
|
|
<>
|
|
<div className="sticky top-0 z-30 bg-WHITE pt-[env(safe-area-inset-top)]">
|
|
<div className="relative flex flex-row h-[65px] bg-WHITE w-full items-center justify-center border-b border-inner-border">
|
|
<ArrowRight
|
|
onClick={onBack}
|
|
className="absolute top-5 right-5 cursor-pointer"
|
|
/>
|
|
<p className="text-B16 font-bold ">{title}</p>
|
|
{!hideSupportButton && (
|
|
<div
|
|
className="absolute top-4 h-8 w-8 left-5 rounded-full bg-WHITE shadow-xl flex items-center justify-center cursor-pointer"
|
|
onClick={handleSupportClick}
|
|
role="button"
|
|
tabIndex={0}
|
|
onKeyDown={handleKeyDown}
|
|
>
|
|
<Headset size={20} />
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
<CallDialog
|
|
isCallModalOpen={isCallModalOpen}
|
|
setIsCallModalOpen={setIsCallModalOpen}
|
|
handleCallConfirm={handleCallConfirm}
|
|
/>
|
|
</>
|
|
);
|
|
});
|
|
|
|
export default HeaderWithSupport;
|