mokona-ui
v0.0.14
Published
React UI component library
Readme
mokona-ui
React UI 컴포넌트 라이브러리.
풍부한 애니메이션 반응, CSS variable 기반 다크모드, React 17~19 지원을 목표로 설계했습니다.
설치
npm install mokona-ui
# or
pnpm add mokona-ui소비자 프로젝트에서 스타일시트를 한 번 import합니다.
import "mokona-ui/styles.css";사용법
전체 import
import { Button, Toast, BottomSheet } from "mokona-ui";Subpath import (트리쉐이킹 최적화)
필요한 컴포넌트만 가져오면 불필요한 코드가 번들에 포함되지 않습니다.
import { Button } from "mokona-ui/button";
import { TextField } from "mokona-ui/textfield";
import { toast, Toaster } from "mokona-ui/toast";컴포넌트
Foundation
| 컴포넌트 | 설명 |
|---|---|
| Button | 탄성 tap 애니메이션, 5가지 variant, loading 상태 |
| Text | 타이포그래피 토큰 래퍼, as prop으로 시맨틱 태그 지정 |
| Divider | 수평/수직, spacing 조절 |
<Button variant="primary" size="md" loading>계속하기</Button>
<Button variant="danger" fullWidth>삭제</Button>
<Text variant="title1">잔액 조회</Text>
<Text variant="body2" color="muted">오늘 사용 금액</Text>Input
| 컴포넌트 | 설명 |
|---|---|
| TextField | label, helperText, errorMessage, 접근성 aria 자동 처리, size (sm/md/lg) |
| Checkbox | 체크 시 path draw 애니메이션, Radix 접근성, size (sm/md/lg) |
| Toggle | label + description 레이아웃 내장, Radix Switch 기반, size (sm/md/lg) |
| RadioGroup | items 배열로 선언, size (sm/md/lg) |
| Textarea | 자동 높이 조절, label/helper 내장 |
| Select | Radix 기반 드롭다운, options 배열 |
| Slider | 범위 슬라이더, Radix Slider 기반 |
| SegmentedControl | 탭 전환 컨트롤, sliding 인디케이터 애니메이션, size (sm/md) |
| NumericSpinner | +/- 버튼으로 숫자 입력, min/max/step 지원 |
| SearchField | 검색 입력 + 지우기 버튼 |
| OTPInput | N자리 일회용 코드 입력 |
<TextField label="이메일" placeholder="[email protected]" isError errorMessage="올바른 이메일 형식이 아닙니다" size="lg" />
<Checkbox label="전체 동의" size="md" onCheckedChange={setChecked} />
<Toggle label="푸시 알림" description="혜택 및 이벤트 소식을 받습니다" size="sm" />
<RadioGroup
value={plan}
onChange={setPlan}
items={[{ value: "basic", label: "기본", description: "월 9,900원" }, { value: "pro", label: "프로", description: "월 19,900원" }]}
size="lg"
/>
<SegmentedControl items={[{ value: "day", label: "일" }, { value: "week", label: "주" }, { value: "month", label: "월" }]} value={period} onChange={setPeriod} />Feedback
| 컴포넌트 | 설명 |
|---|---|
| Toast / Toaster / toast() | 함수 호출 방식, 4가지 variant, 콘텐츠 너비 자동 조절, 텍스트 선택 가능 |
| BottomSheet | spring 슬라이드 + 드래그로 닫기 |
| Badge | 6가지 variant, 3가지 size |
| Chip | 선택/해제 상태, 제거 버튼 내장 |
| Progress | value 기반 determinate, indeterminate prop으로 스트라이프 애니메이션, size/color 지원 |
| Alert | 아이콘 + 제목 + 설명, 4가지 variant |
| AlertDialog / ConfirmDialog | 모달 형태 확인 다이얼로그 |
| Rating | 별점 입력/표시 |
// 앱 최상단에 Toaster 한 번 추가
<Toaster />
// 어디서든 함수로 호출
toast("송금이 완료되었습니다");
toast.positive("계좌가 연결되었습니다");
toast.negative("오류가 발생했습니다", { description: "잠시 후 다시 시도해주세요" });
// Progress
<Progress value={72} showLabel />
<Progress indeterminate color="primary" /> {/* 스트라이프 흐름 애니메이션 */}Layout / 기타
| 컴포넌트 | 설명 |
|---|---|
| Card | 3가지 variant, onClick 시 tap 애니메이션 자동 활성화 |
| Spinner | 4가지 size, 3가지 color |
| Skeleton | text / circular / rectangular variant, multi-line 지원 |
| Tabs | line / pill variant |
| Accordion | 아코디언, Radix 기반 |
| Table | columns + data 배열 선언형 |
| Pagination | 페이지 이동 버튼 |
| Stepper | 단계 진행 표시 |
| Avatar | 이미지 + fallback 이니셜 |
| Tooltip | hover 시 설명 팝업 |
| Popover | 클릭 시 떠있는 패널 |
| DropdownMenu | 컨텍스트 메뉴 |
| Modal / Drawer | 전체 화면 오버레이 / 사이드 패널 |
| Calendar / DatePicker | 날짜 선택 |
| BottomCTA | 화면 하단 고정 CTA 버튼 영역 |
| ListRow | 아이템 목록 행 (아이콘 + 텍스트 + 우측 액션) |
| Result | 성공/실패/로딩 결과 화면 |
| Empty | 빈 상태 안내 |
| Icon | lucide-react 기반 아이콘 래퍼 |
| Form | react-hook-form 연동 Form 필드 |
<Card variant="elevated" onClick={() => navigate("/detail")}>
<Text variant="body2" color="muted">토스뱅크 통장</Text>
<Text variant="title2">1,234,567원</Text>
</Card>
<Skeleton variant="text" lines={3} />
<Skeleton variant="circular" width={48} height={48} />다크모드
CSS variable 기반으로 구현되어 있습니다. data-theme="dark" 속성 하나로 전체 테마가 전환됩니다.
// 다크모드 적용
document.documentElement.setAttribute("data-theme", "dark");
// 라이트모드 복귀
document.documentElement.removeAttribute("data-theme");Tailwind darkMode 클래스도 함께 지원합니다.
<html class="dark"> ... </html>디자인 토큰
CSS variable로 정의된 토큰을 직접 사용할 수 있습니다.
/* 컬러 */
var(--color-primary) /* #3182F6 */
var(--color-positive) /* #00B493 */
var(--color-negative) /* #F04452 */
var(--color-warning) /* #FF8A00 */
var(--color-foreground)
var(--color-muted)
var(--color-border)
/* 그림자 */
var(--shadow-sm)
var(--shadow-md)
var(--shadow-lg)
var(--shadow-overlay)TypeScript 토큰 상수도 export합니다.
import { colors, typography } from "mokona-ui";
colors.primary.DEFAULT // "#3182f6"
typography.title1 // { fontSize: "22px", lineHeight: "1.4", fontWeight: 700 }Peer Dependencies
{
"react": "^17 || ^18 || ^19",
"react-dom": "^17 || ^18 || ^19"
}성능 설계
LazyMotion으로 Framer Motion 번들 절감
모든 애니메이션 컴포넌트에 LazyMotion + domAnimation + m.* 패턴을 적용했습니다.
motion.* 대신 m.*을 사용하면 Framer Motion의 고급 기능(3D, layout animation 등)을 제외한 기본 기능만 로드해 번들 크기를 줄입니다.
// ❌ 전체 번들 포함
import { motion } from "framer-motion";
// ✅ domAnimation만 로드 (~30% 절감)
import { LazyMotion, domAnimation, m } from "framer-motion";
<LazyMotion features={domAnimation}>
<m.div whileTap={{ scale: 0.96 }} />
</LazyMotion>useSyncExternalStore 기반 Toast 상태
useToast는 React 18의 useSyncExternalStore로 구현했습니다.
여러 컴포넌트가 useToast()를 구독해도 상태 변경 시 setState가 한 번만 발생합니다.
// ❌ 기존: N개 구독자 → N번 setState
listeners.forEach((l) => l(toasts));
// ✅ 개선: React가 배치 처리
useSyncExternalStore(subscribe, getSnapshot);Subpath exports로 트리쉐이킹
Button만 사용해도 BottomSheet(Framer Motion drag 포함)가 번들에 들어가는 문제를 방지합니다.
// BottomSheet 코드가 번들에 포함되지 않음
import { Button } from "mokona-ui/button";Skeleton GPU 가속
shimmer 애니메이션에 will-change: transform을 적용해 GPU 합성 레이어로 분리했습니다.
여러 Skeleton이 동시에 렌더링될 때 CPU 부하가 줄어듭니다.
Card 리마운트 방지
interactive prop 유무에 따라 motion.div와 div를 분기하면 prop이 바뀔 때 컴포넌트가 리마운트됩니다.
항상 motion.div를 사용하고 whileTap만 조건부로 적용해 이 문제를 방지했습니다.
Showcase
컴포넌트 데모 앱이 showcase/ 폴더에 포함되어 있습니다 (Next.js).
cd showcase && pnpm dev # http://localhost:3000개발
# 컴포넌트 개발 서버
pnpm storybook # http://localhost:6006
# 빌드
pnpm build
# 테스트
pnpm test
# 릴리즈 — package.json version 올리고 커밋/푸시하면 GitHub Actions가 자동 배포
# (수동 배포 시: pnpm publish — prepublishOnly로 build 자동 선행 실행)더 자세한 내용은 CLAUDE.md · TECH.md · PROJECT.md를 참고하세요.
스택
- Radix UI — 접근성 primitives
- Tailwind CSS v3 — CSS variable 기반 토큰 시스템
- CVA (class-variance-authority) — variant 관리
- Framer Motion v10 — 애니메이션
- tsup — ESM + CJS 듀얼 번들
- Storybook 8 — 컴포넌트 문서 및 테스트
- Vitest — 단위 테스트
- Changesets — 버전 관리 및 npm 배포
