JS Design System v0.6

Item Tile

아이콘·제목·설명으로 항목을 카드 형태로 고르는 타일입니다. 정책 템플릿, 연동 모듈, 보고서 유형 선택에 씁니다.

1. Default

선택하지 않은 기본 타일입니다.

2. Grid

button.tile 그리드. 선택은 .on + aria-pressed.

3. With Tag

우상단에 상태·신규 태그.

4. Horizontal

좁은 폭에서는 가로 배치.

Props

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

Prop / ClassType · ValuesDefaultDescription
.tilebutton—.ico + b(제목) + span(설명). aria-pressed
.onbooleanfalse선택(accent 보더·배경)
.horizontalbooleanfalse가로 배치
disabledattribute—선택 불가
.tile-gridcontainer—auto-fill 180px 그리드

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 { Tile, TileGrid } 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 .tile, .tile-grid, .tag

/* JS Design System v0.6 · .tile, .tile-grid, .tag · 토큰(var(--*))은 assets/style.css :root 참고 */
.tag{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;padding:3px 10px;border-radius:var(--radius-full);line-height:1.6;background:var(--bg-panel);color:var(--text-secondary);white-space:nowrap}
.tag::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor;flex:none}
.tag.critical{background:var(--sev-critical-bg);color:var(--sev-critical-text)}
.tag.high{background:var(--sev-high-bg);color:var(--sev-high-text)}
.tag.medium{background:var(--sev-medium-bg);color:var(--sev-medium-text)}
.tag.low{background:var(--sev-low-bg);color:var(--sev-low-text)}
.tag.info{background:var(--sev-info-bg);color:var(--sev-info-text)}
.tag.ok{background:var(--success-subtle);color:var(--success-text)}
.tag.accent{background:var(--accent-subtle);color:var(--accent-text)}
.tag.sm{font-size:12px;padding:1px 8px}
.tag.lg{font-size:12px;padding:5px 12px}
.tag.plain::before{display:none}
.tag.outline{background:transparent;box-shadow:inset 0 0 0 1px currentColor}
.tag.solid.critical{background:var(--sev-critical);color:var(--sev-critical-on)}
.tag.solid.high{background:var(--sev-high);color:var(--sev-high-on)}
.tag.solid.medium{background:var(--sev-medium);color:var(--sev-medium-on)}
.tag.solid.low{background:var(--sev-low);color:var(--sev-low-on)}
.tag.solid.info{background:var(--sev-info);color:var(--sev-info-on)}
.tag.solid.ok{background:var(--success);color:var(--success-on)}
.tag.solid.accent{background:var(--accent);color:var(--accent-on)}
.tile-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:12px;width:100%}
.tile{display:flex;flex-direction:column;gap:8px;padding:16px;background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-lg);cursor:pointer;position:relative;text-align:left;font:inherit;color:var(--text-primary);transition:border-color var(--motion-fast),box-shadow var(--motion-fast)}
.tile:hover{border-color:var(--border-strong);box-shadow:var(--shadow-1)}
.tile.on{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent);background:var(--accent-subtle)}
.tile .ico{width:36px;height:36px;border-radius:var(--radius-lg);background:var(--accent-subtle);color:var(--accent-text);display:grid;place-items:center;font-weight:700;font-size:14px}
.tile.on .ico{background:var(--accent);color:var(--accent-on)}
.tile b{font-size:14px}
.tile span{font-size:12px;color:var(--text-tertiary)}
.tile .tag{position:absolute;top:12px;right:12px}
.tile.horizontal{flex-direction:row;align-items:center}
.tile.horizontal>div{display:flex;flex-direction:column;gap:2px;min-width:0}
.tile[disabled]{opacity:.4;cursor:not-allowed;pointer-events:none}