-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ui-kit): Accordion 컴포넌트 추가 (#47)
* feat(ui-kit): Accordion 컴포넌트 추가 * feat(ui-kit): 아코디언 라벨 스타일 수정 * feat(ui-kit): input 컴포넌트 가현님 피드백 적용 * feat(ui-kit): 아코디언 상태 변경 이벤트 추가
- Loading branch information
Showing
9 changed files
with
204 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import React, { forwardRef, HTMLAttributes, useEffect, useRef, useState } from 'react'; | ||
import { Combine } from 'src/types/utils'; | ||
import classnames from 'classnames'; | ||
import Icon from '../Icon'; | ||
import { chevronDown } from 'ionicons/icons'; | ||
import Text from '../Text'; | ||
import { useResizeObserver } from 'src/hooks/useResizeObserver'; | ||
import { colors } from 'src/constants/colors'; | ||
|
||
type Props = Combine< | ||
{ | ||
label: string; | ||
defaultOpen?: boolean; | ||
onChange?: (state: boolean) => void; | ||
onOpen?: () => void; | ||
onClose?: () => void; | ||
}, | ||
HTMLAttributes<HTMLDivElement> | ||
>; | ||
const Accordion = forwardRef<HTMLDivElement, Props>(function Accordion( | ||
{ label, className, children, defaultOpen = false, onChange, onOpen, onClose, ...props }, | ||
ref | ||
) { | ||
const [open, setOpen] = useState(defaultOpen); | ||
const contentRef = useRef<HTMLDivElement>(null); | ||
const [bodyHeight, setBodyHeight] = useState(0); | ||
|
||
const toggleContentOpen = () => { | ||
setOpen((state) => !state); | ||
}; | ||
|
||
const updateContentHeight = () => | ||
setBodyHeight(contentRef.current?.getBoundingClientRect().height ?? 0); | ||
|
||
useResizeObserver(contentRef, updateContentHeight); | ||
|
||
useEffect(() => { | ||
onChange?.(open); | ||
}, [open]); | ||
|
||
useEffect(() => { | ||
if (open === true) { | ||
onOpen?.(); | ||
} else { | ||
onClose?.(); | ||
} | ||
}, [open]); | ||
|
||
return ( | ||
<div | ||
ref={ref} | ||
className={classnames( | ||
'lubycon-accordion', | ||
{ | ||
'lubycon-accordion--opened': open, | ||
}, | ||
className | ||
)} | ||
{...props} | ||
> | ||
<div className="lubycon-accordion__label" onClick={toggleContentOpen} role="button"> | ||
<Icon | ||
icon={chevronDown} | ||
type="outline" | ||
size={20} | ||
className="lubycon-accordion__label__icon" | ||
color={colors.gray90} | ||
/> | ||
<Text typography="subtitle" className="lubycon-accordion__label__text"> | ||
{label} | ||
</Text> | ||
</div> | ||
<div className="lubycon-accordion__cover" style={{ height: open ? bodyHeight : 0 }}> | ||
<div | ||
className="lubycon-accordion__cover__content" | ||
style={{ opacity: open ? 1 : 0 }} | ||
ref={contentRef} | ||
> | ||
{children} | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
}); | ||
|
||
export default Accordion; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { RefObject, useEffect, useRef } from 'react'; | ||
import ResizeObserver from 'resize-observer-polyfill'; | ||
|
||
export function useResizeObserver( | ||
ref: RefObject<HTMLElement>, | ||
resizeCallback: (arg: ResizeObserverEntry['contentRect']) => void | ||
) { | ||
const resizeObsesrverRef = useRef<ResizeObserver | null>(null); | ||
const onResize = useRef(resizeCallback); | ||
|
||
useEffect(() => { | ||
if (ref.current === null) { | ||
return; | ||
} | ||
|
||
resizeObsesrverRef.current = new ResizeObserver((entries) => { | ||
onResize.current(entries[0].contentRect); | ||
}); | ||
resizeObsesrverRef.current.observe(ref.current); | ||
|
||
return () => resizeObsesrverRef.current?.disconnect(); | ||
}, [ref]); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
$animation-duration: 0.3s ease-in-out; | ||
|
||
.lubycon-accordion { | ||
border: { | ||
top: 1px solid get-color('gray20'); | ||
bottom: 1px solid get-color('gray20'); | ||
} | ||
& + & { | ||
border-top: none; | ||
} | ||
&--opened { | ||
.lubycon-accordion__label__icon { | ||
transform: rotate(180deg); | ||
} | ||
} | ||
&__label { | ||
display: flex; | ||
align-items: center; | ||
padding: 16px; | ||
user-select: none; | ||
cursor: pointer; | ||
transition: background-color 0.1s ease-in-out; | ||
&:hover { | ||
background-color: get-color('gray10'); | ||
} | ||
&__icon { | ||
margin-right: 16px; | ||
transition: transform $animation-duration; | ||
} | ||
&__text { | ||
color: get-color('gray90'); | ||
} | ||
} | ||
&__cover { | ||
transition: height $animation-duration; | ||
overflow: hidden; | ||
&__content { | ||
padding: 8px 16px 16px 50px; | ||
transition: opacity $animation-duration; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
@import './Accordion'; | ||
@import './Alert'; | ||
@import './Button'; | ||
@import './Text'; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import React from 'react'; | ||
import { Accordion } from 'src'; | ||
import { Meta } from '@storybook/react/types-6-0'; | ||
|
||
export default { | ||
title: 'Lubycon UI Kit/Accordion', | ||
} as Meta; | ||
|
||
export const Default = () => { | ||
return ( | ||
<> | ||
<Accordion | ||
label="👀 텍스트가 숨겨져 있어요" | ||
onChange={(v) => console.log(`onChange: ${v}`)} | ||
onOpen={() => console.log('handleOpen')} | ||
onClose={() => console.log('handleClose')} | ||
> | ||
아코디언이 펼쳐지면 아래에 내용이 나옵니다. | ||
<br /> | ||
아코디언이 펼쳐지면 아래에 내용이 나옵니다. | ||
<br /> | ||
아코디언이 펼쳐지면 아래에 내용이 나옵니다. | ||
<br /> | ||
</Accordion> | ||
<Accordion label="🔥 이미지가 숨겨져 있어요"> | ||
<img | ||
src="http://cogulmars.cafe24.com/img/04about_img01.png" | ||
alt="귀여운 에비츄" | ||
width="300" | ||
/> | ||
</Accordion> | ||
<Accordion label="제목을 입력하세요"> | ||
아코디언이 펼쳐지면 아래에 내용이 나옵니다. | ||
<br /> | ||
아코디언이 펼쳐지면 아래에 내용이 나옵니다. | ||
<br /> | ||
아코디언이 펼쳐지면 아래에 내용이 나옵니다. | ||
<br /> | ||
</Accordion> | ||
</> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters