banner of desktop completed

This commit is contained in:
2026-02-06 10:03:55 +03:30
parent f44e3ab421
commit dc0a04dc7d
20 changed files with 10158 additions and 12233 deletions

View File

@@ -1,19 +1,62 @@
"use client";
import MainMap from "@/components/MainMap";
import { motion, AnimatePresence } from "framer-motion";
import LocationMarker from "./LocationMarker";
import {useModalStore} from "@/stores/useModalStore";
import {CloseIcon} from "@/assets";
import MarkerPosition from "@/components/Home/MarkerPosition";
const backdropVariants = {
hidden: { opacity: 0 },
visible: { opacity: 1 },
exit: { opacity: 0 },
};
const modalVariants = {
hidden: { opacity: 0, scale: 0.9 },
visible: {
opacity: 1,
scale: 1,
transition: { stiffness: 300, damping: 25 },
},
exit: { opacity: 0, scale: 0.9 },
};
const LocationModal = () => {
const closeModal = useModalStore((s) => s.closeModal);
return (
<div style={{ width: "100%", height: "100dvh", position: "relative" }}>
<MainMap>
<LocationMarker
location={{ lat: 36.541, lng: 54.56 }}
onDragEnd={() => {
console.log("hello");
}}
/>
</MainMap>
</div>
<AnimatePresence>
<motion.div
className="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
variants={backdropVariants}
initial="hidden"
animate="visible"
exit="exit"
onClick={closeModal}
>
<motion.div
className="relative h-[50vh] w-[90vw] rounded-lg shadow-lg sm:h-[40vh] sm:w-[40vw] lg:h-[60vh] lg:w-[50vw]"
variants={modalVariants}
initial="hidden"
animate="visible"
exit="exit"
onClick={(e) => e.stopPropagation()}
>
<button
onClick={closeModal}
className="absolute top-2 left-2 z-50 cursor-pointer rounded-full bg-black/60 p-2 transition hover:bg-black/60"
>
<CloseIcon className="h-5 w-5 text-white" />
</button>
<div className="relative h-full w-full">
<MainMap>
<MarkerPosition onChange={(loc) => console.log(loc)} />
</MainMap>
</div>
</motion.div>
</motion.div>
</AnimatePresence>
);
};
export default LocationModal;

View File

