JS Design System v0.6

Indicator

상태 점, 건수 배지, 단계 표시처럼 작은 시각 신호입니다. 텍스트 라벨과 함께 써 색만으로 의미를 전달하지 않습니다.

1. Default

상태 점과 라벨을 함께 쓰는 기본 형태입니다.

정상

2. Status Dot

에이전트·서비스 상태. 라벨 필수. 실시간 위험은 .pulse.

정상 주의 장애 점검 중 오프라인 실시간 공격 탐지

3. Count Badge

미확인 건수. 99 초과는 99+. 아이콘 위에는 .with-count.

3 99+ 12 128 5

4. Steps

온보딩·마법사 진행 단계. 완료 .done, 현재 .on.

  1. 기본 정보
  2. 적용 대상
  3. 3규칙 설정
  4. 4검토 · 배포

Props

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

Prop / ClassType · ValuesDefaultDescription
.indicatorspan—점 + 라벨. ok | warn | danger | info | accent | (neutral)
.pulsebooleanfalse깜빡임(위험 실시간)
.countspan—건수. .accent / .neutral / .dot(점만)
.with-countwrapper—아이콘 우상단에 count 배치
.steps lili—.done 완료, .on 현재. .vertical 세로

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 { Indicator, Count, WithCount, Steps } 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 .indicator, .count, .with-count, .steps

/* JS Design System v0.6 · .indicator, .count, .with-count, .steps · 토큰(var(--*))은 assets/style.css :root 참고 */
.tabs .tab .count{font-size:12px;font-weight:700;padding:1px 6px;border-radius:var(--radius-full);background:var(--bg-panel);color:var(--text-secondary);min-width:0;height:auto}
.tabs .tab.on .count{background:var(--accent-subtle);color:var(--accent-text)}
.sidenav a .count{margin-left:auto}
.sidenav.collapsed a span,.sidenav.collapsed .group,.sidenav.collapsed a .count{display:none}
.indicator{display:inline-flex;align-items:center;gap:8px;font-size:14px}
.indicator::before{content:"";width:8px;height:8px;border-radius:50%;background:var(--interaction-inactive);flex:none}
.indicator.ok::before{background:var(--success)}
.indicator.warn::before{background:var(--warning)}
.indicator.danger::before{background:var(--danger)}
.indicator.info::before{background:var(--info)}
.indicator.accent::before{background:var(--accent-graphic)}
.indicator.pulse::before{box-shadow:0 0 0 0 var(--danger);animation:pulse 1.6s infinite}
.count{display:inline-grid;place-items:center;min-width:20px;height:20px;padding:0 6px;border-radius:var(--radius-full);background:var(--danger);color:var(--danger-on);font-size:12px;font-weight:700;line-height:1;}
.count.neutral{background:var(--bg-panel);color:var(--text-secondary)}
.count.accent{background:var(--accent);color:var(--accent-on)}
.count.dot{min-width:8px;width:8px;height:8px;padding:0}
.with-count{position:relative;display:inline-flex}
.with-count .count{position:absolute;top:-6px;right:-6px}
.steps{display:flex;align-items:center;gap:8px;list-style:none;padding:0;margin:0;font-size:12px;max-width:none}
.steps li{display:flex;align-items:center;gap:8px;color:var(--text-tertiary);margin:0;white-space:nowrap}
.steps li i{width:24px;height:24px;border-radius:50%;display:inline-grid;place-items:center;font-style:normal;font-size:12px;font-weight:700;background:var(--fill-strong);color:var(--text-secondary);flex:none}
.steps li i svg{width:12px;height:12px;stroke-width:3}
.steps li.done i{background:var(--success);color:var(--success-on)}
.steps li.on{color:var(--text-primary);font-weight:600}
.steps li.on i{background:var(--accent);color:var(--accent-on)}
.steps li+li::before{content:"";width:32px;height:1px;background:var(--border-strong)}
.steps.vertical{flex-direction:column;align-items:flex-start}
.steps.vertical li+li::before{display:none}
.status-item .indicator{font-weight:600}
@keyframes pulse{70%{box-shadow:0 0 0 8px transparent}}