React Package
@jiran/ds-react — 이 가이드의 30개 컴포넌트와 패턴 래퍼를 실제 React 컴포넌트로 구현한 패키지입니다. 사이트와 같은 클래스 마크업을 렌더링하므로 스타일시트 하나로 동작하고, 각 컴포넌트 페이지의 React 탭 코드가 곧 사용법입니다.
설치
npm i @jiran/ds-react
// main.tsx — 앱 진입점에서 한 번
import "@jiran/ds-react/style.css"; // 토큰 + 컴포넌트 CSS (사이트 크롬 제외)
import { ToastProvider, applyAccent } from "@jiran/ds-react";
applyAccent("#1D4ED8"); // 제품 메인 컬러 → --accent-50~900 생성
createRoot(document.getElementById("root")!).render(
<ToastProvider>
<App />
</ToastProvider>,
);<html data-theme="dark"> 또는 setTheme("dark"). 없으면 시스템 설정을 따릅니다. 포털(Popup·Toast)도 <html> 에서 토큰을 상속합니다.ds-root 를 붙이면 Pretendard · 본문 색 · 배경 토큰이 적용됩니다color-mix() 사용 — Chrome 111+ · Safari 16.2+ · Firefox 113+사용
모든 컴포넌트는 forwardRef · className 병합 · 나머지 props 전달을 지원합니다. 변형은 HTML 클래스와 같은 이름의 prop 입니다.
import { Button, TextField, Tag, DataTable, useToast } from "@jiran/ds-react";
function PolicyForm() {
const toast = useToast();
return (
<form onSubmit={(e) => { e.preventDefault(); toast.show("정책이 저장되었습니다"); }}>
<TextField label="정책 이름" required help="2~40자" />
<Tag tone="critical">Critical</Tag>
<Button type="submit" size="md" variant="primary">정책 저장</Button>
</form>
);
}컴포넌트 ↔ 클래스
| 페이지 | export | HTML 클래스 |
|---|---|---|
| Accordion | Accordion, AccordionGroup | .accordion .accordion-group |
| Breadcrumb | Breadcrumb, BreadcrumbItem, BreadcrumbMore | .breadcrumb |
| Button | Button, ButtonGroup | .btn .btn-group |
| Card | Card, CardHead, CardTitle, CardDesc, CardFoot, CardGrid | .card .card-grid |
| Data Visual | Kpi, KpiGrid, ChartCard, BarChart, Donut, DonutRow, ChartLegend, Sparkline | .kpi .kpi-grid .chart .chart-card .donut .donut-row .chart-legend .sparkline |
| Date Picker | Calendar, DatePicker, formatDate | .datepicker .calendar |
| Divider | Divider | .divider |
| Dropdown | Dropdown, DropdownTrigger, Menu, MenuItem, MenuSep, MenuLabel | .dropdown .menu .menu-item .menu-sep .menu-label |
| Indicator | Indicator, Count, WithCount, Steps | .indicator .count .with-count .steps |
| Item Tile | Tile, TileGrid | .tile .tile-grid .tag |
| List | List, ListItem | .list .avatar .tag .indicator |
| Loading | Spinner, Skeleton, SkeletonRow, Progress | .spinner .spinner-wrap .skeleton .skeleton-row .progress .progress-row |
| Navigation | SideNav, SideNavGroup, SideNavItem | .sidenav .count |
| Notification | Notice, Toast, ToastStack, Banner, ToastProvider, useToast | .notice .toast .toast-stack .banner |
| Pagination | Pagination, PaginationBar, paginate | .pagination .pagination-bar .dropdown .menu .menu-item |
| Popup | Popup, PopupSurface, PopupTitle, PopupBody, PopupActions, PopupForm | .popup .popup-backdrop |
| Checkbox | Checkbox, CheckboxGroup | .checkbox .checkbox-group |
| Chip | Chip, ChipGroup | .chip .chip-group |
| Radio Button | Radio, RadioGroup | .radio .radio-group |
| Select Button | SelectButton | .select-btn |
| Search | SearchBar | .searchbar .chip .chip-group |
| Select | Select | .dropdown .menu .menu-item |
| Slider | Slider | .slider |
| Switch | Switch | .switch |
| Tab | Tabs, TabList, Tab, TabPanel | .tabs .tab-panel |
| Data Table | DataTable, ActionBar | .tbl-wrap .tbl .action-bar .tag .checkbox .indicator |
| Table | Table, TableHead, TableBody, TableRow, TableHeader, TableCell | .tbl-wrap .tbl |
| Tag | Tag | .tag |
| Text Field | Field, TextField, TextArea | .field |
| Tooltip | Tooltip | .tooltip .tooltip-wrap |
| Top Navigation | TopBar, TopBarLogo, TopBarNav, TopBarNavItem, TopBarRight, Avatar | .topbar .avatar .searchbar .divider .count .with-count |
동작·접근성
- Dropdown/Select: 바깥 클릭·Esc 닫힘, ↑↓ Home End 이동,
aria-haspopup/expanded,role=listbox|menu - Tabs: ←→ Home End, roving tabIndex,
aria-selected/controls - Popup: Portal + 배경, 포커스 트랩/복원, Esc,
role=dialog aria-modal aria-labelledby - ToastProvider/useToast: 우측 하단 스택, 자동 소멸(기본 4초), 최대 3개,
aria-live=polite - DatePicker/Calendar:
Intl로 요일·월 표기, min/max, range 선택, 프리셋 - DataTable: 정렬(
aria-sort) · 선택(헤더 indeterminate) · 행 액션 · 빈 상태 - Checkbox/Radio/Switch/Slider/Accordion: 네이티브 요소 그대로(키보드·스크린리더 기본 지원)
React 를 쓰지 않는 제품: assets/ds.js
HTML+CSS 탭 코드를 그대로 쓰는 제품은 assets/style.css 와 함께 assets/ds.js(순수 JS · 의존성 없음 · 약 23KB)를 넣으면 이 사이트의 프리뷰와 같은 동작을 얻습니다. 클래스 마크업에 이벤트 위임으로 동작을 붙이므로 서버 렌더링·동적 추가 마크업에도 그대로 적용됩니다(동적으로 넣은 마크업의 초기 상태 동기는 DS.init(root)).
<link rel="stylesheet" href="assets/style.css">
<script src="assets/ds.js" defer></script>
<script>
// 프로그램 API
DS.toast("저장되었습니다", { action: { label: "실행 취소", onClick: undo } }); // tone:"danger", duration(ms, 0=유지)
DS.popup.open("#confirm-delete"); // .popup 요소를 배경과 함께 표시(Esc·배경 클릭·[data-popup-close] 로 닫힘)
document.addEventListener("ds:select", e => console.log(e.detail.value)); // ds:select · ds:tab · ds:page · ds:date · ds:slide
</script>| 컴포넌트 | ds.js 가 붙이는 동작 |
|---|---|
| Dropdown / Select | 트리거 토글, 항목 선택 시 트리거 텍스트 갱신(listbox), 바깥 클릭·Esc 닫힘, ↑↓ Home End Enter |
| Tabs · Select Button · Chip · Tile · List · Card | .on + aria-selected/pressed 전환, Tabs ←→ 키와 .tab-panel 텍스트 갱신, Chip .x 제거, .tile-grid[data-single] 단일 선택, .card-grid .card.clickable 선택 |
| Breadcrumb · Steps · Text Field | .more[data-items] 상위 경로 펼치기, .onboard [data-step=prev|next] 단계 이동, [maxlength] 입력 시 .counter 갱신 |
| Pagination · SideNav · TopBar | 현재 페이지/메뉴 이동(aria-current), 이전/다음 비활성 계산 |
| Slider · Search | --p 트랙 채움·.val 표시, 지우기 버튼 표시/동작 |
| DatePicker · Calendar | 열기/닫기, 달력 없으면 자동 생성(기간 필드는 range), 달 이동, 날짜·기간 선택, 오늘·적용, [data-preset=N] 최근 N일 |
| Checkbox · Terms · Data Table | 전체 선택 ↔ indeterminate, 필수 약관 미동의 시 다음 비활성, 헤더 정렬(aria-sort) · 행 선택 · 액션 바 개수 |
| Notice · Toast · Popup | 닫기/액션 제거, data-duration 자동 소멸, DS.toast() · DS.popup.open(), 배경 클릭·Esc |
개발·검증
_react/src · 예제 _react/examples/<sec>/<page>/<id>.tsx(= 이 사이트 React 탭 소스)npm test — 컴포넌트 동작 + 사이트 HTML 과 React 렌더 구조 일치(태그·클래스·상태 속성) 118개 예제npm run build → dist/ ESM·CJS·d.ts·style.css·fonts. npm run demo 전체 예제 미리보기components.data.js(HTML·props) + style.src.css + _react/src + _react/examples 를 함께 갱신. verify 가 React 탭 누락을 잡습니다