@@ -2,6 +2,12 @@ import SearchItem from "./SearchItem";
import { CalenderIcon, LocationIcon, SearchIcon } from "@/assets";
import { useModalStore } from "@/stores/useModalStore";
import LocationModal from "./LocationModal";
import NoFormSelect from "@/components/UI/NoFormSelect";
import DatePickerField from "@/components/UI/DatePickerField";
const options = [
{ label: "Home", value: "home" },
{ label: "Search", value: "search" },
]
export default function SearchBar() {
const openModal = useModalStore((s) => s.openModal);
@@ -20,16 +26,22 @@ export default function SearchBar() {
{/* تاریخ */}
<SearchItem icon={<CalenderIcon className="size-5" />}>
<input type="date" className="w-full bg-transparent text-gray-500 outline-none" />
<DatePickerField name="bill_of_lading_date" setValue={()=>{
console.log("hello DatePickerField")}} />
</SearchItem>
{/* دسته بندی */}
<SearchItem icon={<SearchIcon className="size-5" />}>
<select className="w-full bg-transparent text-gray-500 outline-none">
<option>دسته بندی</option>
<option>رستوران</option>
<option>کافیشاپ</option>
</select>
<NoFormSelect
value={""}
onChange={()=>{
console.log("hello")}}
options={options}
loading={false}
error={null}
placeholder="علت انسداد"
// onOpen={fetchReasons}
/>
</SearchItem>
</div>
);

View File

@@ -5,8 +5,8 @@ interface SearchItemProps {
function SearchItem({ icon, children }: SearchItemProps) {
return (
<div className="flex min-w-[180px] items-center gap-2 rounded-full bg-white px-4 py-3 shadow-sm">
<div className="text-gray-400">{icon}</div>
<div className="flex min-w-[180px] items-center gap-2 rounded-full bg-white px-4 py-2 shadow-sm">
<div className="text-black">{icon}</div>
<div className="flex-1">{children}</div>
</div>

View File

@@ -0,0 +1,66 @@
import { MarkerIcon, MarkerPreviewIcon } from "@/assets";
import { useMap } from "@vis.gl/react-maplibre";
import maplibregl from "maplibre-gl";
import { useEffect, useRef } from "react";
import { renderToStaticMarkup } from "react-dom/server";
const createMarkerElement = (preview: boolean) => {
const el = document.createElement("div");
const Icon = preview ? MarkerPreviewIcon : MarkerIcon;
el.innerHTML = renderToStaticMarkup(
<Icon className="size-10 text-neo-aqua" />
);
return el;
};
type Props = {
preview?: boolean;
onChange?: (location: { lat: number; lng: number }) => void;
};
const MarkerPosition = ({ preview = false, onChange }: Props) => {
const { homePageMap } = useMap();
const markerRef = useRef<maplibregl.Marker | null>(null);
useEffect(() => {
if (!homePageMap) return;
const map = homePageMap.getMap();
if (!map) return;
// create marker once
if (!markerRef.current) {
const el = createMarkerElement(preview);
markerRef.current = new maplibregl.Marker({
element: el,
anchor: "bottom",
subpixelPositioning: true,
})
.setLngLat(map.getCenter())
.addTo(map);
}
const onMove = () => {
const center = map.getCenter();
markerRef.current?.setLngLat(center);
onChange?.({
lat: center.lat,
lng: center.lng,
});
};
map.on("moveend", onMove);
return () => {
map.off("moveend", onMove);
markerRef.current?.remove();
markerRef.current = null;
};
}, [homePageMap, preview]);
return null;
};
export default MarkerPosition;

View File

@@ -0,0 +1,79 @@
import { MarkerIcon } from "@/assets";
import { LatLng } from "@/stores/LocationStore";
import { Marker, MarkerDragEvent } from "@vis.gl/react-maplibre";
import { AnimatePresence, motion } from "framer-motion";
import { useState } from "react";
type Props = {
location: LatLng;
onDragEnd: (e: MarkerDragEvent) => void;
};
const dropInVariants = {
initial: { y: -50, opacity: 0, scale: 0.8 },
animate: {
y: 0,
opacity: 1,
scale: 1,
transition: {
type: "spring" as const,
stiffness: 600,
damping: 30,
},
},
};
export default function LocationMarker({ location, onDragEnd }: Props) {
const [isDragging, setIsDragging] = useState(false);
const handleDragStart = () => {
setIsDragging(true);
};
const handleDragEnd = (e: MarkerDragEvent) => {
setIsDragging(false);
onDragEnd(e);
};
return (
<Marker
latitude={location.lat}
longitude={location.lng}
draggable
anchor="bottom"
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
>
<AnimatePresence mode="wait">
<motion.div
variants={dropInVariants}
initial="initial"
animate={{
y: isDragging ? -20 : 0,
opacity: 1,
transition: {
type: "spring" as const,
stiffness: 500,
damping: 25,
},
}}
exit="exit"
className="relative flex flex-col items-center"
>
{/* Drop pointer inside the marker (shown only when dragging) */}
{isDragging && (
<motion.div
layoutId="drop-pointer"
initial={{ scale: 0, opacity: 0 }}
animate={{ scale: 1, opacity: 0.5, y: 10 }}
exit={{ scale: 0, opacity: 0 }}
transition={{ type: "spring", stiffness: 300, damping: 20 }}
className="absolute -bottom-4.5 z-[-1] size-1.5 rounded-full bg-black shadow-md"
/>
)}
<MarkerIcon className="text-neo-aqua size-8" />
</motion.div>
</AnimatePresence>
</Marker>
);
}

View File

@@ -0,0 +1,62 @@
"use client";
import MainMap from "@/components/MainMap";
import { motion, AnimatePresence } from "framer-motion";
import LocationMarker from "./LocationMarker";
import {useModalStore} from "@/stores/useModalStore";
import {CloseIcon} from "@/assets";
import MarkerPosition from "@/components/Home/MarkerPosition";
const backdropVariants = {
hidden: { opacity: 0 },
visible: { opacity: 1 },
exit: { opacity: 0 },
};
const modalVariants = {
hidden: { opacity: 0, scale: 0.9 },
visible: {
opacity: 1,
scale: 1,
transition: { stiffness: 300, damping: 25 },
},
exit: { opacity: 0, scale: 0.9 },
};
const LocationModal = () => {
const closeModal = useModalStore((s) => s.closeModal);
return (
<AnimatePresence>
<motion.div
className="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
variants={backdropVariants}
initial="hidden"
animate="visible"
exit="exit"
onClick={closeModal}
>
<motion.div
className="relative h-[50vh] w-[90vw] rounded-lg shadow-lg sm:h-[40vh] sm:w-[40vw] lg:h-[60vh] lg:w-[50vw]"
variants={modalVariants}
initial="hidden"
animate="visible"
exit="exit"
onClick={(e) => e.stopPropagation()}
>
<button
onClick={closeModal}
className="absolute top-2 left-2 z-50 cursor-pointer rounded-full bg-black/60 p-2 transition hover:bg-black/60"
>
<CloseIcon className="h-5 w-5 text-white" />
</button>
<div className="relative h-full w-full">
<MainMap>
<MarkerPosition onChange={(loc) => console.log(loc)} />
</MainMap>
</div>
</motion.div>
</motion.div>
</AnimatePresence>
);
};
export default LocationModal;

View File

@@ -0,0 +1,48 @@
import SearchItem from "./SearchItem";
import { CalenderIcon, LocationIcon, SearchIcon } from "@/assets";
import { useModalStore } from "@/stores/useModalStore";
import LocationModal from "./LocationModal";
import NoFormSelect from "@/components/UI/NoFormSelect";
import DatePickerField from "@/components/UI/DatePickerField";
const options = [
{ label: "Home", value: "home" },
{ label: "Search", value: "search" },
]
export default function SearchBar() {
const openModal = useModalStore((s) => s.openModal);
return (
<div className="bg-card flex max-w-2xl items-center justify-between gap-1 rounded-full p-4">
{/* آدرس */}
<SearchItem icon={<LocationIcon className="size-5" />}>
<button
type="button"
onClick={() => openModal(<LocationModal />)}
className="w-full text-right text-gray-500"
>
آدرس
</button>
</SearchItem>
{/* تاریخ */}
<SearchItem icon={<CalenderIcon className="size-5" />}>
<DatePickerField name="bill_of_lading_date" setValue={()=>{
console.log("hello DatePickerField")}} />
</SearchItem>
{/* دسته بندی */}
<SearchItem icon={<SearchIcon className="size-5" />}>
<NoFormSelect
value={""}
onChange={()=>{
console.log("hello")}}
options={options}
loading={false}
error={null}
placeholder="علت انسداد"
// onOpen={fetchReasons}
/>
</SearchItem>
</div>
);
}

View File

@@ -0,0 +1,15 @@
interface SearchItemProps {
icon: React.ReactNode;
children: React.ReactNode;
}
function SearchItem({ icon, children }: SearchItemProps) {
return (
<div className="flex min-w-[180px] items-center gap-2 rounded-full bg-white px-4 py-2 shadow-sm">
<div className="text-black">{icon}</div>
<div className="flex-1">{children}</div>
</div>
);
}
export default SearchItem;

View File

@@ -0,0 +1,169 @@
"use client";
import { ArrowTopLeft, AvatarIcon, BannerImage, BannerLine, BannerStar, LogoIcon, MyOrderIcon } from "@/assets";
import { useTranslations } from "next-intl";
import userStore from "@/stores/userStore";
import Image from "next/image";
import ThemeToggle from "@/components/ThemeToggle";
import { motion } from "framer-motion";
import GroupAvatar from "@/components/UI/GroupAvatar";
import SearchBar from "@/components/Home/Desktop/Banner/SearchBar";
export default function BannerComponent() {
const t = useTranslations("HomePage");
const isAuth = userStore((s) => s.isAuth);
return (
<motion.div
initial={{ opacity: 0, y: 60 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.9, ease: "easeOut" }}
className="bg-home-page-banner relative mt-16 rounded-tr-[200px] rounded-bl-[200px] px-2 pt-2"
>
{/* ================= Header ================= */}
<header className="flex w-full items-center justify-center pt-8">
<div className="flex w-full items-center justify-center space-x-5">
<motion.div
initial={{ scale: 0 }}
animate={{ scale: 1 }}
transition={{ type: "spring", stiffness: 200 }}
>
<LogoIcon className="size-12" />
</motion.div>
<ThemeToggle />
{["home", "search", "salons", "about_us", "contact_us"].map((item, index) => (
<motion.p
key={item}
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.1 * index }}
className="text-text-primary hover:text-primary-200 cursor-pointer transition"
>
{t(item)}
</motion.p>
))}
</div>
<div className="flex w-full items-center justify-center">
{isAuth ? (
<motion.div whileHover={{ scale: 1.1 }} className="cursor-pointer">
<AvatarIcon className="h-6 w-6" />
</motion.div>
) : (
<span className="flex w-full items-center justify-center gap-x-2">
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
className="bg-bg flex items-center justify-center gap-x-2 rounded-lg p-3"
>
<MyOrderIcon className="h-6 w-6" />
<p>{t("my_order")}</p>
</motion.button>
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
className="bg-primary-200 flex items-center justify-center gap-x-2 rounded-lg p-3"
>
<AvatarIcon className="h-6 w-6" />
<p>{t("auth")}</p>
</motion.button>
</span>
)}
</div>
</header>
{/* ================= Main ================= */}
<motion.main initial="hidden" animate="visible" className="flex w-full items-center justify-center py-12">
{/* ===== Left Content ===== */}
<div className="flex w-full flex-col items-center justify-center space-y-7">
{/* Title */}
<motion.div className="text-4xl font-bold">
<motion.span
variants={{
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0 },
}}
className="block"
>
{t("main_title_line1")}
</motion.span>
<motion.div
variants={{
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0 },
}}
className="flex items-center justify-between"
>
{t("main_title_line2")}
<motion.div
initial={{ scaleX: 0 }}
animate={{ scaleX: 1 }}
transition={{ delay: 0.6, duration: 0.4 }}
className="origin-right"
>
<BannerLine className="h-1 w-28" />
</motion.div>
<motion.div
animate={{ rotate: [0, 10, -10, 0] }}
transition={{ repeat: Infinity, duration: 3 }}
>
<BannerStar className="h-6 w-6" />
</motion.div>
</motion.div>
</motion.div>
{/* Description */}
<motion.p
variants={{
hidden: { opacity: 0 },
visible: { opacity: 1 },
}}
className="text-center text-xs"
>
{t("des")}
</motion.p>
{/* CTA Button */}
<motion.button
whileHover={{ scale: 1.07 }}
whileTap={{ scale: 0.95 }}
transition={{ type: "spring", stiffness: 300 }}
className="bg-primary-200 flex items-center justify-center gap-x-3 rounded-lg p-3"
>
<p className="text-white">{t("see_salons")}</p>
<motion.div whileHover={{ x: -4, y: -4 }}>
<ArrowTopLeft className="size-5 text-white" />
</motion.div>
</motion.button>
<GroupAvatar />
</div>
{/* ===== Right Image ===== */}
<motion.div
animate={{ y: [0, -12, 0] }}
transition={{ repeat: Infinity, duration: 4, ease: "easeInOut" }}
className="flex w-full items-center justify-center"
>
<Image
src={BannerImage}
alt="main_image"
className="object-cover"
width={400}
height={200}
priority
/>
</motion.div>
</motion.main>
<div className="absolute -bottom-10 left-24">
<SearchBar />
</div>
</motion.div>
);
}

