feat: refine storefront product and sale sections
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { Children, useRef } from "react";
|
||||
import { Children, useRef, useState } from "react";
|
||||
import { Swiper, SwiperSlide } from "swiper/react";
|
||||
import { FreeMode } from "swiper/modules";
|
||||
import type { Swiper as SwiperClass } from "swiper";
|
||||
@@ -10,6 +10,7 @@ import "swiper/css/free-mode";
|
||||
type CarouselProps = {
|
||||
children: React.ReactNode;
|
||||
ariaLabel: string;
|
||||
slideClassName?: string;
|
||||
};
|
||||
|
||||
function ChevronLeftIcon() {
|
||||
@@ -40,11 +41,12 @@ function ChevronRightIcon() {
|
||||
);
|
||||
}
|
||||
|
||||
export function Carousel({ children, ariaLabel }: CarouselProps) {
|
||||
export function Carousel({ children, ariaLabel, slideClassName }: CarouselProps) {
|
||||
const swiperRef = useRef<SwiperClass | null>(null);
|
||||
const [isLocked, setIsLocked] = useState(false);
|
||||
|
||||
const btnClass =
|
||||
"absolute top-1/2 z-10 flex h-10 w-10 -translate-y-1/2 items-center justify-center rounded-full border border-white/40 bg-white/40 text-red shadow-sm backdrop-blur-md transition-colors hover:border-red/40 hover:bg-white/60 hover:text-red-dark";
|
||||
"absolute top-1/2 z-10 flex h-10 w-10 -translate-y-1/2 items-center justify-center rounded-full border border-white/40 bg-white/40 text-red shadow-sm backdrop-blur-md transition-colors hover:border-red/40 hover:bg-white/60 hover:text-red-dark disabled:pointer-events-none disabled:opacity-0";
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
@@ -52,6 +54,7 @@ export function Carousel({ children, ariaLabel }: CarouselProps) {
|
||||
type="button"
|
||||
onClick={() => swiperRef.current?.slidePrev()}
|
||||
aria-label="قبلی"
|
||||
disabled={isLocked}
|
||||
className={`${btnClass} right-1`}
|
||||
>
|
||||
<ChevronRightIcon />
|
||||
@@ -60,6 +63,7 @@ export function Carousel({ children, ariaLabel }: CarouselProps) {
|
||||
type="button"
|
||||
onClick={() => swiperRef.current?.slideNext()}
|
||||
aria-label="بعدی"
|
||||
disabled={isLocked}
|
||||
className={`${btnClass} left-1`}
|
||||
>
|
||||
<ChevronLeftIcon />
|
||||
@@ -68,10 +72,17 @@ export function Carousel({ children, ariaLabel }: CarouselProps) {
|
||||
modules={[FreeMode]}
|
||||
onSwiper={(swiper) => {
|
||||
swiperRef.current = swiper;
|
||||
setIsLocked(swiper.isLocked);
|
||||
}}
|
||||
onLock={(swiper) => {
|
||||
swiper.slideTo(0, 0);
|
||||
setIsLocked(true);
|
||||
}}
|
||||
onUnlock={() => setIsLocked(false)}
|
||||
dir="rtl"
|
||||
slidesPerView="auto"
|
||||
spaceBetween={16}
|
||||
watchOverflow
|
||||
freeMode={{ enabled: true, momentum: true, sticky: true }}
|
||||
grabCursor
|
||||
role="region"
|
||||
@@ -83,7 +94,12 @@ export function Carousel({ children, ariaLabel }: CarouselProps) {
|
||||
// wrapper height — resolves per-slide instead of stretching to match
|
||||
// the tallest sibling. height:auto (inline, so it wins) lets normal
|
||||
// flex stretch equalize card heights across a row.
|
||||
<SwiperSlide style={{ width: "auto", height: "auto" }}>{child}</SwiperSlide>
|
||||
<SwiperSlide
|
||||
className={slideClassName}
|
||||
style={slideClassName ? { height: "auto" } : { width: "auto", height: "auto" }}
|
||||
>
|
||||
{child}
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user