-
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): List, ListItem, ListItemImage 컴포넌트 추가 (#45)
* feat(ui-kit): 리스트 기본 모양 잡음 * feat(ui-kit): 리스트에 left, right area 추가 * feat(ui-kit): 리스트 스토리북 수정
- Loading branch information
Showing
9 changed files
with
307 additions
and
2 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,57 @@ | ||
import React, { HTMLAttributes, forwardRef, ReactNode } from 'react'; | ||
import classnames from 'classnames'; | ||
import { Combine } from 'src/types/utils'; | ||
import Text from '../Text'; | ||
|
||
type Props = Combine< | ||
{ | ||
left?: ReactNode; | ||
right?: ReactNode; | ||
title?: string; | ||
content: string; | ||
caption?: string; | ||
}, | ||
Omit<HTMLAttributes<HTMLLIElement>, 'children' | 'role'> | ||
>; | ||
const ListItem = forwardRef<HTMLLIElement, Props>(function ListItem( | ||
{ className, left, right, title, content, caption, onClick, ...props }, | ||
ref | ||
) { | ||
const isClickable = onClick != null; | ||
|
||
return ( | ||
<li | ||
ref={ref} | ||
className={classnames( | ||
'lubycon-list__item', | ||
{ | ||
'lubycon-list__item--clickable': isClickable, | ||
}, | ||
className | ||
)} | ||
onClick={onClick} | ||
role="listitem" | ||
{...props} | ||
> | ||
{left ? <div className="lubycon-list__item__left">{left}</div> : null} | ||
<div className="lubycon-list__item__center"> | ||
{title ? ( | ||
<Text className="lubycon-list__item__center__title" fontWeight="bold"> | ||
{title} | ||
</Text> | ||
) : null} | ||
<Text className="lubycon-list__item__center__content" typography="p2"> | ||
{content} | ||
</Text> | ||
{caption ? ( | ||
<Text className="lubycon-list__item__center__caption" typography="caption"> | ||
{caption} | ||
</Text> | ||
) : null} | ||
</div> | ||
{right ? <div className="lubycon-list__item__right">{right}</div> : null} | ||
</li> | ||
); | ||
}); | ||
|
||
export default ListItem; |
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,22 @@ | ||
import React, { ImgHTMLAttributes } from 'react'; | ||
import classnames from 'classnames'; | ||
|
||
const ListItemImage = ({ | ||
className, | ||
src, | ||
alt, | ||
tabIndex, | ||
...props | ||
}: ImgHTMLAttributes<HTMLImageElement>) => ( | ||
<div | ||
className={classnames('lubycon-list__item__image', className)} | ||
style={{ backgroundImage: `url(${src})` }} | ||
role="img" | ||
aria-label={alt} | ||
tabIndex={tabIndex} | ||
> | ||
<img src={src} alt={alt} tabIndex={-1} {...props} /> | ||
</div> | ||
); | ||
|
||
export default ListItemImage; |
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,18 @@ | ||
import React, { HTMLAttributes, forwardRef } from 'react'; | ||
import classnames from 'classnames'; | ||
|
||
type Props = Omit<HTMLAttributes<HTMLUListElement>, 'role'>; | ||
const List = forwardRef<HTMLUListElement, Props>(function List( | ||
{ children, className, ...props }, | ||
ref | ||
) { | ||
return ( | ||
<ul ref={ref} className={classnames('lubycon-list', className)} role="list" {...props}> | ||
{children} | ||
</ul> | ||
); | ||
}); | ||
|
||
export default List; | ||
export { default as ListItem } from './ListItem'; | ||
export { default as ListItemImage } from './ListItemImage'; |
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,69 @@ | ||
.lubycon-list { | ||
padding: 0; | ||
margin: 0; | ||
display: flex; | ||
flex-direction: column; | ||
} | ||
|
||
.lubycon-list__item { | ||
display: flex; | ||
align-items: center; | ||
list-style: none; | ||
margin: 0; | ||
padding: 13px 0; | ||
& + & { | ||
border-top: 1px solid get-color('gray20'); | ||
} | ||
&--clickable { | ||
transition: background-color 0.1s ease-in-out; | ||
cursor: pointer; | ||
&:hover { | ||
background-color: get-color('gray10'); | ||
} | ||
&:active { | ||
background-color: get-color('gray20'); | ||
} | ||
} | ||
|
||
&__left { | ||
padding-left: 12px; | ||
width: auto; | ||
flex: 0 0 auto; | ||
} | ||
&__center { | ||
padding: 0 16px; | ||
display: flex; | ||
flex-direction: column; | ||
flex-grow: 1; | ||
&__title { | ||
color: get-color('gray90'); | ||
} | ||
&__content { | ||
-webkit-box-orient: vertical; | ||
-webkit-line-clamp: 2; | ||
display: -webkit-box; | ||
overflow: hidden; | ||
} | ||
&__caption { | ||
margin-top: 4px; | ||
color: get-color('gray60'); | ||
} | ||
} | ||
&__right { | ||
padding-right: 8px; | ||
} | ||
|
||
&__image { | ||
position: relative; | ||
width: 48px; | ||
height: 48px; | ||
border-radius: 4px; | ||
overflow: hidden; | ||
background-repeat: no-repeat; | ||
background-size: cover; | ||
background-position: 50% 50%; | ||
> img { | ||
display: none; | ||
} | ||
} | ||
} |
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 |
---|---|---|
|
@@ -14,4 +14,5 @@ | |
@import './Card'; | ||
@import './Snackbar'; | ||
@import './Container'; | ||
@import './List'; | ||
@import './Input'; |
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,138 @@ | ||
import React from 'react'; | ||
import { Button, List, ListItem } from 'src'; | ||
import { Meta } from '@storybook/react/types-6-0'; | ||
import { ListItemImage } from 'src/components/List'; | ||
import Icon from 'src/components/Icon'; | ||
import { chevronForward } from 'ionicons/icons'; | ||
import { colors } from 'src/constants/colors'; | ||
|
||
export default { | ||
title: 'Lubycon UI Kit/List', | ||
} as Meta; | ||
|
||
const DummyItem = ({ onClick }: { onClick?: () => void }) => ( | ||
<ListItem | ||
title="리스트 제목" | ||
content="여기에 내용이 들어갑니다" | ||
caption="캡션입니다" | ||
onClick={onClick} | ||
/> | ||
); | ||
const DummyItemWithoutCaption = () => ( | ||
<ListItem title="리스트 제목" content="여기에 내용이 들어갑니다" /> | ||
); | ||
const DummyItemWithoutTitle = () => ( | ||
<ListItem content="여기에 내용이 들어갑니다" caption="캡션입니다" /> | ||
); | ||
const noop = () => {}; | ||
|
||
export const Default = () => { | ||
return ( | ||
<List> | ||
<ListItem title="루비콘 UI Kit" content="리스트 컴포넌트" caption="5일전" /> | ||
<DummyItem /> | ||
<DummyItem /> | ||
<DummyItem /> | ||
<DummyItem /> | ||
</List> | ||
); | ||
}; | ||
|
||
export const WithoutCaption = () => { | ||
return ( | ||
<List> | ||
<ListItem title="루비콘 UI Kit" content="리스트 컴포넌트" /> | ||
<DummyItemWithoutCaption /> | ||
<DummyItemWithoutCaption /> | ||
<DummyItemWithoutCaption /> | ||
<DummyItemWithoutCaption /> | ||
</List> | ||
); | ||
}; | ||
|
||
export const WithoutTitle = () => { | ||
return ( | ||
<List> | ||
<ListItem content="리스트 컴포넌트" caption="5일전" /> | ||
<DummyItemWithoutTitle /> | ||
<DummyItemWithoutTitle /> | ||
<DummyItemWithoutTitle /> | ||
<DummyItemWithoutTitle /> | ||
</List> | ||
); | ||
}; | ||
|
||
export const LeftRight = () => { | ||
return ( | ||
<List> | ||
<ListItem | ||
left={<ListItemImage src="http://cogulmars.cafe24.com/img/04about_img01.png" />} | ||
title="썸네일 조합형" | ||
content="UI Kit에서 제공되는 이미지 컴포넌트를 사용한 예시입니다" | ||
/> | ||
<ListItem | ||
left={<ListItemImage src="http://cogulmars.cafe24.com/img/04about_img01.png" />} | ||
title="썸네일 조합형" | ||
content="UI Kit에서 제공되는 이미지 컴포넌트를 사용한 예시입니다" | ||
caption="5일전" | ||
/> | ||
<ListItem | ||
left={ | ||
<img | ||
src="http://cogulmars.cafe24.com/img/04about_img01.png" | ||
style={{ width: 48, borderRadius: 4 }} | ||
/> | ||
} | ||
title="썸네일 조합형" | ||
content="일반 img 태그를 사용한 예시입니다" | ||
caption="5일전" | ||
/> | ||
<ListItem | ||
title="버튼 조합형" | ||
content="자세히 보려면 클릭하세요" | ||
right={<Icon icon={chevronForward} type="outline" size={24} color={colors.gray60} />} | ||
onClick={noop} | ||
/> | ||
<ListItem | ||
title="버튼 조합형 자유" | ||
content="자세히 보려면 클릭하세요" | ||
right={<Button size="small">보러가기</Button>} | ||
/> | ||
<ListItem | ||
left={<ListItemImage src="http://cogulmars.cafe24.com/img/04about_img01.png" />} | ||
title="썸네일 + 버튼 조합형" | ||
content="자세히 보려면 클릭하세요" | ||
right={<Icon icon={chevronForward} type="outline" size={24} color={colors.gray60} />} | ||
onClick={noop} | ||
/> | ||
</List> | ||
); | ||
}; | ||
|
||
export const Clickable = () => { | ||
return ( | ||
<List> | ||
<ListItem title="루비콘 UI Kit" content="리스트 컴포넌트" caption="5일전" onClick={noop} /> | ||
<DummyItem onClick={noop} /> | ||
<DummyItem onClick={noop} /> | ||
<DummyItem onClick={noop} /> | ||
<DummyItem onClick={noop} /> | ||
</List> | ||
); | ||
}; | ||
|
||
export const Multiline = () => { | ||
return ( | ||
<List style={{ maxWidth: 375 }}> | ||
<ListItem | ||
title="루비콘 UI Kit" | ||
content="리스트 컴포넌트의 내용이 두 줄이 넘어가면 말줄임으로 처리됩니다. 루비콘 UI kit 은 오픈소스로 배포되는 한국형 라이브러리입니다" | ||
caption="5일전" | ||
/> | ||
<DummyItem /> | ||
<DummyItem /> | ||
<DummyItem /> | ||
<DummyItem /> | ||
</List> | ||
); | ||
}; |