View File

@@ -1,3 +1,7 @@
export default function MobileHome() {
return <></>;
return (
<div className="h-full w-full">
</div>
);
}

View File

@@ -0,0 +1,76 @@
"use client";
import { CalendarHijri } from "@/components/UI/Calendar";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/UI/Popover";
import { motion } from "framer-motion";
import { useState } from "react";
import { Path, UseFormSetValue } from "react-hook-form";
type Props<T extends Record<string, any>> = {
name: Path<T>;
label?: string | null;
setValue: UseFormSetValue<T>;
defaultValue?: string | null;
};
export default function DatePickerField<T extends Record<string, any>>({
name,
label,
setValue,
defaultValue,
}: Props<T>) {
const [date, setDate] = useState<Date | undefined>(defaultValue ? new Date(defaultValue) : undefined);
const [open, setOpen] = useState(false);
// format date into Persian numerals
const formatJalali = (date?: Date) => {
if (!date) return "";
const formatter = new Intl.DateTimeFormat("fa-IR", {
year: "numeric",
month: "2-digit",
day: "2-digit",
});
return formatter.format(date);
};
return (
<div className="relative flex flex-col justify-between gap-1">
<motion.label
className="text-sm font-medium"
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
>
{label}
</motion.label>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<button
type="button"
onClick={() => setOpen(true)}
className={
"text-black rounded-lg px-3 text-start focus:outline-none"
}
>
{date ? formatJalali(date) : "تاریخ"}
</button>
</PopoverTrigger>
<PopoverContent align="center" className="z-50 w-auto p-0" sideOffset={8}>
<div>
<CalendarHijri
selected={date}
onSelect={(selectedDate) => {
setDate(selectedDate);
if (selectedDate) {
setValue(name, selectedDate.toISOString() as any, { shouldValidate: true });
setOpen(false);
}
}}
/>
</div>
</PopoverContent>
</Popover>
</div>
);
}

