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>
70 lines
2.0 KiB
TypeScript
70 lines
2.0 KiB
TypeScript
import React from "react";
|
|
import { useSearchParams } from "@remix-run/react";
|
|
import AppInput from "./AppInput";
|
|
import { Search as SearchIcon } from "lucide-react";
|
|
import FilterDrawer from "./FilterDrawer";
|
|
|
|
interface SearchTopBarProps {
|
|
searchValue: string;
|
|
setSearchValue: (value: string) => void;
|
|
placeholder?: string;
|
|
minimumPrice?: number;
|
|
maximumPrice?: number;
|
|
onSearch?: () => void;
|
|
}
|
|
|
|
const SearchTopBar: React.FC<SearchTopBarProps> = ({
|
|
searchValue,
|
|
setSearchValue,
|
|
placeholder = "جستجو...",
|
|
minimumPrice = 0,
|
|
maximumPrice = 10000000,
|
|
onSearch,
|
|
}) => {
|
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
const isChangedSearchBar = searchValue !== (searchParams.get("q") || "");
|
|
|
|
const handleSearch = () => {
|
|
if (onSearch) {
|
|
onSearch();
|
|
return;
|
|
}
|
|
|
|
if (isChangedSearchBar) {
|
|
const params = new URLSearchParams(searchParams);
|
|
if (searchValue.trim()) {
|
|
params.set("q", searchValue);
|
|
} else {
|
|
params.delete("q");
|
|
}
|
|
setSearchParams(params, { replace: true });
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="flex flex-col gap-4 pb-4 pt-[calc(1rem_+_env(safe-area-inset-top))] px-4 w-full sticky top-0 z-30 bg-WHITE">
|
|
<div className="flex items-center justify-center gap-2 rounded-[10px] w-full relative">
|
|
<AppInput
|
|
inputIcon={SearchIcon}
|
|
inputDir="rtl"
|
|
inputTitle={""}
|
|
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
if (e.key === "Enter") {
|
|
handleSearch();
|
|
}
|
|
}}
|
|
className="bg-WHITE2 focus:border-blue-500"
|
|
inputValue={searchValue}
|
|
inputPlaceholder={placeholder}
|
|
inputOnChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
|
setSearchValue(e.target.value);
|
|
}}
|
|
/>
|
|
<FilterDrawer minimumPrice={minimumPrice} maximumPrice={maximumPrice} />
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default SearchTopBar;
|