Components / Media
Asset
이미지, 아이콘, 아바타 등을 표시하는 미디어 래퍼 컴포넌트입니다. 다양한 shape와 fallback 처리를 지원합니다.
사용법
Asset은 작품 썸네일, 작가 프로필, 갤러리 아이콘 등 다양한 미디어를 일관된 형태로 표시합니다.
<Asset shape="rounded" size={64} src="/artwork.jpg" />
<Asset shape="circle" size={64} src="/artist.jpg" />
<Asset shape="square" size={64} src="/gallery.jpg" />
<div style="width:48px;height:48px;background:var(--alpha-4);display:flex;align-items:center;justify-content:center"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="var(--text-muted)" stroke-width="1.5"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg> </div>
Shape: square / rounded / circle
콘텐츠 유형에 따라 적절한 형태를 선택합니다.
default (직각)
radius: 0
hover only
radius: 3px
circle (아바타)
radius: 50%
<Asset shape="square" /> {/* 갤러리 썸네일 */}
<Asset shape="rounded" /> {/* 작품 이미지, 기본값 */}
<Asset shape="circle" /> {/* 작가 프로필 */}
Size 옵션
사용 맥락에 따라 다양한 크기를 지원합니다. number(px) 또는 프리셋 문자열을 전달합니다.
24px
36px
48px
64px
96px
<Asset size={24} /> {/* 인라인 아이콘 */}
<Asset size={36} /> {/* 리스트 아이템 */}
<Asset size={48} /> {/* 카드 썸네일 */}
<Asset size={64} /> {/* 상세 프로필 */}
<Asset size={96} /> {/* 히어로 프로필 */}
Fallback 처리
이미지 로드 실패 시 배경색 + 이니셜 또는 아이콘으로 대체합니다.
Initial
Icon
Empty
<!-- 이니셜 fallback --> <Asset src="/broken.jpg" fallback="initial" name="박수근" /> <!-- 아이콘 fallback --> <Asset src="/broken.jpg" fallback="icon" /> <!-- 빈 placeholder --> <Asset src="/broken.jpg" fallback="empty" />
접근성
Asset은 시각적 미디어를 표시하므로, 대체 텍스트를 반드시 제공합니다.
| 속성 | 값 | 설명 |
|---|---|---|
alt | "{설명}" | 이미지의 대체 텍스트입니다. 장식 이미지는 빈 문자열을 사용합니다. |
role | "img" | fallback(div) 사용 시 이미지 역할을 명시합니다. |
aria-label | "{이름}" | 아바타 사용 시 이름 정보를 제공합니다. |
사용 방법 예시
작가 프로필, 작품 리스트에서 Asset이 사용되는 모습입니다.
박수근
한국화 · 작품 24점
김환기
유화 · 작품 18점
이중섭
유화 · 작품 31점
인터페이스
Asset 컴포넌트의 Props를 정의합니다.
AssetProps
| 속성 | 필수 | 기본값 | 타입 | 설명 |
|---|---|---|---|---|
src | — | — | string | 이미지 URL입니다. |
shape | — | rounded | square | rounded | circle | 미디어의 모양입니다. |
size | — | 48 | number (px) | 너비와 높이입니다. |
fallback | — | empty | initial | icon | empty | 로드 실패 시 대체 표시 방식입니다. |
name | — | — | string | initial fallback 시 이니셜 추출에 사용합니다. |
alt | — | "" | string | 이미지 대체 텍스트입니다. |
Components / Typography
Paragraph
텍스트, 아이콘, 배지, 링크 등을 조합하는 복합 텍스트 컴포넌트입니다. 7단계 타이포그래피 스케일(t1~t7)과 말줄임 처리를 지원합니다.
사용법
Paragraph는 일관된 타이포그래피 스케일로 텍스트를 렌더링합니다. Text, Icon, Badge, Link 서브 컴포넌트를 조합합니다.
박수근 — 빨래터
한국 근현대 미술의 거장 박수근의 대표작으로, 소박한 일상의 아름다움을 담아낸 작품입니다. 더 알아보기
<Paragraph scale="t3"> <Paragraph.Text>박수근 — 빨래터</Paragraph.Text> </Paragraph> <Paragraph scale="t5" color="secondary"> <Paragraph.Text>한국 근현대 미술의...</Paragraph.Text> <Paragraph.Link href="/detail">더 알아보기</Paragraph.Link> </Paragraph>
<p style="font-family:var(--sans);font-size:var(--text-sm);line-height:1.7;color:var(--text)"> 본문 텍스트입니다. 작품의 가치와 의미를 전달합니다. </p>
Typography Scale (t1~t7)
7단계 스케일로 텍스트의 크기와 역할을 정의합니다. t1~t3은 제목, t4~t5는 본문, t6~t7은 캡션/라벨입니다.
<Paragraph scale="t1">...</Paragraph> {/* 28px, Bold, 제목 */}
<Paragraph scale="t5">...</Paragraph> {/* 15px, Regular, 본문, 기본값 */}
<Paragraph scale="t7">...</Paragraph> {/* 11px, Regular, 라벨 */}
Sub-Components
Text, Icon, Badge, Link 4가지 서브 컴포넌트를 자유롭게 조합합니다.
<Paragraph> <Paragraph.Icon name="diamond" /> <Paragraph.Text>추천 작품</Paragraph.Text> <Paragraph.Badge color="green">New</Paragraph.Badge> <Paragraph.Link href="/more">자세히</Paragraph.Link> </Paragraph>
Ellipsis (말줄임표)
긴 텍스트를 지정한 줄 수에서 잘라내고 말줄임표(...)를 표시합니다.
1줄 말줄임
한국 근현대 미술의 거장 박수근의 대표작으로, 소박한 일상의 아름다움을 담아낸 작품
2줄 말줄임
한국 근현대 미술의 거장 박수근의 대표작으로, 소박한 일상의 아름다움을 담아낸 작품입니다. 따뜻한 색감과 질감이 인상적입니다.
<Paragraph ellipsis={1}>...</Paragraph> {/* 1줄 후 잘라냄 */}
<Paragraph ellipsis={2}>...</Paragraph> {/* 2줄 후 잘라냄 */}
{/* aria-label에 전체 텍스트를 반드시 제공하세요 */}
접근성
Paragraph는 텍스트 콘텐츠의 구조와 접근성을 보장합니다.
| 속성 | 값 | 설명 |
|---|---|---|
aria-label | "{전체텍스트}" | ellipsis 사용 시 전체 텍스트를 제공합니다. |
lang | "ko" | "en" | 텍스트 언어를 명시합니다. (Pretendard/Space Grotesk 분기) |
role (Link) | "link" | Link 서브 컴포넌트의 역할입니다. |
사용 방법 예시
작품 상세 페이지에서 Paragraph가 사용되는 모습입니다.
박수근 — 빨래터
한국 근현대 미술의 거장 박수근의 대표작으로, 소박한 일상의 아름다움을 담아낸 작품입니다. 더 알아보기
인터페이스
Paragraph 및 서브 컴포넌트의 Props를 정의합니다.
ParagraphProps
| 속성 | 필수 | 기본값 | 타입 | 설명 |
|---|---|---|---|---|
scale | — | t5 | t1 | t2 | t3 | t4 | t5 | t6 | t7 | 타이포그래피 스케일입니다. |
weight | — | auto | regular | medium | semibold | bold | 글씨 굵기. auto면 스케일에 따라 자동입니다. |
color | — | text | text | secondary | muted | red | 텍스트 색상 토큰입니다. |
ellipsis | — | — | number (lines) | 말줄임 처리할 최대 줄 수입니다. |
children | ✓ | — | ReactNode | Text, Icon, Badge, Link 서브 컴포넌트를 조합합니다. |
Paragraph.Text / Paragraph.Icon / Paragraph.Badge / Paragraph.Link
| 속성 | 필수 | 기본값 | 타입 | 설명 |
|---|---|---|---|---|
children | ✓ | — | ReactNode | 서브 컴포넌트 콘텐츠입니다. |
href | — | — | string | Link 서브 컴포넌트의 URL입니다. |
name | — | — | string | Icon 서브 컴포넌트의 아이콘 이름입니다. |
color | — | — | string | Badge 서브 컴포넌트의 색상입니다. |
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
Artwork Card
CHAART. 전용 작품 카드 컴포넌트입니다. 작품 이미지, 작가명, 제목, 가격, 상태 배지를 표시하며 세로/가로 레이아웃을 지원합니다.
사용법
ArtworkCard는 작품 이미지 + 정보 텍스트를 하나의 터치 영역으로 묶습니다. 클릭 시 상세 페이지로 이동합니다.
빨래터
박수근 · 유화
₩ 2,400,000
<ArtworkCard
image="/artwork.jpg"
title="빨래터"
artist="박수근"
medium="유화"
price="₩ 2,400,000"
badge={{ color: 'green', children: 'Available' }}
onWishlist={() => toggleWishlist(id)}
/>
<div class="ch-card" style="overflow:hidden;padding:0">
<div style="aspect-ratio:4/3;background:var(--alpha-4)"></div>
<div style="padding:var(--space-4)">
<p style="font-size:var(--text-sm);font-weight:700;color:var(--charcoal);margin:0 0 4px">작품 제목</p>
<p style="font-size:var(--text-xs);color:var(--text-muted);margin:0 0 8px">작가명</p>
<p style="font-size:var(--text-sm);font-weight:700;color:var(--charcoal);font-family:var(--mono);margin:0">₩12,000,000</p>
</div>
</div>
Vertical 레이아웃
이미지가 위, 텍스트가 아래에 배치되는 기본 레이아웃입니다. 그리드, 캐러셀에서 사용합니다.
빨래터
박수근
어디서 무엇이
김환기
<ArtworkCard layout="vertical" /> {/* 기본값 */}
{/* 그리드: grid-template-columns: repeat(2, 1fr) */}
Horizontal 레이아웃
이미지가 왼쪽, 텍스트가 오른쪽에 배치됩니다. 검색 결과, 찜 목록에서 사용합니다.
빨래터
박수근 · 유화 · 1954
₩ 2,400,000
<ArtworkCard layout="horizontal" />
{/* 이미지 80×80, 텍스트 flex: 1 */}
상태 Badge / 찜 버튼
이미지 위에 상태 Badge(좌상단)와 찜 버튼(우상단)을 오버레이합니다.
<ArtworkCard
badge={{ color: 'green', children: 'Available' }}
secondaryBadge={{ color: 'blue', children: 'VIP' }}
isWishlisted={true}
onWishlist={() => toggleWishlist(id)}
/>
접근성
ArtworkCard는 클릭 가능한 카드로, 적절한 접근성을 제공합니다.
| 속성 | 값 | 설명 |
|---|---|---|
role | "article" | 독립적인 콘텐츠 단위를 표현합니다. |
aria-label | "{title} by {artist}" | 카드의 주요 정보를 전달합니다. |
tabIndex | 0 | 키보드 탐색에 포함됩니다. |
img alt | "{title}" | 작품 이미지의 대체 텍스트입니다. |
사용 방법 예시
메인 화면 추천 작품 그리드에서 ArtworkCard가 사용되는 모습입니다.
추천 작품
빨래터
박수근
해질녘
김환기
인터페이스
ArtworkCard 컴포넌트의 Props를 정의합니다.
ArtworkCardProps
| 속성 | 필수 | 기본값 | 타입 | 설명 |
|---|---|---|---|---|
image | ✓ | — | string | 작품 이미지 URL입니다. |
title | ✓ | — | string | 작품 제목입니다. |
artist | ✓ | — | string | 작가명입니다. |
medium | — | — | string | 작품 매체 (유화, 수채화 등)입니다. |
price | — | — | string | 가격 텍스트입니다. |
layout | — | vertical | vertical | horizontal | 카드 레이아웃입니다. |
badge | — | — | BadgeProps | 이미지 위 상태 Badge입니다. |
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 | 아이템이 없을 때 표시할 메시지입니다. |
Components / Typography
Highlight
텍스트의 일부를 시각적으로 강조하는 인라인 컴포넌트입니다. 배경색, 밑줄, 굵기+색상 등 다양한 방식을 지원합니다.
사용법
Highlight는 가격, 할인율, 작가명 등 핵심 텍스트를 강조합니다. variant를 지정하여 강조 방식을 선택합니다.
이 작품의 감정가는 12,000,000원이며, 박수근 작가의 대표작입니다.
이 작품의 감정가는 <Highlight>12,000,000원</Highlight>이며, <Highlight>박수근</Highlight> 작가의 대표작입니다.
<mark style="background:rgba(150,30,35,0.1);color:var(--red-brand);padding:2px 4px">highlighted text</mark>
Background 하이라이트
배경색으로 텍스트를 강조합니다. 기본 variant이며, 색상을 지정할 수 있습니다.
현재 가격: ₩12,000,000
할인율: -15%
상태: 경매 진행중
<Highlight variant="background" color="red">₩12,000,000</Highlight> <Highlight variant="background" color="green">-15%</Highlight> <Highlight variant="background" color="blue">경매 진행중</Highlight>
Underline 하이라이트
밑줄로 텍스트를 강조합니다. 본문 흐름을 방해하지 않으면서 핵심 정보를 표시합니다.
박수근 작가의 작품은 한국 근대미술을 대표합니다.
감정가 ₩12,000,000으로 평가되었습니다.
<Highlight variant="underline" color="red">박수근</Highlight> <Highlight variant="underline" color="orange">₩12,000,000</Highlight>
Bold + Color 하이라이트
굵기와 색상을 조합하여 강조합니다. 배경 없이 텍스트 자체를 부각시킵니다.
30% 할인 중인 김환기 작가의 작품을 한정 판매합니다.
<Highlight variant="bold" color="red">30%</Highlight> <Highlight variant="bold" color="dark">김환기</Highlight> <Highlight variant="bold" color="blue">한정 판매</Highlight>
접근성
| 속성 | 값 | 설명 |
|---|---|---|
role | "mark" | 강조된 텍스트 영역임을 명시합니다. |
aria-label | "강조: {text}" | 색상만으로 의미를 전달하지 않도록 라벨을 제공합니다. |
| 시맨틱 태그 | <mark> | HTML mark 요소를 기본 렌더링 태그로 사용합니다. |
사용 방법 예시
빨래터
박수근 · 유화 · 1954
감정가
₩12,000,000
-15% 할인 전월 대비
한국 근대미술의 거장 박수근의 대표작으로, 국보급 작품입니다.
인터페이스
HighlightProps
| 속성 | 필수 | 기본값 | 타입 | 설명 |
|---|---|---|---|---|
variant | — | background | background | underline | bold | 강조 표현 방식입니다. |
color | — | red | red | green | blue | orange | dark | 강조 색상입니다. |
children | ✓ | — | string | 강조할 텍스트입니다. |
as | — | mark | mark | span | strong | 렌더링할 HTML 태그입니다. |
intensity | — | medium | light | medium | strong | 강조 강도입니다. 배경 투명도/밑줄 두께에 영향합니다. |
Components / Layout & List
List Footer
리스트 하단에 배치되는 더보기, 페이지네이션, 로딩 상태 영역입니다. 작품 목록, 경매 내역 등 긴 리스트 끝에서 추가 콘텐츠 탐색을 유도합니다.
사용법
기본 리스트 푸터는 더보기 버튼을 표시합니다. 리스트의 마지막 아이템 아래에 배치하세요.
<List>
{items.map(item => <ListItem key={item.id} {...item} />)}
<ListFooter type="more" onMore={handleLoadMore} />
</List>
<div style="padding:var(--space-4);text-align:center;border-top:1px solid var(--border)"> <button style="font-size:var(--text-sm);color:var(--text-muted);background:none;border:none;cursor:pointer">더 보기</button> </div>
페이지네이션
전체 페이지 수와 현재 페이지를 표시하는 페이지네이션 모드입니다.
<ListFooter
type="pagination"
currentPage={1}
totalPages={12}
onPageChange={handlePageChange}
/>
로딩 스피너
무한 스크롤 등에서 추가 데이터를 불러오는 중일 때 표시합니다.
<ListFooter type="loading" message="작품을 불러오는 중…" />
접근성
| 속성 | 값 | 설명 |
|---|---|---|
role | navigation | 페이지네이션 모드에서 네비게이션 역할을 부여합니다 |
aria-label | "페이지 탐색" | 페이지네이션 영역의 목적을 설명합니다 |
aria-current | "page" | 현재 활성 페이지를 나타냅니다 |
aria-live | "polite" | 로딩 상태 변경을 스크린 리더에 알립니다 |
사용 방법 예시
인터페이스
ListFooterProps
| 속성 | 필수 | 기본값 | 타입 | 설명 |
|---|---|---|---|---|
type | ✓ | — | "more" | "pagination" | "loading" | 리스트 푸터 유형 |
message | "더보기" | string | 버튼 또는 로딩 텍스트 | |
currentPage | 1 | number | 현재 페이지 (pagination 모드) | |
totalPages | — | number | 전체 페이지 수 (pagination 모드) | |
remainCount | — | number | 남은 아이템 수 (more 모드) | |
onMore | — | () => void | 더보기 클릭 핸들러 | |
onPageChange | — | (page: number) => void | 페이지 변경 핸들러 |
Components / Layout & List
Post
SNS형 게시글 카드 컴포넌트입니다. 프로필, 본문, 이미지, 인터랙션 영역으로 구성되며, 갤러리 소식, 전시 후기, 작가 인터뷰 등 피드 콘텐츠에 사용됩니다.
사용법
기본 포스트는 프로필 영역, 텍스트 본문, 인터랙션 버튼으로 구성됩니다.
다음 주 금요일, 신진 작가 3인의 그룹전 "경계의 시선"이 오픈합니다. 회화, 조각, 미디어아트가 어우러진 이번 전시에 많은 관심 부탁드립니다.
<Post
author={{ name: "아트스페이스 갤러리", avatar: "/gallery.jpg" }}
timestamp="2시간 전"
content="다음 주 금요일, 신진 작가 3인의 그룹전이 오픈합니다."
likes={24}
comments={8}
/>
<article style="padding:var(--space-4);border-bottom:1px solid var(--border)">
<div style="display:flex;align-items:center;gap:var(--space-3);margin-bottom:var(--space-3)">
<div style="width:36px;height:36px;border-radius:50%;background:var(--alpha-8)"></div>
<div>
<div style="font-size:var(--text-sm);font-weight:600">작성자명</div>
<div style="font-size:var(--text-xs);color:var(--text-muted)">2 hours ago</div>
</div>
</div>
<p style="font-size:var(--text-sm);line-height:1.6;margin:0">Post content here</p>
</article>
이미지 포함
단일 이미지를 포함한 포스트입니다. 이미지는 본문과 인터랙션 사이에 배치됩니다.
새 작업실에서의 첫 번째 작품이 완성되었습니다. 빛이 좋은 공간에서 작업하니 색감이 달라지네요.
<Post
author={{ name: "작가 이수연", avatar: "/artist.jpg" }}
timestamp="어제"
content="새 작업실에서의 첫 번째 작품이 완성되었습니다."
images={["/studio.jpg"]}
likes={56}
comments={12}
/>
다중 이미지
여러 이미지를 그리드 형태로 표시합니다. 4장 이상은 오버레이 카운터로 나타냅니다.
서울 아트페어 2026 현장 스케치입니다. 올해는 특히 동남아 갤러리의 참여가 눈에 띄었습니다.
<Post
author={{ name: "전시 리뷰어 박지현", avatar: "/reviewer.jpg" }}
timestamp="3일 전"
content="서울 아트페어 2026 현장 스케치입니다."
images={["/fair1.jpg", "/fair2.jpg", "/fair3.jpg", ...moreImages]}
likes={142}
comments={31}
/>
접근성
| 속성 | 값 | 설명 |
|---|---|---|
role | article | 포스트가 독립적인 콘텐츠 단위임을 명시합니다 |
aria-label | string | 포스트 요약 정보를 제공합니다 (작성자, 시간) |
alt | string | 이미지에 대체 텍스트를 제공합니다 |
aria-pressed | boolean | 좋아요 버튼의 토글 상태를 전달합니다 |
사용 방법 예시
이번 주말 오프닝 리셉션에 초대합니다. 작가와의 대화도 준비되어 있습니다.
올해 가장 인상 깊었던 전시를 꼽자면 단연 국립현대미술관의 회고전입니다.
인터페이스
PostProps
| 속성 | 필수 | 기본값 | 타입 | 설명 |
|---|---|---|---|---|
author | ✓ | — | { name: string; avatar?: string } | 작성자 정보 |
timestamp | ✓ | — | string | Date | 작성 시간 표시 |
content | ✓ | — | string | ReactNode | 게시글 본문 콘텐츠 |
images | [] | string[] | 첨부 이미지 URL 배열 | |
likes | 0 | number | 좋아요 수 | |
comments | 0 | number | 댓글 수 | |
liked | false | boolean | 현재 사용자의 좋아요 여부 | |
onLike | — | () => void | 좋아요 클릭 핸들러 |
Components / Layout & List
Table Row
테이블 형태의 데이터 행 컴포넌트입니다. 구조화된 데이터를 일관된 행 레이아웃으로 표시하며, 선택 및 상호작용을 지원합니다.
사용법
<TableRow
cells={["무제 No.203", "김환기", "₩85,000,000", "판매중"]}
onClick={() => openDetail(id)}
/>
<table style="width:100%;border-collapse:collapse;font-size:var(--text-sm)">
<thead>
<tr style="border-bottom:2px solid var(--border)">
<th style="text-align:left;padding:var(--space-3);font-weight:600">Name</th>
<th style="text-align:left;padding:var(--space-3);font-weight:600">Status</th>
</tr>
</thead>
<tbody>
<tr style="border-bottom:1px solid var(--border)">
<td style="padding:var(--space-3)">Item</td>
<td style="padding:var(--space-3)"><span class="ch-badge ch-badge--green">Active</span></td>
</tr>
</tbody>
</table>
변형
접근성
| 속성 | 값 | 설명 |
|---|---|---|
role | row | 테이블 행 역할을 스크린 리더에 전달합니다 |
aria-selected | true | false | 선택 가능한 행의 선택 상태를 전달합니다 |
aria-rowindex | 행 인덱스 | 전체 테이블에서의 행 위치를 전달합니다 |
tabindex | 0 | 클릭 가능한 행의 키보드 포커스를 지원합니다 |
| 키보드 | Enter / Space | 포커스된 행을 선택하거나 클릭합니다 |
사용 방법 예시
인터페이스
TableRowProps
| 속성 | 필수 | 기본값 | 타입 | 설명 |
|---|---|---|---|---|
cells | ✓ | — | ReactNode[] | 행에 표시할 셀 데이터 배열 |
onClick | — | () => void | 행 클릭 시 호출되는 콜백 | |
selected | false | boolean | 행 선택 상태 | |
striped | false | boolean | 줄무늬 배경 표시 여부 | |
divider | true | boolean | 하단 구분선 표시 여부 |