Skip to content

Commit

Permalink
[#75] Feat: 이미지 상세 모달 layout 수정 (#84)
Browse files Browse the repository at this point in the history
  • Loading branch information
hyeonjinan096 authored Mar 5, 2024
1 parent 661688d commit 383ea90
Show file tree
Hide file tree
Showing 9 changed files with 291 additions and 104 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"react-masonry-css": "^1.0.16",
"react-error-boundary": "^4.0.12",
"react-toastify": "^10.0.4",
"swiper": "^11.0.7",
"tailwind-merge": "^2.2.1"
},
"devDependencies": {
Expand Down
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions src/components/ImageDetailModal/ButtonWithIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { ButtonHTMLAttributes } from "react";
import { ReactNode } from "react";
import { LucideIcon } from "lucide-react";
import { cn } from "@/utils/tailwind";

interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
Icon: LucideIcon;
iconLabel: string;
children: ReactNode;
onClick: () => void;
isDisabled?: boolean;
}

const ButtonWithIcon = ({ Icon, iconLabel, children, onClick, isDisabled = false }: Props) => {
return (
<button
onClick={onClick}
disabled={isDisabled}
className={cn("flex flex-col items-center space-x-1 overflow-hidden text-icon sm:w-100pxr", {
"cursor-not-allowed opacity-40": isDisabled,
"cursor-pointer": !isDisabled,
})}
>
<Icon aria-label={iconLabel} />
<span className="mt-1 hidden text-xs sm:flex">{children}</span>
</button>
);
};

export default ButtonWithIcon;
67 changes: 0 additions & 67 deletions src/components/ImageDetailModal/TagNavigator.tsx

This file was deleted.

97 changes: 97 additions & 0 deletions src/components/ImageDetailModal/TagSlider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { useState, useRef, useEffect } from "react";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
import { Navigation } from "swiper/modules";
import SwiperCore from "swiper";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { cn } from "@/utils/tailwind";
import { TagDetail } from "@/types/tag";
import TagBadge from "../common/TagBadge";

interface Props {
tags: TagDetail[];
textSize?: string;
className?: string;
onClick?: () => void;
}

const TagSlider = ({ tags, textSize = "xs", className, onClick }: Props) => {
const [showPrevButton, setShowPrevButton] = useState(false);
const [showNextButton, setShowNextButton] = useState(true);
const [mainImageIndex, setMainImageIndex] = useState(0);

const navigationPrevRef = useRef<HTMLButtonElement>(null);
const navigationNextRef = useRef<HTMLButtonElement>(null);

const arrowButtonClasses = "absolute top-0 z-10 h-full from-background from-70%";

useEffect(() => {
SwiperCore.use([Navigation]);
}, []);

const handleBeforeInit = (swiper: SwiperCore) => {
const swiperNavigation = swiper.params.navigation;
if (swiperNavigation && typeof swiperNavigation !== "boolean" && swiper.navigation) {
swiperNavigation.prevEl = navigationPrevRef.current;
swiperNavigation.nextEl = navigationNextRef.current;
swiper.activeIndex = mainImageIndex;
swiper.navigation.update();
}
};

return (
<div className={cn("relative flex w-full bg-background px-20pxr py-10pxr", className)}>
<Swiper
slidesPerView={"auto"}
spaceBetween={27}
pagination={{
type: "fraction",
}}
navigation={{ prevEl: navigationPrevRef.current, nextEl: navigationNextRef.current }}
onBeforeInit={handleBeforeInit}
className="h-auto w-full"
onSlideChange={(event) => setMainImageIndex(event.activeIndex)}
onReachBeginning={() => {
setShowPrevButton(false);
}}
onReachEnd={() => {
setShowNextButton(false);
}}
onFromEdge={() => {
setShowPrevButton(true);
setShowNextButton(true);
}}
>
<button
className={cn(arrowButtonClasses, "bg-gradient-to-r pr-7pxr", {
hidden: !showPrevButton,
})}
ref={navigationPrevRef}
aria-label="이전으로 이동"
>
<ChevronLeft strokeWidth={1.5} />
</button>

{tags.map(({ name, id }) => (
<SwiperSlide key={id} className="w-fit cursor-pointer text-center text-text-primary">
<button onClick={onClick}>
<TagBadge content={name} className={`bg-primary px-2 py-1 text-${textSize}`} />
</button>
</SwiperSlide>
))}

<button
className={cn(arrowButtonClasses, "right-0 bg-gradient-to-l pl-7pxr", {
hidden: !showNextButton,
})}
ref={navigationNextRef}
aria-label="다음으로 이동"
>
<ChevronRight strokeWidth={1.5} />
</button>
</Swiper>
</div>
);
};

export default TagSlider;
Loading

0 comments on commit 383ea90

Please sign in to comment.