@samusesapple/react-native-design
v0.1.0
Published
React Native design system built with NativeWind
Maintainers
Readme
@samusesapple/react-native-design
React Native 디자인 시스템 (NativeWind 기반)
설치
yarn add @samusesapple/react-native-designPeer Dependencies
yarn add react react-native nativewind tailwindcss프로젝트 초기 세팅
1. Tailwind 설정
프로젝트 루트의 tailwind.config.ts에서 디자인 시스템의 preset을 확장합니다.
// tailwind.config.ts
import type { Config } from "tailwindcss";
import designSystemConfig from "@samusesapple/react-native-design/tailwind.config";
const config: Config = {
content: ["./src/**/*.{js,ts,jsx,tsx}"],
presets: [designSystemConfig],
theme: {
extend: {
// 프로젝트별 커스텀 토큰 추가 가능
},
},
};
export default config;2. Provider 설정
앱 최상위에 DesignSystemProvider를 감싸줍니다. locale에 따라 Typography 토큰이 자동 전환됩니다.
import { DesignSystemProvider } from "@samusesapple/react-native-design";
export default function App() {
return (
<DesignSystemProvider locale="ko">{/* 앱 콘텐츠 */}</DesignSystemProvider>
);
}| locale | 설명 |
| ------ | --------------- |
| ko | 한국어 (기본값) |
| en | 영어 |
색상 모드 (colorScheme)
색상 모드는 제어/비제어 두 방식으로 사용할 수 있습니다. NativeWind colorScheme과 연동되어 컴포넌트의 dark: variant와 useDesignSystem().colorScheme에 반영됩니다.
dark 모드에서는 surface/text/border/icon/systemState 및 모든 컴포넌트 색상이 WCAG AA 대비를 만족하는 기본 다크 토큰으로 자동 전환됩니다. useResolveColor()로 해석되는 색상(SVG fill 등)도 활성 모드에 맞게 반환됩니다.
1. OS 설정 따라가기 (제어)
colorScheme="system"을 지정하면 OS 다크/라이트 설정을 실시간으로 따라갑니다.
<DesignSystemProvider colorScheme="system">{/* 앱 콘텐츠 */}</DesignSystemProvider>| colorScheme | 설명 |
| ----------- | -------------------- |
| light | 라이트 모드 |
| dark | 다크 모드 |
| system | OS 설정을 따름 |
colorScheme을 지정하면 제어 모드가 되어 그 값이 강제됩니다. 앱 상태로 직접 관리하려면colorScheme={myState}처럼 넘기고myState를 갱신하세요.
2. 앱 내 수동 토글 (비제어)
colorScheme을 생략하면 비제어 모드가 됩니다. 초기값은 defaultColorScheme(기본 "light")로 정하고, useDesignSystem()의 toggleColorScheme/setColorScheme으로 앱에서 전환합니다.
import { useDesignSystem } from "@samusesapple/react-native-design";
// Provider: colorScheme 생략 → 비제어
<DesignSystemProvider defaultColorScheme="light">{/* ... */}</DesignSystemProvider>;
// 어디서든 토글
function ThemeToggleButton() {
const { colorScheme, toggleColorScheme, setColorScheme } = useDesignSystem();
return (
<Button onPress={toggleColorScheme}>
{colorScheme === "dark" ? "라이트로" : "다크로"}
</Button>
);
// setColorScheme("system") 으로 OS 추종으로 되돌릴 수도 있습니다.
}| useDesignSystem() | 타입 | 설명 |
| ----------------- | ------------------------------------------- | -------------------------- |
| colorScheme | "light" \| "dark" | 현재 활성 모드 |
| toggleColorScheme | () => void | light ↔ dark 토글 |
| setColorScheme | (s: "light" \| "dark" \| "system") => void | 특정 모드로 설정 |
색상 토큰 오버라이드
DesignSystemProvider의 colorOverrides prop으로 색상 토큰을 프로젝트별로 오버라이드할 수 있습니다. 색상은 brand → semantic → component 순으로 파생되며, 상위 레벨을 바꾸면 하위 파생값이 자동으로 갱신됩니다. 오버라이드하지 않은 값은 기본값이 유지됩니다.
colorOverrides는 semantic과 component 두 그룹으로 구성됩니다.
import {
DesignSystemProvider,
baseColors,
} from "@samusesapple/react-native-design";
export default function App() {
return (
<DesignSystemProvider
locale="ko"
colorOverrides={{
semantic: {
brand: { primary: baseColors.apple },
},
}}
>
{/* 앱 콘텐츠 */}
</DesignSystemProvider>
);
}brand 오버라이드
brand.primary를 다른 팔레트(baseColors.*)로 교체하면 surface.brandPrimary, text.brand, border.brand 등 brand에서 파생되는 semantic 값과, 이를 참조하는 component 색상(버튼·인풋 등)이 모두 자동 갱신됩니다.
colorOverrides={{
semantic: {
brand: { primary: baseColors.coral },
},
}}brandPrimaryBaseLevel prop으로 brand.primary가 사용할 기준 명도 레벨(기본 500)을 조정할 수 있습니다.
<DesignSystemProvider brandPrimaryBaseLevel={600}>개별 semantic 오버라이드
특정 semantic 값을 직접 지정할 수도 있습니다.
colorOverrides={{
semantic: {
text: { default: { primary: "#111111" } },
surface: { default: { brandPrimary: "#FF0000" } },
},
}}component 오버라이드
특정 컴포넌트의 색상만 변경하고 싶을 때 사용합니다.
colorOverrides={{
component: {
button: {
primary: { background: "#FF0000", label: "#FFFFFF" },
},
},
}}다크 모드 오버라이드
darkColorOverrides는 colorOverrides와 동일한 구조({ semantic, component })로, 다크 모드 전용 색상을 커스터마이즈합니다. light와 독립적으로 적용되며, 지정하지 않은 값은 기본 다크 토큰이 유지됩니다.
<DesignSystemProvider
colorScheme="system"
colorOverrides={{ semantic: { brand: { primary: baseColors.apple } } }}
darkColorOverrides={{
semantic: {
surface: { default: { background: "#0a0a0a" } },
text: { default: { primary: "#fafafa" } },
},
}}
>
{/* 앱 콘텐츠 */}
</DesignSystemProvider>비색상 토큰(spacing · height · borderRadius · fontWeight) 은 현재 런타임 오버라이드를 지원하지 않습니다. 위 1단계의 Tailwind preset 확장(
theme.extend)을 통해 빌드 타임에 커스터마이즈하세요.
Tokens
디자인 토큰을 직접 import하여 사용할 수 있습니다.
import {
baseColors,
semanticColors,
componentColors,
spacing,
height,
borderRadius,
fontWeight,
typography,
} from "@samusesapple/react-native-design";색상 토큰 구조
색상은 base → semantic → component 세 레벨로 export됩니다.
| 레벨 | 토큰 | 설명 |
| ------------- | ---------------------------- | -------------------------------------------------------- |
| Base | baseColors | 기본 컬러 팔레트 (gray, coral, apple, sky 등) |
| Semantic | semanticColors.brand | 브랜드 컬러 (primary, secondary) |
| | semanticColors.text | 텍스트 컬러 (default, inverse 모드별) |
| | semanticColors.surface | 면/배경 컬러 |
| | semanticColors.border | 선/구분선 컬러 |
| | semanticColors.icon | 아이콘 컬러 |
| | semanticColors.systemState | 시스템 상태 컬러 (success, info, warning, error) |
| Component | componentColors.button | 버튼 컬러 |
| | componentColors.input | 인풋 컬러 |
| | componentColors.navigation | 네비게이션 컬러 |
| | componentColors.modal | 모달 컬러 |
| | componentColors.filter | 필터 컬러 |
| | componentColors.toggle | 토글 컬러 |
기타 토큰
| 토큰 | 설명 |
| -------------- | --------------------------------------------------- |
| spacing | 간격 (xs~3xl) |
| height | 높이 (버튼, 인풋 등 컴포넌트별) |
| borderRadius | 모서리 라운딩 (버튼, 인풋, 모달 등 컴포넌트별) |
| fontWeight | 폰트 두께 (regular, medium, semibold, bold) |
| typography | 언어별 타이포그래피 스타일 (ko, en) |
아이콘
SVG 파일에서 React Native 아이콘 컴포넌트를 자동 생성합니다.
아이콘 생성
yarn generate:iconssrc/assets/icons/ 하위에 SVG 파일을 배치하면 자동으로 react-native-svg 기반 컴포넌트가 생성됩니다.
폴더 구조가 그대로 namespace export에 반영됩니다.
사용법
import { Default, Round } from "@samusesapple/react-native-design";
<Default.Solid.Heart size={24} color="red" />
<Default.Stroke.Search size={20} color="#333" />
<Round.Solid.Home size={28} color="blue" />폴더 구조 → Export 매핑
| assets 경로 | 사용법 |
| --------------------------------- | ----------------------- |
| icons/Default/Solid/Heart.svg | Default.Solid.Heart |
| icons/Default/Stroke/Search.svg | Default.Stroke.Search |
| icons/Round/Solid/Home.svg | Round.Solid.Home |
| icons/Logo.svg (루트) | Root.Logo |
폴더를 추가/삭제/이름변경 후 yarn generate:icons만 실행하면 전체 export 체인이 자동 반영됩니다.
소비 프로젝트에서 아이콘 생성
이 패키지를 설치한 프로젝트에서도 동일한 아이콘 생성 파이프라인을 사용할 수 있습니다:
# 기본 경로 (src/assets/icons → src/components/Icons)
npx react-native-design-icons
# 커스텀 경로
npx react-native-design-icons --input src/icons --output src/components/Icons
# components/index.ts 자동 동기화
npx react-native-design-icons --input src/icons --output src/components/Icons --components-index src/components/index.ts| 옵션 | 설명 | 기본값 |
| --------------------------- | ----------------------------- | ---------------------- |
| --input <dir> | SVG 소스 디렉토리 | src/assets/icons |
| --output <dir> | 출력 Icons 디렉토리 | src/components/Icons |
| --components-index <file> | export 자동 동기화할 index.ts | (없음) |
첫 실행 시 types.ts와 Icon.tsx가 자동 생성됩니다.
IconProps
| prop | 타입 | 기본값 | 설명 |
| ------- | ---------------------- | ---------------- | ---------------- |
| size | number | 24 | 아이콘 크기 (px) |
| color | string | "currentColor" | 아이콘 색상 |
| style | StyleProp<ViewStyle> | - | 추가 스타일 |
컴포넌트
Typography
import { Typography } from "@samusesapple/react-native-design";
<Typography variant="Body1">본문 텍스트</Typography>
<Typography.Heading1>제목</Typography.Heading1>
<Typography.Body2 color="#333">본문</Typography.Body2>Button
import { Button } from "@samusesapple/react-native-design";
<Button variant="primary" size="Medium">확인</Button>
<Button variant="ghost" size="Small" shape="round">취소</Button>
<Button variant="secondary" fullWidth>전체 너비</Button>| prop | 타입 | 기본값 | 설명 |
| ----------- | -------------------------------------------------------------------- | ----------- | -------------- |
| variant | "primary" | "secondary" | "ghost" | "gray" | "outline" | "primary" | 버튼 스타일 |
| size | "XSmall" | "Small" | "Medium" | "Large" | "XLarge" | "Medium" | 버튼 크기 |
| shape | "default" | "square" | "semiRound" | "round" | "default" | 모서리 형태 |
| fullWidth | boolean | false | 전체 너비 사용 |
| disabled | boolean | false | 비활성화 |
| iconFront | ReactNode | - | 앞쪽 아이콘 |
| iconBack | ReactNode | - | 뒤쪽 아이콘 |
TextField
import { TextField } from "@samusesapple/react-native-design";
<TextField placeholder="입력" />
<TextField shape="line" isError />
<TextField button={{ children: "인증", variant: "primary" }} />| prop | 타입 | 기본값 | 설명 |
| -------------- | ----------------------- | ----------- | --------- |
| shape | "default" | "line" | "default" | 인풋 형태 |
| isError | boolean | false | 에러 상태 |
| disabled | boolean | false | 비활성화 |
| rightElement | ReactNode | - | 우측 요소 |
| button | ButtonProps | - | 부착 버튼 |
유틸리티
import { cn } from "@samusesapple/react-native-design";
// tailwind-merge 기반 클래스 병합
<View className={cn("p-4", isActive && "bg-primary-500")} />;폴더 구조
src/
├── assets/
│ └── icons/ ← SVG 소스 (자유 구조)
│ ├── Default/
│ │ ├── Solid/*.svg
│ │ └── Stroke/*.svg
│ └── Round/
│ ├── Solid/*.svg
│ └── Stroke/*.svg
├── components/
│ ├── Icons/
│ │ ├── Icon.tsx ← createIcon 헬퍼 (수동 관리)
│ │ ├── types.ts ← IconProps (수동 관리)
│ │ ├── index.ts ← 자동 생성
│ │ └── generated/ ← 전부 자동 생성 (수동 편집 금지)
│ ├── Typography/
│ ├── Buttons/
│ ├── TextField/
│ ├── Checkbox/
│ └── Popup/
├── providers/
│ └── DesignSystemProvider.tsx
├── tokens/
│ ├── colors/
│ │ ├── constants/
│ │ │ ├── base.ts
│ │ │ ├── semantic.ts
│ │ │ ├── components.ts
│ │ │ └── index.ts
│ │ └── index.ts
│ ├── spacing/
│ ├── height/
│ ├── borderRadius/
│ ├── fontWeight/
│ ├── typography/
│ └── index.ts
├── utils/
│ └── cn.ts
└── index.ts스크립트
yarn build # 빌드
yarn dev # 워치 모드 빌드
yarn typecheck # 타입 체크
yarn lint # ESLint 검사
yarn clean # dist 폴더 삭제
yarn generate:icons # SVG → RN 아이콘 컴포넌트 자동 생성