Components / Layout & List
List Row
리스트 아이템의 한 행을 구성하는 컴포넌트입니다. Prefix(아이콘/이미지), 텍스트 영역, Suffix(액션/값)를 조합합니다.
사용법
ListRow는 Prefix + Text + Suffix의 3-슬롯 구조입니다. 각 슬롯은 선택적으로 사용할 수 있습니다.
작품 제목
작가명 · 유화
<ListRow>
<ListRow.Prefix>
<Asset shape="rounded" size={40} />
</ListRow.Prefix>
<ListRow.Text title="작품 제목" subtitle="작가명 · 유화" />
<ListRow.Suffix><ChevronIcon /></ListRow.Suffix>
</ListRow> <div style="display:flex;align-items:center;padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--border);gap:var(--space-3);cursor:pointer;transition:background var(--dur-fast)">
<div style="width:40px;height:40px;background:var(--alpha-4);flex-shrink:0"></div>
<div style="flex:1;min-width:0">
<div style="font-size:var(--text-sm);font-weight:600;color:var(--charcoal)">List Item Title</div>
<div style="font-size:var(--text-xs);color:var(--text-muted)">Subtitle or description</div>
</div>
<span class="ch-badge ch-badge--green">Active</span>
</div> Prefix 옵션
아이콘, 이미지 썸네일, 아바타 등 행의 왼쪽에 시각 요소를 배치합니다.
아이콘 Prefix
shape: rounded
아바타 Prefix
shape: circle
이미지 Prefix
shape: square
<ListRow.Prefix>
<Asset shape="rounded" size={40} icon={<DiamondIcon />} />
</ListRow.Prefix>
<ListRow.Prefix>
<Asset shape="circle" size={40} name="박수근" fallback="initial" />
</ListRow.Prefix> Text 영역 구성
title(주 텍스트)과 subtitle(보조 텍스트)로 구성됩니다. 각각 ellipsis 처리가 가능합니다.
Title Only
갤러리 이름
Title + Subtitle
작품 제목
작가명 · 유화 · 1954
Title + Subtitle + Badge
빨래터
Available박수근 · 유화
<ListRow.Text
title="빨래터"
subtitle="박수근 · 유화"
badge={<Badge color="green">Available</Badge>}
/> Suffix 옵션
행 오른쪽에 값, 액션, 화살표 등을 배치합니다.
Chevron (이동)
Value (값)
₩ 2,400,000Button (액션)
Toggle (스위치)
<ListRow.Suffix><ChevronIcon /></ListRow.Suffix> <ListRow.Suffix><span>₩ 2,400,000</span></ListRow.Suffix> <ListRow.Suffix><Button size="small">팔로우</Button></ListRow.Suffix>
접근성
ListRow는 리스트 아이템으로, 적절한 ARIA 속성과 키보드 탐색을 지원합니다.
| 속성 | 값 | 설명 |
|---|---|---|
role | "listitem" | 리스트의 한 항목임을 명시합니다. |
aria-label | "{title}" | 항목의 제목을 스크린 리더에 전달합니다. |
tabIndex | 0 | 클릭 가능한 행은 포커스 가능합니다. |
onClick | — | 터치/클릭 시 상세로 이동합니다. |
사용 방법 예시
작품 목록 화면에서 ListRow가 사용되는 모습입니다.
빨래터
박수근
어디서 무엇이 되어
김환기
소
이중섭
인터페이스
ListRow 및 서브 컴포넌트의 Props를 정의합니다.
ListRowProps
| 속성 | 필수 | 기본값 | 타입 | 설명 |
|---|---|---|---|---|
children | — | ReactNode | Prefix, Text, Suffix 서브 컴포넌트를 조합합니다. | |
onClick | — | — | () => void | 행 클릭 핸들러입니다. |
padding | — | 16 | number (px) | 좌우 패딩입니다. |
ListRow.Text
| 속성 | 필수 | 기본값 | 타입 | 설명 |
|---|---|---|---|---|
title | — | string | 주 텍스트입니다. | |
subtitle | — | — | string | 보조 텍스트입니다. |
badge | — | — | ReactNode | 제목 옆 뱃지입니다. |
ellipsis | — | 1 | number | 말줄임 줄 수입니다. |
ListRow.Prefix / ListRow.Suffix
| 속성 | 필수 | 기본값 | 타입 | 설명 |
|---|---|---|---|---|
children | — | ReactNode | 슬롯 내부 콘텐츠입니다. |
크기 (Size)
3단계 사이즈 스케일을 지원합니다. 기본값은 md입니다.
상태 (States)
ListRow의 인터랙션 상태입니다.
작품
작품
작품
작품
반응형 (Responsive)
브레이크포인트별 동작 변화입니다.
stacked, meta below
single row, truncated
full row, all columns
Components / Layout & List
List Header
리스트 그룹의 섹션 제목을 정의하며, titleType에 따라 Paragraph, TextButton, Selector 등 다양한 형태로 렌더링됩니다.
사용법
ListHeader는 리스트 상단에 섹션 제목과 부가 액션을 표시합니다. titleType에 따라 다양한 렌더링 모드를 지원합니다.
<ListHeader titleType="paragraph" title="추천 작품" description="CHAART가 선별한 이번 주 추천 작품입니다" />
<div class="ch-section-header">SECTION TITLE</div> <!-- Sub variant --> <div class="ch-section-header ch-section-header--sub">SUB SECTION</div>
Paragraph 타입
텍스트만으로 구성된 기본 헤더입니다. 타이틀과 설명문을 배치합니다.
Title Only
Title + Description
<ListHeader titleType="paragraph" title="추천 작품" /> <ListHeader titleType="paragraph" title="추천 작품" description="..." />
TextButton 타입
타이틀 오른쪽에 텍스트 버튼(더보기 등)을 배치합니다.
<ListHeader
titleType="textButton"
title="인기 작품"
buttonText="더보기"
onButtonClick={() => navigate('/popular')}
/> Selector 타입
타이틀 오른쪽에 드롭다운 또는 필터 셀렉터를 배치합니다.
<ListHeader
titleType="selector"
title="작품 목록"
selectorValue="최신순"
selectorOptions={['최신순', '인기순', '가격순']}
onSelectorChange={(v) => setSortBy(v)}
/> 설명 위치 (top / bottom)
description의 위치를 타이틀 위(top) 또는 아래(bottom)에 배치할 수 있습니다.
descriptionPosition: top
descriptionPosition: bottom (기본)
<ListHeader descriptionPosition="top" description="Park Soo-keun Collection" /> <ListHeader descriptionPosition="bottom" description="CHAART가 선별한 추천" />
접근성
ListHeader는 섹션의 제목 역할을 합니다.
| 속성 | 값 | 설명 |
|---|---|---|
role | "heading" | 섹션 제목 역할을 명시합니다. |
aria-level | "2" | 헤딩 레벨을 지정합니다. |
aria-label | "{title}" | 제목 텍스트를 스크린 리더에 전달합니다. |
사용 방법 예시
메인 화면에서 ListHeader로 섹션을 구분하는 모습입니다.
추천 작품
더보기최근 본 작품
인터페이스
ListHeader 컴포넌트의 Props를 정의합니다.
ListHeaderProps
| 속성 | 필수 | 기본값 | 타입 | 설명 |
|---|---|---|---|---|
titleType | — | paragraph | paragraph | textButton | selector | 헤더 타이틀 유형입니다. |
title | — | string | 섹션 타이틀 텍스트입니다. | |
description | — | — | string | 타이틀 보조 설명입니다. |
descriptionPosition | — | bottom | top | bottom | 설명 텍스트의 위치입니다. |
buttonText | — | — | string | textButton 타입에서 버튼 텍스트입니다. |
onButtonClick | — | — | () => void | textButton 클릭 핸들러입니다. |
selectorValue | — | — | string | selector 타입에서 현재 선택 값입니다. |
selectorOptions | — | — | string[] | selector 타입에서 옵션 목록입니다. |
padding | — | 24 | number (px) | 좌우 패딩입니다. |
Components / Layout & List
Top
페이지 상단의 헤더 영역입니다. 타이틀, 서브타이틀, 배지, 보조 액션 등을 포함하며 페이지의 진입점 역할을 합니다.
사용법
Top은 각 화면의 최상단에 1개만 배치됩니다. 타이틀 + 보조 요소 조합으로 페이지의 맥락을 설정합니다.
Park Soo-keun Collection
빨래터
Available박수근, 1954 · 유화
<Top
title="빨래터"
subtitle="박수근, 1954 · 유화"
subtitlePosition="bottom"
badge={{ color: 'green', children: 'Available' }}
>
<Top.SubtitleParagraph position="top">
Park Soo-keun Collection
</Top.SubtitleParagraph>
</Top> <div style="display:flex;align-items:center;justify-content:space-between;padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--border)"> <button style="background:none;border:none;cursor:pointer;padding:8px">←</button> <h1 style="font-size:var(--text-base);font-weight:700;margin:0">Page Title</h1> <button style="background:none;border:none;cursor:pointer;padding:8px">⋮</button> </div>
Simple Title
타이틀만 단독으로 사용하는 가장 기본적인 형태입니다.
페이지 제목
<Top title="페이지 제목" />
Subtitle 위치 (top / bottom)
subtitle이 top이면 카테고리/분류 정보를, bottom이면 부가 설명을 배치합니다.
Subtitle Top (카테고리)
카테고리 라벨
페이지 제목
Subtitle Bottom (설명)
빨래터
박수근, 1954 · 유화
<Top title="페이지 제목" subtitle="카테고리" subtitlePosition="top" /> <Top title="빨래터" subtitle="박수근, 1954" subtitlePosition="bottom" />
Badge 조합
타이틀과 같은 줄에 Badge를 배치하여 상태 정보(Available, VIP 등)를 표시합니다.
빨래터
Available박수근, 1954 · 유화
<Top
title="빨래터"
subtitle="박수근, 1954 · 유화"
badge={{ color: 'green', children: 'Available' }}
/> Right Asset + Lower CTA
우측 상단에 Asset(48×48), 하단에 CTA 버튼을 배치하는 확장형입니다.
컬렉션
12개 작품
<Top
title="컬렉션"
subtitle="12개 작품"
rightAsset={<Asset shape="rounded" size={48} />}
lowerCTA={{ children: '컬렉션 관리 →', variant: 'weak' }}
/> 접근성
Top은 페이지의 주제를 정의하며, 적절한 헤딩 레벨을 사용합니다.
| 속성 | 값 | 설명 |
|---|---|---|
role | "heading" | 타이틀이 페이지 헤딩 역할을 합니다. |
aria-level | "1" | 페이지 최상위 헤딩입니다. |
aria-label | "{title}" | 페이지 제목을 스크린 리더에 전달합니다. |
사용 방법 예시
작품 상세 화면에서 Top이 사용되는 모습입니다.
Park Soo-keun Collection
빨래터
Available박수근, 1954 · 유화
인터페이스
Top 컴포넌트의 Props를 정의합니다.
TopProps
| 속성 | 필수 | 기본값 | 타입 | 설명 |
|---|---|---|---|---|
title | — | string | 메인 타이틀 텍스트입니다. | |
subtitle | — | — | string | 부제 텍스트입니다. |
subtitlePosition | — | bottom | top | bottom | 부제의 위치입니다. |
badge | — | — | BadgeProps | 타이틀 옆에 표시될 Badge입니다. |
rightAsset | — | — | ReactNode | 우측 상단 Asset (48×48)입니다. |
lowerCTA | — | — | ButtonProps | 하단 CTA 버튼입니다. |
padding | — | 24 | number (px) | 좌우 패딩입니다. |
Components / Layout & List
Asset — 마켓 카드
CHAART 마켓의 핵심 자산 표시 패턴. sb-dp-market-grid · sb-dp-carousel · sb-dp-section-hd 3종 레이아웃과 chrt-save 찜 버튼으로 구성됩니다. MKT-001 / HOM-001에서 확정된 모노크롬 정보 위계.
마켓 그리드 .sb-dp-market-grid
마켓 메인 2열 고정 그리드. row-gap 28px, column-gap var(--space-4). 썸네일 aspect-ratio 1/1 필수. sb-dp-section-hd와 함께 사용합니다.
박수근 유화
Park Soo-Keun
72.7 × 60.6cm
2,400,000원
<ArtworkCard
image="/artwork.jpg"
artist="박수근"
artistEn="Park Soo-Keun"
category="유화"
size="72.7 × 60.6cm"
price="2,400,000원"
onWishlist={() => toggleWishlist(id)}
/> <div>
<div class="sb-dp-artwork-item__thumb">
<img src="/artwork.jpg" alt="작품명" style="width:100%;height:100%;object-fit:cover;">
<div class="chrt-save" onclick="this.classList.toggle('is-saved')" style="position:absolute;top:8px;right:8px;">
<svg width="18" height="18" ...></svg>
</div>
</div>
<div style="margin:8px 0 0;">
<p style="font-size:var(--size-md-font);font-weight:600;...">
작가명 <span style="font-size:var(--text-2xs);border:1px solid rgba(6,6,6,0.1);...">유화</span>
</p>
<p style="font-size:var(--size-xs-font);font-family:var(--serif);color:rgba(6,6,6,0.45);">Artist Name</p>
<p style="font-size:var(--size-xs-font);color:var(--alpha-40);">72.7 × 60.6cm</p>
<p style="font-size:var(--size-sm-font);font-weight:700;color:var(--charcoal);">12,000,000원</p>
</div>
</div> Vertical 레이아웃
이미지가 위, 텍스트가 아래에 배치되는 기본 레이아웃입니다. 그리드, 캐러셀에서 사용합니다.
박수근 유화
Park Soo-Keun
김환기 유화
Kim Whan-Ki
<ArtworkCard layout="vertical" /> {/* 기본값 */}
{/* 그리드: grid-template-columns: repeat(2, 1fr) */} Horizontal 레이아웃
이미지가 왼쪽, 텍스트가 오른쪽에 배치됩니다. 검색 결과, 찜 목록에서 사용합니다.
빨래터
박수근 · 유화 · 1954
₩ 2,400,000
<ArtworkCard layout="horizontal" />
{/* 이미지 80×80, 텍스트 flex: 1 */} 찜 버튼
이미지 우상단에 북마크 아이콘으로 찜 버튼을 오버레이합니다.
<ArtworkCard
isWishlisted={true}
onWishlist={() => toggleWishlist(id)}
/> 접근성
ArtworkCard는 클릭 가능한 카드로, 적절한 접근성을 제공합니다.
| 속성 | 값 | 설명 |
|---|---|---|
role | "article" | 독립적인 콘텐츠 단위를 표현합니다. |
aria-label | "{title} by {artist}" | 카드의 주요 정보를 전달합니다. |
tabIndex | 0 | 키보드 탐색에 포함됩니다. |
img alt | "{title}" | 작품 이미지의 대체 텍스트입니다. |
사용 방법 예시
메인 화면 추천 작품 그리드에서 ArtworkCard가 사용되는 모습입니다.
추천 작품
박수근
Park Soo-Keun
김환기
Kim Whan-Ki
인터페이스
ArtworkCard 컴포넌트의 Props를 정의합니다.
ArtworkCardProps
| 속성 | 필수 | 기본값 | 타입 | 설명 |
|---|---|---|---|---|
image | — | string | 작품 이미지 URL입니다. | |
artist | — | string | 작가명입니다. | |
artistEn | — | — | string | 작가 영문명 (캐러셀/상세용) |
category | — | — | string | 작품 카테고리 배지 (유화, 수채화 등) |
size | — | — | string | 작품 사이즈 (그리드용, 예: "72.7 × 60.6cm") |
price | — | — | string | 가격 텍스트입니다. |
layout | — | vertical | vertical | horizontal | 카드 레이아웃입니다. |
isWishlisted | — | false | boolean | 찜 상태입니다. |
onWishlist | — | — | () => void | 찜 토글 핸들러입니다. |
onClick | — | — | () => void | 카드 클릭 핸들러입니다. |
크기 (Size)
3단계 사이즈 스케일을 지원합니다. 기본값은 md입니다.
빨래터
박수근
빨래터
박수근 · 유화
빨래터
박수근 · 유화 · 1953
상태 (States)
ArtworkCard의 인터랙션 상태입니다.
빨래터
박수근
빨래터
박수근
빨래터
박수근
빨래터
박수근
반응형 (Responsive)
브레이크포인트별 동작 변화입니다.
1-col, full-width
작가명
작가명
2-col grid
3-col grid, max-content
Components / Layout & List
Board Row
게시판 및 매물 목록의 한 행을 구성하는 컴포넌트입니다. 좌측 썸네일, 제목, 설명, 보조 정보(가격, 날짜)를 포함합니다.
사용법
Board Row는 작품 매물 목록, 경매 리스트, 게시판 글 등에서 한 행의 정보를 구조적으로 표현합니다.
빨래터
박수근 · 유화 · 45.5 x 38cm
<BoardRow thumbnail="/images/artwork-01.jpg" title="빨래터" description="박수근 · 유화 · 45.5 x 38cm" price="12,000,000원" date="2일 전" />
<div style="display:flex;align-items:center;padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--border);gap:var(--space-3)">
<span style="font-family:var(--mono);font-size:var(--text-xs);color:var(--text-muted);width:32px">01</span>
<div style="flex:1;min-width:0">
<div style="font-size:var(--text-sm);font-weight:600;color:var(--charcoal)">게시글 제목</div>
</div>
<span style="font-size:var(--text-xs);color:var(--text-muted)">2024.01.15</span>
</div> 썸네일 유무
썸네일이 없는 경우 텍스트만으로 구성됩니다. 게시판 형태의 리스트에 적합합니다.
해질녘
김환기 · 유화
[공지] 2월 경매 일정 안내
관리자 · 2026.02.15
<!-- 썸네일 포함 -->
<BoardRow thumbnail="/images/art.jpg" title="해질녘" />
<!-- 썸네일 없음 (게시판형) -->
<BoardRow title="[공지] 2월 경매 일정 안내" showThumbnail={false} /> 하이라이트 (new / hot)
신규 등록, 인기 매물 등을 시각적으로 강조합니다. 좌측 컬러 바와 뱃지로 표현합니다.
군상
NEW이중섭 · 유화
산수화 병풍
HOT정선 · 수묵화
<BoardRow highlight="new" title="군상" /> <BoardRow highlight="hot" title="산수화 병풍" />
접근성
| 속성 | 값 | 설명 |
|---|---|---|
role | "listitem" | 목록 내 한 항목임을 명시합니다. |
aria-label | "{title}, {price}" | 작품명과 가격을 스크린 리더에 전달합니다. |
tabIndex | 0 | 키보드 탐색을 지원합니다. |
사용 방법 예시
박수근 · 유화
₩12,000,000
김환기 · 유화
₩8,500,000
이중섭 · 유화
₩25,000,000
인터페이스
BoardRowProps
| 속성 | 필수 | 기본값 | 타입 | 설명 |
|---|---|---|---|---|
title | — | string | 행의 제목 텍스트입니다. | |
description | — | — | string | 제목 아래 보조 설명입니다. |
thumbnail | — | — | string | 좌측 썸네일 이미지 URL입니다. |
showThumbnail | — | true | boolean | 썸네일 영역 표시 여부입니다. |
price | — | — | string | 가격 표시 텍스트입니다. |
date | — | — | string | 등록일 또는 경과 시간입니다. |
highlight | — | — | new | hot | 행 강조 유형입니다. |
onClick | — | — | () => void | 행 클릭 핸들러입니다. |
Components / Layout & List
Grid List
2~3열 그리드로 카드를 배치하는 리스트 컴포넌트입니다. 갤러리, 카탈로그, 작가 목록 등에 사용합니다.
사용법
Grid List는 카드형 아이템을 균등 그리드로 배치합니다. columns prop으로 열 수를 지정합니다.
빨래터
박수근
₩12,000,000
해질녘
김환기
₩8,500,000
<GridList columns={2} gap={12}>
<ArtworkCard title="빨래터" artist="박수근" price="₩12,000,000" />
<ArtworkCard title="해질녘" artist="김환기" price="₩8,500,000" />
</GridList> <div class="ch-grid ch-grid--3"> <div class="ch-card">Item 1</div> <div class="ch-card">Item 2</div> <div class="ch-card">Item 3</div> </div> <!-- Auto-fill responsive --> <div class="ch-grid ch-grid--auto"> <div class="ch-card">Auto Item</div> </div>
2열 / 3열
2열은 작품 상세 정보가 필요한 경우, 3열은 한눈에 많은 아이템을 보여줄 때 사용합니다.
2열 그리드
3열 그리드
<GridList columns={2}>...</GridList> {/* 작품 갤러리 */}
<GridList columns={3}>...</GridList> {/* 작가 목록, 카탈로그 */} 불균등 그리드
masonry prop을 활성화하면 아이템 높이에 따라 자연스럽게 배치됩니다. 다양한 크기의 작품 이미지에 적합합니다.
산수화
정물
인물화
풍경화
<GridList columns={2} masonry>
{artworks.map(art => (
<ArtworkCard key={art.id} {...art} />
))}
</GridList> 접근성
| 속성 | 값 | 설명 |
|---|---|---|
role | "list" | 그리드가 리스트임을 명시합니다. |
aria-label | "{title} 목록" | 리스트의 용도를 설명합니다. |
각 아이템 role | "listitem" | 각 카드는 리스트 아이템입니다. |
사용 방법 예시
빨래터
박수근
₩12M
해질녘
김환기
₩8.5M
군상
이중섭
Sold
무제
이우환
₩45M
인터페이스
GridListProps
| 속성 | 필수 | 기본값 | 타입 | 설명 |
|---|---|---|---|---|
columns | — | 2 | 2 | 3 | 4 | 그리드 열 수입니다. |
gap | — | 12 | number | 아이템 간 간격(px)입니다. |
masonry | — | false | boolean | 불균등 그리드(masonry) 모드입니다. |
children | — | ReactNode[] | 그리드에 배치할 카드 아이템입니다. | |
loading | — | false | boolean | 로딩 스켈레톤 표시 여부입니다. |
emptyMessage | — | "항목이 없습니다" | string | 아이템이 없을 때 표시할 메시지입니다. |