JS Design System v0.6

Navigation

콘솔 좌측의 1차 내비게이션입니다. 그룹 라벨로 메뉴를 묶고 현재 위치를 .on 으로 표시합니다. 폭 240, 접으면 64.

1. Default

그룹 라벨(.group) + 링크. 아이콘 18px, 건수는 .count. 하위 항목은 .sub.

2. Collapsed

1280 이하 또는 사용자가 접었을 때. 아이콘만, 라벨은 툴팁으로.

Props

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

Prop / ClassType · ValuesDefaultDescription
.sidenavnav—폭 240, 세로 링크 목록
.groupdiv—그룹 라벨(uppercase caption)
a.oncurrent—현재 메뉴(accent subtle)
a.subchild—하위 항목(들여쓰기)
.collapsedbooleanfalse폭 64, 아이콘만
.countelement—미확인 건수

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 { SideNav, SideNavGroup, SideNavItem } 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 .sidenav, .count

/* JS Design System v0.6 · .sidenav, .count · 토큰(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{width:240px;padding:12px;background:var(--bg-surface);border-right:1px solid var(--border-default);display:flex;flex-direction:column;gap:2px;font-size:14px;min-height:320px}
.sidenav .group{margin:12px 12px 4px;font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--text-tertiary);font-weight:600}
.sidenav a{display:flex;align-items:center;font-weight:500;gap:10px;padding:8px 12px;border-radius:var(--radius-md);text-decoration:none;color:var(--text-primary);white-space:nowrap}
.sidenav a:hover{background:var(--bg-subtle)}
.sidenav a.on{background:var(--accent-subtle);color:var(--accent-text);font-weight:600}
.sidenav a svg{width:18px;height:18px;flex:none;color:var(--text-tertiary)}
.sidenav a.on svg{color:var(--accent-text)}
.sidenav a .count{margin-left:auto}
.sidenav a.sub{padding-left:40px;font-size:14px;color:var(--text-secondary)}
.sidenav.collapsed{width:64px;padding:12px 10px}
.sidenav.collapsed a{justify-content:center;padding:10px 0}
.sidenav.collapsed a span,.sidenav.collapsed .group,.sidenav.collapsed a .count{display:none}
.sidenav .foot{margin-top:auto;padding:12px;font-size:12px;color:var(--text-tertiary)}
.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 .count{position:absolute;top:-6px;right:-6px}