View File

@@ -0,0 +1,91 @@
"use client";
import React from "react";
import {Select, SelectTrigger, SelectValue, SelectContent, SelectItem} from "@/components/UI/Select";
import {motion} from "framer-motion";
interface Option {
value: string | number;
label: string;
}
interface ReusableSelectProps {
value: string | number;
onChange: (value: string | number) => void;
options: Option[];
loading?: boolean;
error?: string | null;
placeholder?: string;
onOpen?: () => void;
}
const NoFormSelect: React.FC<ReusableSelectProps> = ({
value,
onChange,
options,
loading = false,
error = null,
placeholder = "انتخاب کنید",
onOpen,
}) => {
return (
<Select
value={value?.toString() || ""}
onValueChange={(val) => onChange(val)}
onOpenChange={(open) => {
if (open && onOpen) onOpen();
}}
>
<SelectTrigger
className={`"text-black placeholder-black w-full overflow-x-scroll rounded-lg `}
>
<SelectValue placeholder={placeholder}/>
</SelectTrigger>
<SelectContent
className="bg-card overflow-y-auto rounded-xl border-0 shadow-lg">
{loading && (
<SelectItem value="loading" disabled>
در حال بارگذاری...
</SelectItem>
)}
{error && (
<SelectItem value="error" disabled>
{error}
</SelectItem>
)}
{!loading && !error && (
<>
<motion.div
whileHover={{scale: 1.05}}
whileTap={{scale: 0.95}}
className="rounded px-2 py-1"
>
<SelectItem
value="all"
className="hover:from-primary-400 hover:to-primary-500 cursor-pointer hover:bg-linear-to-l"
>
تمامی موارد
</SelectItem>
</motion.div>
{options.map((opt) => (
<motion.div
key={opt.value}
whileHover={{scale: 1.05}}
whileTap={{scale: 0.95}}
className="rounded px-2 py-1"
>
<SelectItem
value={opt.value.toString()}
className="hover:from-primary-400 hover:to-primary-500 cursor-pointer hover:bg-linear-to-l"
>
{opt.label}
</SelectItem>
</motion.div>
))}
</>
)}
</SelectContent>
</Select>
);
};
export default NoFormSelect;

View File

@@ -26,7 +26,7 @@ function PopoverContent({
align={align}
sideOffset={sideOffset}
className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
"bg-card text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md p-4 shadow-md outline-hidden",
className
)}
{...props}

View File

@@ -25,14 +25,14 @@ function SelectTrigger({
data-slot="select-trigger"
data-size={size}
className={cn(
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"data-[placeholder]:text-black [&_svg:not([class*='text-'])]:text-black dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md bg-transparent px-3 text-sm whitespace-nowrap transition-[color,box-shadow] outline-none disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-7 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
>
{children}
<SelectPrimitive.Icon asChild>
<ChevronIcon className="text-text size-4 rotate-270" />
<ChevronIcon className="text-text size-3 rotate-270" />
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
);
@@ -48,7 +48,7 @@ function SelectContent({
<SelectPrimitive.Content
data-slot="select-content"
className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md",
position === "popper" &&
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
className