JS Design System v0.6

Top Navigation

제품 상단 바입니다. 제품 로고 · 1차 메뉴(사이드 내비가 없는 제품) · 전역 검색 · 알림 · 사용자 메뉴로 구성합니다.

1. Default

로고 + 메뉴 + 우측 액션. 현재 메뉴는 .on.

사이드 내비가 있는 제품은 상단 메뉴 대신 전역 검색을 둡니다.

Props

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

Prop / ClassType · ValuesDefaultDescription
.topbarheader—높이 56, 하단 1px
.logoa—제품 마크(i) + 이름 + small 버전
nav a.oncurrent—현재 1차 메뉴
.rightcontainer—우측 액션(알림·설정·아바타)
.avatarspan—이니셜 32 (sm 24)

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 { TopBar, TopBarLogo, TopBarNav, TopBarNavItem, TopBarRight, Avatar } 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 .topbar, .avatar, .searchbar, .divider, .count, .with-count

/* JS Design System v0.6 · .topbar, .avatar, .searchbar, .divider, .count, .with-count · 토큰(var(--*))은 assets/style.css :root 참고 */
.searchbar{display:flex;align-items:center;gap:8px;height:40px;padding:0 12px;min-width:280px;border:1px solid var(--border-strong);border-radius:var(--radius-md);background:var(--bg-surface);transition:border-color var(--motion-fast)}
.searchbar svg{width:18px;height:18px;color:var(--text-tertiary);flex:none}
.searchbar input{flex:1;border:0;background:transparent;font:inherit;font-size:14px;color:var(--text-primary);outline:0;min-width:0}
.searchbar input::placeholder{color:var(--text-disabled)}
.searchbar:focus-within{border-color:var(--border-focus)}
.searchbar .clear{border:0;padding:0;background:var(--bg-panel);color:var(--text-secondary);width:20px;height:20px;border-radius:50%;font:inherit;font-size:12px;line-height:0;cursor:pointer;display:grid;place-items:center;flex:none}
.searchbar .clear svg{display:block;width:12px;height:12px}
.searchbar kbd{font-size:12px;color:var(--text-tertiary);border:1px solid var(--border-default);border-radius:4px;padding:1px 5px;background:var(--bg-subtle)}
.searchbar.lg{height:48px}
.searchbar.lg input{font-size:16px}
.searchbar.block{width:100%}
.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}
.topbar{display:flex;align-items:center;gap:16px;height:56px;padding:0 20px;background:var(--bg-surface);border-bottom:1px solid var(--border-default);width:100%}
.topbar .logo{font-weight:700;display:flex;align-items:center;gap:8px;text-decoration:none;color:var(--text-primary);white-space:nowrap}
.topbar .logo i{width:24px;height:24px;border-radius:6px;background:var(--accent);display:inline-block}
.topbar .logo small{font-weight:500;color:var(--text-tertiary);font-size:12px}
.topbar nav{display:flex;gap:4px;margin-left:8px}
.topbar nav a{padding:8px 12px;border-radius:var(--radius-md);text-decoration:none;color:var(--text-secondary);font-size:14px;font-weight:500;white-space:nowrap}
.topbar nav a:hover{color:var(--text-primary)}
.topbar nav a.on{color:var(--text-primary);background:var(--bg-panel)}
.topbar .right{margin-left:auto;display:flex;align-items:center;gap:8px}
.topbar .searchbar{min-width:220px;height:36px}
.topbar .divider.vertical{height:20px}
.avatar{width:32px;height:32px;border-radius:50%;background:var(--accent-subtle);color:var(--accent-text);display:inline-grid;place-items:center;font-size:12px;font-weight:700;flex:none}
.avatar.sm{width:24px;height:24px;font-size:10px}
.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}
.divider{border:0;border-top:1px solid var(--border-default);margin:16px 0;width:100%}
.divider.strong{border-color:var(--border-strong)}
.divider.dashed{border-top-style:dashed}
.divider.label{display:flex;align-items:center;gap:12px;border:0;font-size:12px;color:var(--text-tertiary);white-space:nowrap}
.divider.label::before,.divider.label::after{content:"";flex:1;height:1px;background:var(--border-default)}
.divider.vertical{width:1px;height:24px;border:0;background:var(--border-default);margin:0 12px;display:inline-block;vertical-align:middle;flex:none}