Skip to content

Commit

Permalink
fix: ImageModal, Carousel 수정 (#269)
Browse files Browse the repository at this point in the history
  • Loading branch information
shinhyojeong committed Feb 1, 2024
2 parents 078875b + cd1d94a commit 320c875
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 52 deletions.
11 changes: 11 additions & 0 deletions .changeset/neat-zebras-yell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@offer-ui/react": patch
---

- Carousel
- onClick, 화살표 클릭시에는 동작하지 않도록 수정
- tablet, mobile에서 인디케이터 클릭시 동작하지 않는 이슈 수정
- src -> url로 변경
- ImageModal
- 처음에 이미지 위치 잡지 못하는 이슈 수정
- src -> url로 변경
6 changes: 3 additions & 3 deletions packages/react/src/components/Carousel/Carousel.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ export default meta
export const Default: StoryObj<CarouselProps> = {
args: {
images: [
{ id: 1, src: 'https://picsum.photos/400' },
{ id: 2, src: 'https://picsum.photos/400' },
{ id: 3, src: 'https://picsum.photos/400' }
{ id: 1, url: 'https://picsum.photos/400' },
{ id: 2, url: 'https://picsum.photos/400' },
{ id: 3, url: 'https://picsum.photos/400' }
],
isArrow: true,
name: 'products',
Expand Down
65 changes: 38 additions & 27 deletions packages/react/src/components/Carousel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,20 @@ import { useMedia } from '@offer-ui/hooks/useMedia'
import type { ForwardedRef, HTMLAttributes, TouchEventHandler } from 'react'
import { forwardRef, useEffect, useState } from 'react'

type ImageInfo = {
id: number
url: string
}

export type CarouselProps = {
/** Carousel 컴포넌트에 들어갈 이미지들을 정합니다.
* @type { src: string, id: number } []
* @type ImageInfo []
*/
images: ImageInfo[]
/** Carousel 에서 처음에 보여줄 이미지를 선택합니다.
* @type number
*/
images: { src: string; id: number }[]
selectedIndex: number
/** Carousel 컴포넌트에 화살표의 유무를 정합니다.
* @type boolean
*/
Expand All @@ -23,9 +32,13 @@ export type CarouselProps = {
*/
name: string
/** Carousel 내에 Image 클릭시 실행할 함수를 지정합니다.
* @type (): void | undefined
*/
onClickImage?(): void
/** Carousel 내에 Indicator가 변할 때 실행할 함수를 지정합니다.
* @type (index: number): void | undefined
*/
onClick?(index: number): void
onChangeIndicator?(index: number): void
} & HTMLAttributes<HTMLDivElement>

type SliderProps = {
Expand Down Expand Up @@ -54,12 +67,21 @@ const FULL_SCREEN_WIDTH = 100
const USER_DRAG_LENGTH = 100

export const Carousel = forwardRef(function Carousel(
{ images = [], isArrow, size = 687, name, onClick, ...props }: CarouselProps,
{
images = [],
isArrow,
size = 687,
selectedIndex,
name,
onClickImage,
onChangeIndicator,
...props
}: CarouselProps,
ref: ForwardedRef<HTMLDivElement>
) {
const { desktop } = useMedia()
const carouselWidthSize = desktop ? size : FULL_SCREEN_WIDTH
const [currentIndex, setCurrentIndex] = useState<number>(0)
const [currentIndex, setCurrentIndex] = useState<number>(selectedIndex)
const [startClientX, setStartClientX] = useState<number>(0)
const [endClientX, setEndClientX] = useState<number>(0)
const [cursorOn, setCursorOn] = useState<boolean>(false)
Expand All @@ -70,13 +92,16 @@ export const Carousel = forwardRef(function Carousel(

const handleIndicator = (idx: number): void => {
setCurrentIndex(idx)
onChangeIndicator?.(idx)
}

const handleOffset: HandleOffset = navType => {
const { LEFT } = NAV_TYPE
const goPrev = navType === LEFT
const nextIndex = goPrev ? currentIndex - 1 : currentIndex + 1

setCurrentIndex(goPrev ? currentIndex - 1 : currentIndex + 1)
setCurrentIndex(nextIndex)
onChangeIndicator?.(nextIndex)
}

const handleTouchStart: TouchEventHandler<HTMLDivElement> = e => {
Expand Down Expand Up @@ -118,23 +143,21 @@ export const Carousel = forwardRef(function Carousel(
onTouchStart={handleTouchStart}>
<StyledImageBox
currentTranslateX={currentTranslateX}
onClick={(): void => onClick?.(currentIndex)}>
onClick={(): void => onClickImage?.()}>
{images.map(image => {
return (
<StyledImage
key={image.id}
alt={`${name}- ${image.id}`}
size={carouselWidthSize}
src={image.src}
src={image.url}
/>
)
})}
</StyledImageBox>
{isArrow && hasImages && (
<>
{isFirstImage ? (
<div />
) : (
{!isFirstImage && (
<StyledLeftArrow
type="button"
onClick={(): void => {
Expand All @@ -143,9 +166,7 @@ export const Carousel = forwardRef(function Carousel(
<Icon size={40} type="chevronLeft" />
</StyledLeftArrow>
)}
{isLastImage ? (
<div />
) : (
{!isLastImage && (
<StyledRightArrow
type="button"
onClick={(): void => {
Expand Down Expand Up @@ -248,25 +269,13 @@ const StyledImage = styled(Image)<ImageProps>`
}
`

export const StyledArrowBox = styled.div`
position: absolute;
top: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: space-between;
align-items: center;
${({ theme }): string => theme.mediaQuery.tablet} {
display: none;
}
`

const StyledRightArrow = styled.button`
position: absolute;
top: 50%;
right: 0;
width: 40px;
height: 60px;
z-index: ${({ theme }): number => theme.zIndex.common};
border: none;
transform: translate(0, -50%);
background-color: ${({ theme }): string => theme.colors.white};
Expand All @@ -279,6 +288,8 @@ const StyledLeftArrow = styled.button`
left: 0;
width: 40px;
height: 60px;
z-index: ${({ theme }): number => theme.zIndex.common};
border: none;
transform: translate(0, -50%);
background-color: ${({ theme }): string => theme.colors.white};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ export const Default: StoryObj<ImageModal> = {
images: [
{
id: 1,
src: 'errorImage'
url: 'errorImage'
},
{
id: 2,
src: 'http://placekitten.com/500/600'
url: 'http://placekitten.com/500/600'
},
{
id: 3,
src: 'http://placekitten.com/400/800'
url: 'http://placekitten.com/400/800'
}
],
name: 'cat-detail'
Expand Down
38 changes: 19 additions & 19 deletions packages/react/src/components/ImageModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { createPortal } from 'react-dom'

type ImageInfo = {
id: number
src: string
url: string
}
export type ImageModalProps = {
/**
Expand All @@ -20,14 +20,14 @@ export type ImageModalProps = {
isOpen?: boolean
/**
* ImageModal에 띄울 이미지들을 정합니다.
* @type IconType
* @type ImageInfo
*/
images: ImageInfo[]
/**
* ImageModal의 처음 띄워줄 이미지 index를 지정합니다.
* @type number | undefined
*/
initIndex?: number
selectedIndex?: number
/**
* ImageModal의 이름을 정합니다.
* @type string
Expand Down Expand Up @@ -77,17 +77,17 @@ const calculateSizeRate = (width: number, height: number): number =>

export const ImageModal = forwardRef(function ImageModal(
{
onClose,
initIndex = 0,
selectedIndex = 0,
images = [],
isOpen = false,
name,
onClose,
...props
}: ImageModalProps,
ref: ForwardedRef<HTMLDivElement>
) {
const imagesInfo = useRef<ResizeImageInfo[]>([])
const [currentIndex, setCurrentIndex] = useState<number>(initIndex)
const [currentIndex, setCurrentIndex] = useState<number>(selectedIndex)
const startClientX = useRef<number | null>(null)
const topElement = useRef<HTMLDivElement | null>(null)
const hasImages = images.length > 0
Expand All @@ -110,20 +110,20 @@ export const ImageModal = forwardRef(function ImageModal(
}, [images])

useEffect(() => {
isOpen && setCurrentIndex(initIndex)
}, [isOpen])
setCurrentIndex(selectedIndex)
}, [isOpen, selectedIndex])

const getImagesInfo = async (): Promise<void> => {
const fulfilledImages = images.map(({ src, id }) => {
const fulfilledImages = images.map(({ url, id }) => {
const image = new Image()
image.src = src
image.src = url

return new Promise(resolve => {
image.onload = (): void => {
resolve({
height: image.height,
id,
src,
url,
width: (image.width * DEFAULT_RESIZE_IMAGE.HEIGHT) / image.height
})
}
Expand All @@ -132,7 +132,7 @@ export const ImageModal = forwardRef(function ImageModal(
resolve({
height: DEFAULT_RESIZE_IMAGE.HEIGHT,
id,
src: null,
url: null,
width: DEFAULT_RESIZE_IMAGE.WIDTH
})
}
Expand Down Expand Up @@ -161,7 +161,7 @@ export const ImageModal = forwardRef(function ImageModal(
}

return sumImageWidth
}, [currentIndex])
}, [currentIndex, imagesInfo.current, selectedIndex])

const handleClickIndicator = (idx: number): void => {
setCurrentIndex(idx)
Expand Down Expand Up @@ -211,15 +211,15 @@ export const ImageModal = forwardRef(function ImageModal(
ref={ref}
currentIndex={currentIndex}
currentTranslateX={currentTranslateX}>
{imagesInfo.current.map(({ src, id, width, height }) => (
{imagesInfo.current.map(({ url, id, width, height }) => (
<StyledImage
key={id}
alt={`${name}-${id}`}
height={`${height}px`}
isFixedHeight={
calculateSizeRate(width, height) < IMAGE_MAX_RATE
}
src={src}
src={url}
width={`${width}px`}
/>
))}
Expand Down Expand Up @@ -273,15 +273,15 @@ const StyledImageContainer = styled.div<StyledImageContainerProps>`
${({ theme }): string => theme.mediaQuery.mobile} {
transform: translate(0, 0);
gap: 0;
transform: ${({ currentIndex }): SerializedStyles =>
css`translate(-${currentIndex * 100}vw, 0);`};
transform: ${({ currentIndex }): string =>
`translate(-${currentIndex * 100}vw, 0)`};
}
${({ theme }): string => theme.mediaQuery.tablet} {
transform: translate(0, 0);
gap: 0;
transform: ${({ currentIndex }): SerializedStyles =>
css`translate(-${currentIndex * 100}vw, 0);`};
transform: ${({ currentIndex }): string =>
`translate(-${currentIndex * 100}vw, 0)`};
}
`

Expand Down
1 change: 1 addition & 0 deletions packages/react/src/styles/themes/zIndex.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export type ZIndex = typeof zIndex

export const zIndex = {
common: 100,
modal: 300,
modalIcon: 400,
selectbox: 200
Expand Down

0 comments on commit 320c875

Please sign in to comment.