responsive

This commit is contained in:
hamid zarghami
2026-07-21 15:16:47 +03:30
parent 14d1422970
commit 112aee1cdf
10 changed files with 46 additions and 44 deletions
+1 -1
View File
@@ -5,7 +5,7 @@ import { BREADCRUMB_ITEMS } from "../constants";
const ProductBreadcrumb: FC = () => {
return (
<nav aria-label="مسیر صفحه" className="flex items-center justify-start gap-2 bg-secondary px-4 py-3 text-sm text-[#3F4D5A] sm:px-8 lg:px-30">
<nav aria-label="مسیر صفحه" className="flex items-center justify-start gap-2 overflow-x-auto bg-secondary px-4 py-3 text-sm whitespace-nowrap text-[#3F4D5A] sm:px-8 lg:px-30">
{BREADCRUMB_ITEMS.map((item, index) => (
<Fragment key={item.label}>
{index > 0 && <ArrowLeft2 size={14} color="currentColor" className="shrink-0" />}
+12 -10
View File
@@ -17,19 +17,21 @@ const ProductDetail: FC = () => {
<>
<ProductBreadcrumb />
<div className="px-4 py-6 sm:px-8 sm:py-8 lg:px-30">
<div className="flex flex-col items-start gap-8 lg:flex-row lg:items-start lg:gap-10">
<ProductGallery images={PRODUCT_GALLERY_IMAGES} alt={PRODUCT_TITLE} />
<div className="flex w-full min-w-0 flex-1 flex-col items-end">
<ProductPurchaseOptions selectedTier={selectedTier} onSelectTier={setSelectedTier} />
<ProductOrderActions selectedTier={selectedTier} />
<div className="pb-28 lg:pb-0">
<div className="px-4 py-6 sm:px-8 sm:py-8 lg:px-30">
<div className="flex flex-col items-start gap-6 sm:gap-8 lg:flex-row lg:items-start lg:gap-10">
<ProductGallery images={PRODUCT_GALLERY_IMAGES} alt={PRODUCT_TITLE} />
<div className="flex w-full min-w-0 flex-1 flex-col">
<ProductPurchaseOptions selectedTier={selectedTier} onSelectTier={setSelectedTier} />
<ProductOrderActions selectedTier={selectedTier} />
</div>
</div>
</div>
</div>
<ProductTabs />
<ProductRelated />
<ContactCtaSection />
<ProductTabs />
<ProductRelated />
<ContactCtaSection />
</div>
</>
);
};
+3 -3
View File
@@ -13,12 +13,12 @@ const ProductGallery: FC<ProductGalleryProps> = ({ images, alt }) => {
const [activeIndex, setActiveIndex] = useState(0);
return (
<div className="flex w-full shrink-0 flex-col gap-3 lg:w-[45%] lg:max-w-120">
<div className="relative aspect-square w-full overflow-hidden rounded-2xl bg-[#F7FAFC]">
<div className="flex w-full shrink-0 flex-col gap-3 sm:gap-4 lg:w-[45%] lg:max-w-120">
<div className="relative aspect-square w-full overflow-hidden rounded-xl bg-[#F7FAFC] sm:rounded-2xl">
<Image src={images[activeIndex]} alt={alt} fill priority className="object-contain p-4" sizes="(max-width: 1024px) 100vw, 480px" />
</div>
<div className="grid grid-cols-4 gap-2.5">
<div className="grid grid-cols-4 gap-2 sm:gap-2.5">
{images.slice(0, 4).map((image, index) => (
<button
key={index}
@@ -10,18 +10,18 @@ type ProductOrderActionsProps = {
const ProductOrderActions = ({ selectedTier }: ProductOrderActionsProps) => {
return (
<div className="mt-5 flex w-full flex-col gap-3 self-end rounded-t-2xl bg-white px-4 py-4 shadow-[0px_-4px_34px_0px_#1A456C14] sm:flex-row sm:items-center sm:justify-between sm:gap-5 sm:px-5 sm:py-4">
<div className="fixed inset-x-0 bottom-0 z-40 flex w-full flex-col gap-3 rounded-t-2xl bg-white px-4 py-3 shadow-[0px_-4px_34px_0px_#1A456C14] sm:flex-row sm:items-center sm:justify-between sm:gap-4 sm:px-8 sm:py-4 lg:relative lg:inset-auto lg:mt-5 lg:gap-5 lg:rounded-t-2xl lg:px-5 lg:shadow-[0px_-4px_34px_0px_#1A456C14]">
<div className="space-y-1 text-right">
<p className="text-base font-bold text-[#0A1B2C] sm:text-lg">{formatPrice(selectedTier.totalPrice)}</p>
<div className="flex items-center justify-end gap-2">
<div className="flex flex-wrap items-center justify-end gap-2">
<span className="text-xs text-[#0A1B2C] sm:text-sm">{formatPrice(selectedTier.unitPrice)} به ازای هر عدد</span>
<span className="rounded-lg bg-[#00893E] px-2 py-0.5 text-[10px] font-medium text-white sm:text-xs">{PRODUCT_PROFIT_PERCENT}٪ سود</span>
</div>
</div>
<div className="hidden h-16 w-0 shrink-0 border-s-2 border-primary sm:block" />
<div className="hidden h-16 w-0 shrink-0 border-s-2 border-primary lg:block" />
<div className="flex flex-col gap-2 sm:flex-row sm:items-end sm:gap-5">
<div className="flex flex-col gap-2 sm:flex-row sm:items-end sm:gap-4 lg:gap-5">
<div className="w-full space-y-1 sm:w-32">
<span className="block text-right text-xs font-medium text-[#0A1B2C]">تعداد</span>
<Select options={[...STICKY_QUANTITY_OPTIONS]} defaultValue="1000" className="h-10 rounded-xl border-[#E9EEF2] text-sm" />
@@ -14,11 +14,11 @@ type ProductPurchaseOptionsProps = {
const ProductPurchaseOptions: FC<ProductPurchaseOptionsProps> = ({ selectedTier, onSelectTier }) => {
return (
<div className="flex w-full min-w-0 flex-1 flex-col items-end gap-4">
<div className="flex w-full min-w-0 flex-1 flex-col gap-4">
<div className="w-full space-y-2 text-right">
<h1 className="text-xl font-bold text-[#0A1B2C] sm:text-2xl">{PRODUCT_TITLE}</h1>
<div className="flex items-center gap-2">
<div className="flex items-center justify-end gap-2">
<Rating initialValue={PRODUCT_RATING} size={16} readonly rtl allowFraction SVGstyle={{ display: "inline-block" }} />
<span className="text-sm font-medium text-[#0A1B2C]">{PRODUCT_RATING}</span>
</div>
@@ -55,17 +55,19 @@ const ProductPurchaseOptions: FC<ProductPurchaseOptionsProps> = ({ selectedTier,
type="button"
onClick={() => onSelectTier(tier)}
className={cn(
"flex h-10 w-full items-center justify-between gap-2 rounded-xl border border-[#E9EEF2] px-3 transition-colors",
"flex min-h-10 w-full items-center justify-between gap-1.5 rounded-xl border border-[#E9EEF2] px-2.5 transition-colors sm:gap-2 sm:px-3",
isSelected ? "bg-secondary" : "bg-white hover:bg-secondary/50",
)}
>
<span className="w-6 shrink-0 text-end text-xs font-medium text-[#0A1B2C]">{tier.quantity}</span>
<span className="hidden w-6 shrink-0 text-end text-xs font-medium text-[#0A1B2C] sm:inline">{tier.quantity}</span>
<div className="flex min-w-0 flex-1 items-center justify-center gap-2">
<span className="text-[11px] text-[#0A1B2C] sm:text-xs">{formatPrice(tier.unitPrice)} / هر عدد</span>
<span className="text-xs font-medium text-[#0A1B2C]">{formatPrice(tier.totalPrice)}</span>
<div className="flex min-w-0 flex-1 items-center justify-between gap-1.5 sm:justify-center sm:gap-2">
<span className="text-[10px] text-[#0A1B2C] sm:text-xs">{formatPrice(tier.unitPrice)} / هر عدد</span>
<span className="text-[11px] font-medium text-[#0A1B2C] sm:text-xs">{formatPrice(tier.totalPrice)}</span>
</div>
<span className={cn("w-6 shrink-0 text-start text-xs font-medium", tier.discount ? "text-[#DC0000]" : "text-[#0A1B2C]")}>{tier.discount ? `-${tier.discount}%` : tier.quantity}</span>
<span className={cn("w-8 shrink-0 text-start text-[10px] font-medium sm:w-6 sm:text-xs", tier.discount ? "text-[#DC0000]" : "text-[#0A1B2C]")}>
{tier.discount ? `-${tier.discount}%` : tier.quantity}
</span>
</button>
);
})}
+1 -1
View File
@@ -5,7 +5,7 @@ import { RELATED_PRODUCTS } from "../constants";
const ProductRelated: FC = () => {
return (
<section className="mt-10 px-4 sm:mt-12 sm:px-8 lg:px-30">
<section className="mt-8 px-4 sm:mt-10 sm:px-8 lg:mt-12 lg:px-30">
<Carousel slidesPerView={{ base: 1.4, md: 3, lg: 5 }} gap={{ base: 12, md: 16, lg: 24 }}>
<div className="flex items-center justify-between gap-4">
<h2 className="text-lg font-bold text-[#0A1B2C] sm:text-xl">محصولات مرتبط</h2>