JS Design System v0.6

Card

관련 정보와 액션을 한 덩어리로 묶는 컨테이너입니다. 보더 대신 Surface 배경 + shadow/1 로 구획합니다.

1. Default

head(제목 + 상태) · desc · foot(액션 우측). 보더 없이 Surface 배경과 shadow/1 로 구획합니다.

라이선스

정상

1,000석 중 842석 사용 중. 2026-12-31 만료.

2. Header Actions

헤더 우측에 기간 선택(Select Button) 또는 더 보기 메뉴. 패널이 없으니 탭이 아니라 role=group + aria-pressed 를 씁니다.

주간 탐지 추이

이번 주 탐지 412건, 지난주보다 18% 증가

3. Bordered / Compact

카드 위에 카드를 겹칠 때는 .bordered, 밀도 높은 그리드는 .compact.

Bordered

그림자 대신 1px 보더

Compact

padding 16 · 제목 14

4. Clickable / Selected

카드 전체가 눌리면 .clickable. 이동이면 a, 선택이면 button + aria-pressed 로 두고 선택된 것에 .on 을 줍니다.

5. Loading

데이터를 기다리는 동안 내용 자리에 Skeleton 을 넣고 컨테이너에 aria-busy 를 둡니다. 로드되면 같은 자리를 실제 내용으로 바꿥니다.

Props

HTML 에서는 클래스와 속성으로, React(@jiran/ds-react)에서는 같은 이름의 prop(variant · size …)으로 변형·상태를 지정합니다.

Prop / ClassType · ValuesDefaultDescription
.cardcontainer—flex column · gap 12 · padding 24 · 최소 폭 260. React Card
.card-head / .title / .desc / .card-footelements—헤더(양끝 정렬) / 제목 Title/1 16·24 / 설명 Body/2 14 / 푸터 우측 정렬 — React CardHead·CardTitle·CardDesc·CardFoot
.borderedbooleanfalseshadow 대신 1px 보더. 카드 위에 카드를 겹칠 때
.compactbooleanfalsepadding 16 · gap 8 · 제목 14(Title/2)
.flushbooleanfalsepadding·gap 0 — 표나 목록을 카드 폭까지 꽉 채울 때. 헤더만 자체 여백을 갖습니다
.clickablebooleanfalse카드 전체가 눌림. 이동이면 a, 선택이면 button + aria-pressed. hover 에 shadow/2. React clickable + as
.card-grid .card.clickablebehavior—ds.js 가 단일 선택으로 묶어 .on 과 aria-pressed 를 함께 갱신하고 ds:select 를 발행합니다
.onbooleanfalse선택됨 — 안쪽 2px accent 링 + --accent-subtle 배경. 포커스 링(outline)과 겹치지 않아 둘이 동시에 보입니다. React selected
aria-busyattribute—불러오는 중 — 내용 대신 .skeleton 을 넣고 컨테이너에 둡니다. React loading 이 둘을 함께 처리합니다
.card-gridcontainer—auto-fill minmax(260px,1fr) 그리드 · gap 20. React CardGrid

Usage

React: @jiran/ds-react 패키지를 설치하고 style.css 를 한 번 import 하면 위 React 탭 코드를 그대로 쓸 수 있습니다(React Package). HTML: assets/style.css 를 연결하고(일부만 필요하면 아래 컴포넌트 CSS 복사), 동작이 필요하면 assets/ds.js 를 함께 넣습니다 — 이 페이지의 프리뷰가 그 스크립트로 동작합니다. 색은 전부 토큰(var(--accent) 등)을 참조하므로 --accent-* 만 제품 컬러로 바꾸면 됩니다.

React @jiran/ds-react

npm i @jiran/ds-react

// main.tsx — 앱 진입점에서 한 번
import "@jiran/ds-react/style.css";

// 컴포넌트
import { Card, CardHead, CardTitle, CardDesc, CardFoot, CardGrid } from "@jiran/ds-react";

HTML

<!-- 1) 토큰 + 전체 컴포넌트 스타일 한 번에 연결 -->
<link rel="stylesheet" href="assets/style.css">
<!-- 동작(드롭다운·탭·달력·표 정렬/선택·토스트 등) — 순수 JS 한 파일. React 제품은 불필요 -->
<script src="assets/ds.js" defer></script>

<!-- 2) 또는 아래 "Component CSS" 만 프로젝트 CSS 에 붙이고,
        :root 토큰은 Foundations › Design Token 에서 복사 -->

Component CSS .card, .card-grid

/* JS Design System v0.6 · .card, .card-grid · 토큰(var(--*))은 assets/style.css :root 참고 */
.card{background:var(--bg-surface);border-radius:var(--radius-lg);box-shadow:var(--shadow-1);padding:var(--card-pad);display:flex;flex-direction:column;gap:12px;min-width:260px;position:relative}
.card .card-head{display:flex;align-items:center;justify-content:space-between;gap:12px}
.card .title{font-size:16px;line-height:24px;font-weight:600;margin:0}
.card .desc{font-size:14px;color:var(--text-secondary);margin:0;line-height:1.6}
.card .card-foot{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:auto;padding-top:4px}
.card.clickable{appearance:none;border:0;font:inherit;color:inherit;text-align:left;text-decoration:none;cursor:pointer;transition:box-shadow var(--motion-fast)}
.card.bordered{box-shadow:none;border:1px solid var(--border-default)}
.card.clickable:hover{box-shadow:var(--shadow-2)}
.card.on{box-shadow:inset 0 0 0 2px var(--accent),var(--shadow-1);background:var(--accent-subtle)}
.card.clickable.on:hover{box-shadow:inset 0 0 0 2px var(--accent),var(--shadow-2)}
.card.bordered.on{box-shadow:inset 0 0 0 2px var(--accent)}
.card.compact{padding:16px;gap:8px}
.card.compact .title{font-size:14px;line-height:20px}
.card.flush{padding:0;gap:0;overflow:hidden}
.card.flush .card-head{padding:16px var(--card-pad)}
.card-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:var(--card-gap);width:100%}
.onboard .card{width:100%}