krds-react-components
v2.0.1
Published
Korea Responsive Design System React Components
Maintainers
Readme
KRDS React Components
KRDS(Korea Responsive Design System)는 대한민국 디지털 정부를 위한 React 컴포넌트 라이브러리입니다. 반응형, 접근성을 갖춘 UI/UX를 빠르고 일관되게 개발할 수 있도록 지원합니다.
📦 설치
npm install krds-react-components styled-components
# 또는
yarn add krds-react-components styled-components
# 또는
pnpm add krds-react-components styled-components🚀 Next.js에서 사용하기 (Step by Step)
1단계: 프로젝트 생성 및 패키지 설치
# Next.js 프로젝트 생성 (TypeScript 사용 권장)
npx create-next-app@latest my-gov-app --typescript --tailwind --app
# 프로젝트 디렉토리로 이동
cd my-gov-app
# KRDS React Components와 의존성 설치
npm install krds-react-components styled-components
# TypeScript용 타입 정의 설치
npm install -D @types/styled-components2단계: Next.js Config 설정 (next.config.js)
/** @type {import('next').NextConfig} */
const nextConfig = {
compiler: {
// styled-components SSR 지원
styledComponents: true,
},
transpilePackages: ['krds-react-components'],
}
module.exports = nextConfig3단계: ThemeProvider 설정 (app/providers.tsx)
'use client'
import React from 'react'
import { ThemeProvider as KRDSThemeProvider, GlobalStyles, lightTheme } from 'krds-react-components'
import { ThemeProvider as StyledThemeProvider } from 'styled-components'
export function Providers({ children }: { children: React.ReactNode }) {
return (
<StyledThemeProvider theme={lightTheme}>
<KRDSThemeProvider initialMode="light">
<GlobalStyles />
{children}
</KRDSThemeProvider>
</StyledThemeProvider>
)
}4단계: 루트 레이아웃 설정 (app/layout.tsx)
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import { Providers } from './providers'
import './globals.css'
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
title: '정부 웹사이트',
description: 'KRDS React Components를 사용한 정부 웹사이트',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="ko">
<body className={inter.className}>
<Providers>
{children}
</Providers>
</body>
</html>
)
}5단계: 메인 페이지에서 컴포넌트 사용 (app/page.tsx)
'use client'
import { useState } from 'react'
import {
Header,
Footer,
Layout,
Button,
Input,
Select,
Alert,
Card,
Table
} from 'krds-react-components'
export default function Home() {
const [formData, setFormData] = useState({
name: '',
email: '',
region: ''
})
const navigationItems = [
{ id: 'home', label: '홈', href: '/' },
{ id: 'services', label: '서비스', href: '/services' },
{ id: 'support', label: '민원신청', href: '/support' },
{ id: 'info', label: '정보공개', href: '/info' }
]
const regions = [
{ value: 'seoul', label: '서울특별시' },
{ value: 'busan', label: '부산광역시' },
{ value: 'daegu', label: '대구광역시' },
{ value: 'incheon', label: '인천광역시' }
]
const tableData = [
{ id: 1, title: '시스템 점검 안내', date: '2024-08-14', status: '진행중' },
{ id: 2, title: '신청 서비스 개선', date: '2024-08-13', status: '완료' },
{ id: 3, title: '보안 업데이트', date: '2024-08-12', status: '예정' }
]
const tableColumns = [
{ key: 'title', title: '제목', dataIndex: 'title' },
{ key: 'date', title: '날짜', dataIndex: 'date' },
{ key: 'status', title: '상태', dataIndex: 'status' }
]
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault()
alert(`제출 완료: ${JSON.stringify(formData, null, 2)}`)
}
return (
<Layout>
{/* 헤더 */}
<Header
logo={{ text: '정부24', href: '/' }}
navigation={navigationItems}
/>
<main style={{ padding: '2rem 0', minHeight: 'calc(100vh - 200px)' }}>
<div style={{ maxWidth: '1200px', margin: '0 auto', padding: '0 2rem' }}>
{/* 페이지 제목 */}
<div style={{ textAlign: 'center', marginBottom: '3rem' }}>
<h1>KRDS React Components</h1>
<p>Next.js에서 한국 반응형 디자인 시스템 사용하기</p>
</div>
{/* 알림 */}
<Alert
variant="info"
title="환영합니다!"
style={{ marginBottom: '2rem' }}
>
KRDS React Components를 Next.js에서 사용하는 예시입니다.
</Alert>
{/* 폼 섹션 */}
<div style={{ marginBottom: '3rem' }}>
<h2>신청 폼 예시</h2>
<form onSubmit={handleSubmit} style={{ maxWidth: '500px' }}>
<Input
label="이름"
value={formData.name}
onChange={(e) => setFormData(prev => ({ ...prev, name: e.target.value }))}
placeholder="이름을 입력하세요"
required
style={{ marginBottom: '1rem' }}
/>
<Input
label="이메일"
type="email"
value={formData.email}
onChange={(e) => setFormData(prev => ({ ...prev, email: e.target.value }))}
placeholder="이메일을 입력하세요"
required
style={{ marginBottom: '1rem' }}
/>
<Select
label="지역"
options={regions}
value={formData.region}
onChange={(value) => setFormData(prev => ({ ...prev, region: value }))}
placeholder="지역을 선택하세요"
required
style={{ marginBottom: '1.5rem' }}
/>
<div style={{ display: 'flex', gap: '1rem' }}>
<Button type="submit" variant="primary">
제출하기
</Button>
<Button
type="button"
variant="secondary"
onClick={() => setFormData({ name: '', email: '', region: '' })}
>
초기화
</Button>
</div>
</form>
</div>
{/* 테이블 섹션 */}
<div style={{ marginBottom: '3rem' }}>
<h2>공지사항</h2>
<Table
columns={tableColumns}
dataSource={tableData}
caption="공지사항 목록"
/>
</div>
{/* 버튼 그룹 */}
<div style={{ marginBottom: '3rem' }}>
<h2>버튼 예시</h2>
<div style={{ display: 'flex', gap: '1rem', flexWrap: 'wrap' }}>
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="tertiary">Tertiary</Button>
<Button variant="text">Text</Button>
<Button loading>Loading</Button>
<Button disabled>Disabled</Button>
</div>
</div>
</div>
</main>
{/* 푸터 */}
<Footer
copyright="© 2024 정부24. All rights reserved."
links={[
{ label: '이용약관', href: '/terms' },
{ label: '개인정보처리방침', href: '/privacy' },
{ label: '접근성 정책', href: '/accessibility' }
]}
/>
</Layout>
)
}6단계: 프로젝트 실행
# 개발 서버 실행
npm run dev
# 빌드 (배포 전 확인)
npm run build
# 빌드된 프로젝트 실행
npm start7단계: TypeScript 설정 최적화 (tsconfig.json)
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "es6"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}8단계: 스타일드 컴포넌트 레지스트리 설정 (선택사항)
SSR 스타일 이슈 해결을 위한 설정:
app/lib/registry.tsx
'use client'
import React, { useState } from 'react'
import { useServerInsertedHTML } from 'next/navigation'
import { ServerStyleSheet, StyleSheetManager } from 'styled-components'
export default function StyledComponentsRegistry({
children,
}: {
children: React.ReactNode
}) {
const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet())
useServerInsertedHTML(() => {
const styles = styledComponentsStyleSheet.getStyleElement()
styledComponentsStyleSheet.instance.clearTag()
return <>{styles}</>
})
if (typeof window !== 'undefined') return <>{children}</>
return (
<StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
{children}
</StyleSheetManager>
)
}app/layout.tsx 업데이트
import StyledComponentsRegistry from './lib/registry'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="ko">
<body className={inter.className}>
<StyledComponentsRegistry>
<Providers>
{children}
</Providers>
</StyledComponentsRegistry>
</body>
</html>
)
}
## 빠른 시작
### 1. 기본 설정
외부 앱에서 KRDS를 사용하려면 먼저 ThemeProvider와 GlobalStyles를 설정해야 합니다.
```tsx
import React from 'react'
import { ThemeProvider } from 'styled-components'
import { lightTheme, GlobalStyles } from 'krds-react-components'
function App() {
return (
<ThemeProvider theme={lightTheme}>
<GlobalStyles />
<div className="App">
{/* 여기에 앱 컨텐츠 */}
</div>
</ThemeProvider>
)
}
export default App2. 폰트 설정
PretendardGOV 폰트는 패키지에 자동으로 포함되어 있습니다. 추가 설정이 필요하지 않습니다.
참고: 인터넷 연결이 필요한 CDN 기반 폰트를 사용합니다. 오프라인 환경에서는 별도 폰트 설정이 필요할 수 있습니다.
3. 기본 컴포넌트 사용
import { Button, Input, Alert } from 'krds-react-components'
function MyPage() {
return (
<div>
<Alert variant="info" title="안내">
KRDS 컴포넌트 라이브러리에 오신 것을 환영합니다.
</Alert>
<Input
label="이름"
placeholder="이름을 입력하세요"
required
/>
<Button variant="primary" size="large">
제출하기
</Button>
</div>
)
}컴포넌트 상세 사용법
Layout Components
Header - 정부 사이트 표준 헤더
import { Header } from 'krds-react-components'
function App() {
const navigationItems = [
{ id: 'home', label: '홈', href: '/' },
{ id: 'about', label: '소개', href: '/about' },
{ id: 'services', label: '서비스', href: '/services' }
]
const userInfo = {
name: '홍길동',
department: '행정안전부',
isLoggedIn: true
}
return (
<Header
siteName="정부 웹사이트"
logoSrc="/logo.png"
navigationItems={navigationItems}
userInfo={userInfo}
showLanguageSwitcher
onLogoClick={() => window.location.href = '/'}
/>
)
}Footer - 정부 사이트 표준 푸터
import { Footer } from 'krds-react-components'
function App() {
const footerSections = [
{
title: '관련 사이트',
links: [
{ label: '정부24', href: 'https://gov.kr' },
{ label: '국민신문고', href: 'https://epeople.go.kr' }
]
}
]
return (
<Footer
siteName="행정안전부"
address="서울특별시 종로구 세종대로 209"
phone="02-2100-3000"
sections={footerSections}
showAccessibility
/>
)
}Data Display Components
Table - 데이터 테이블
import { Table } from 'krds-react-components'
function DataPage() {
const columns = [
{
key: 'name',
title: '이름',
dataIndex: 'name',
width: '20%'
},
{
key: 'department',
title: '부서',
dataIndex: 'department'
},
{
key: 'position',
title: '직책',
dataIndex: 'position'
},
{
key: 'action',
title: '작업',
dataIndex: 'action',
render: (_, record) => (
<Button size="small" onClick={() => handleEdit(record.id)}>
수정
</Button>
)
}
]
const data = [
{ id: 1, name: '홍길동', department: '행정안전부', position: '과장' },
{ id: 2, name: '김철수', department: '국토교통부', position: '주무관' }
]
return (
<Table
columns={columns}
dataSource={data}
caption="직원 목록 테이블"
bordered
striped
hoverable
/>
)
}Tab - 탭 인터페이스
import { Tab } from 'krds-react-components'
function ContentPage() {
const items = [
{
key: 'notice',
label: '공지사항',
content: (
<div>
<h3>최신 공지사항</h3>
<p>시스템 점검 안내...</p>
</div>
)
},
{
key: 'data',
label: '자료실',
content: (
<div>
<h3>다운로드 자료</h3>
<ul>
<li>사용자 가이드.pdf</li>
<li>API 문서.pdf</li>
</ul>
</div>
)
},
{
key: 'faq',
label: 'FAQ',
content: <div>자주 묻는 질문들...</div>
}
]
return (
<Tab
items={items}
defaultActiveKey="notice"
variant="line"
onChange={(key) => console.log('Active tab:', key)}
/>
)
}Accordion - 아코디언
import { Accordion } from 'krds-react-components'
function FAQPage() {
const items = [
{
key: 'faq1',
header: '서비스 이용 시간은 어떻게 되나요?',
content: (
<div>
<p>24시간 연중무휴로 서비스를 제공합니다.</p>
<p>단, 매주 일요일 새벽 2시~6시는 시스템 점검 시간입니다.</p>
</div>
)
},
{
key: 'faq2',
header: '비밀번호를 잊어버렸어요',
content: (
<div>
<p>로그인 페이지에서 '비밀번호 찾기'를 클릭하세요.</p>
<ol>
<li>본인 확인 절차를 진행합니다</li>
<li>등록된 이메일로 임시 비밀번호를 발송합니다</li>
<li>로그인 후 비밀번호를 변경하세요</li>
</ol>
</div>
)
}
]
return (
<Accordion
items={items}
multiple
bordered
collapsible
/>
)
}Navigation Components
Breadcrumb - 브레드크럼
import { Breadcrumb } from 'krds-react-components'
function DetailPage() {
const items = [
{ label: '홈', href: '/' },
{ label: '공지사항', href: '/notice' },
{ label: '시스템 점검 안내' }
]
return (
<Breadcrumb
items={items}
showHome
separator=">"
maxItems={4}
/>
)
}Pagination - 페이지네이션
import { Pagination } from 'krds-react-components'
function ListPage() {
const [currentPage, setCurrentPage] = useState(1)
const totalPages = 20
return (
<div>
{/* 리스트 내용 */}
<Pagination
currentPage={currentPage}
totalPages={totalPages}
onPageChange={setCurrentPage}
showFirstLast
showPrevNext
maxPageButtons={5}
/>
</div>
)
}Feedback Components
Modal - 모달 다이얼로그
import { Modal, Button } from 'krds-react-components'
function ActionPage() {
const [isDeleteOpen, setIsDeleteOpen] = useState(false)
const [isInfoOpen, setIsInfoOpen] = useState(false)
const handleDelete = () => {
// 삭제 로직
setIsDeleteOpen(false)
}
return (
<div>
<Button onClick={() => setIsDeleteOpen(true)} variant="danger">
삭제
</Button>
<Button onClick={() => setIsInfoOpen(true)} variant="secondary">
정보 보기
</Button>
{/* 확인 모달 */}
<Modal
open={isDeleteOpen}
title="삭제 확인"
size="small"
onClose={() => setIsDeleteOpen(false)}
footer={
<div style={{ display: 'flex', gap: '8px', justifyContent: 'flex-end' }}>
<Button variant="secondary" onClick={() => setIsDeleteOpen(false)}>
취소
</Button>
<Button variant="danger" onClick={handleDelete}>
삭제
</Button>
</div>
}
>
<p>정말로 이 항목을 삭제하시겠습니까?</p>
<p>삭제된 데이터는 복구할 수 없습니다.</p>
</Modal>
{/* 정보 모달 */}
<Modal
open={isInfoOpen}
title="상세 정보"
size="medium"
onClose={() => setIsInfoOpen(false)}
>
<div>
<h4>서비스 안내</h4>
<p>본 서비스는 정부24와 연계하여 제공됩니다.</p>
</div>
</Modal>
</div>
)
}Form 통합 예제
import {
Input, Select, Checkbox, Radio, Textarea, Switch, Button, Alert
} from 'krds-react-components'
function RegisterForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
region: '',
gender: '',
agreement: false,
notifications: true,
description: ''
})
const [errors, setErrors] = useState({})
const regions = [
{ value: 'seoul', label: '서울특별시' },
{ value: 'busan', label: '부산광역시' },
{ value: 'daegu', label: '대구광역시' },
{ value: 'incheon', label: '인천광역시' }
]
const handleSubmit = (e) => {
e.preventDefault()
// 폼 제출 로직
}
return (
<form onSubmit={handleSubmit}>
<Alert variant="info" title="회원가입 안내">
모든 필수 항목을 입력해주세요.
</Alert>
<Input
label="이름"
value={formData.name}
onChange={(e) => setFormData(prev => ({ ...prev, name: e.target.value }))}
required
state={errors.name ? 'error' : undefined}
errorMessage={errors.name}
/>
<Input
label="이메일"
type="email"
value={formData.email}
onChange={(e) => setFormData(prev => ({ ...prev, email: e.target.value }))}
required
state={errors.email ? 'error' : undefined}
errorMessage={errors.email}
/>
<Select
label="지역"
options={regions}
value={formData.region}
onChange={(value) => setFormData(prev => ({ ...prev, region: value }))}
placeholder="지역을 선택하세요"
required
/>
<fieldset>
<legend>성별</legend>
<Radio
name="gender"
value="male"
label="남성"
checked={formData.gender === 'male'}
onChange={(value) => setFormData(prev => ({ ...prev, gender: value }))}
/>
<Radio
name="gender"
value="female"
label="여성"
checked={formData.gender === 'female'}
onChange={(value) => setFormData(prev => ({ ...prev, gender: value }))}
/>
</fieldset>
<Textarea
label="자기소개"
value={formData.description}
onChange={(e) => setFormData(prev => ({ ...prev, description: e.target.value }))}
placeholder="간단한 자기소개를 입력하세요"
maxLength={500}
showCount
/>
<Checkbox
label="이용약관에 동의합니다"
checked={formData.agreement}
onChange={(checked) => setFormData(prev => ({ ...prev, agreement: checked }))}
required
/>
<Switch
label="알림 받기"
checked={formData.notifications}
onChange={(checked) => setFormData(prev => ({ ...prev, notifications: checked }))}
checkedLabel="켜짐"
uncheckedLabel="꺼짐"
/>
<div style={{ marginTop: '24px' }}>
<Button type="submit" variant="primary" size="large" fullWidth>
회원가입
</Button>
</div>
</form>
)
}컴포넌트
Button
import { Button } from 'krds-react-components'
<Button variant="primary" size="large">
기본 버튼
</Button>
<Button variant="secondary" disabled>
비활성화 버튼
</Button>
<Button variant="text" loading>
로딩 중...
</Button>Badge
import { Badge } from 'krds-react-components'
<Badge variant="primary">Label</Badge>
<Badge variant="danger" count={5} />
<Badge variant="success" dot />Form Components
Input
import { Input } from 'krds-react-components'
<Input
label="이름"
placeholder="이름을 입력하세요"
required
/>
<Input
label="이메일"
type="email"
state="error"
errorMessage="올바른 이메일을 입력하세요"
/>Checkbox
import { Checkbox } from 'krds-react-components'
<Checkbox label="이용약관 동의" required />
<Checkbox
label="마케팅 수신 동의"
description="선택사항입니다"
/>Radio
import { Radio, RadioGroup } from 'krds-react-components'
<RadioGroup name="gender" defaultValue="male">
<Radio value="male" label="남성" />
<Radio value="female" label="여성" />
<Radio value="other" label="기타" />
</RadioGroup>Select
import { Select } from 'krds-react-components'
<Select
label="지역 선택"
placeholder="지역을 선택하세요"
options={[
{ value: 'seoul', label: '서울' },
{ value: 'busan', label: '부산' },
{ value: 'daegu', label: '대구' }
]}
/>Textarea
import { Textarea } from 'krds-react-components'
<Textarea
label="의견"
placeholder="의견을 입력하세요"
maxLength={500}
showCount
/>Switch
import { Switch } from 'krds-react-components'
<Switch label="알림 받기" />
<Switch
label="다크 모드"
checkedLabel="켜짐"
uncheckedLabel="꺼짐"
/>테마
라이트 모드
기본 테마로 일반적인 사용 환경에 적합합니다.
고대비 모드
시각적 접근성이 필요한 사용자를 위한 테마입니다.
<ThemeProvider initialMode="high-contrast">
<App />
</ThemeProvider>접근성
KRDS React는 웹 접근성 지침(WCAG 2.1)을 준수하여 개발되었습니다:
- 키보드 내비게이션 지원
- 스크린 리더 호환
- 고대비 모드 지원
- 적절한 ARIA 속성
개발
# 개발 서버 시작 (Storybook)
npm run dev
# 빌드
npm run build
# 테스트
npm test
# 린트
npm run lint테마 커스터마이징
기본 테마를 확장하여 사용할 수 있습니다:
import { lightTheme } from 'krds-react-components'
const customTheme = {
...lightTheme,
colors: {
...lightTheme.colors,
primary: {
...lightTheme.colors.primary,
50: '#1a73e8' // 사용자 정의 색상
}
},
spacing: {
...lightTheme.spacing,
custom: '2.5rem' // 사용자 정의 간격
}
}
// ThemeProvider에 customTheme 사용
<ThemeProvider theme={customTheme}>
<App />
</ThemeProvider>고대비 모드
시각적 접근성이 필요한 사용자를 위한 고대비 테마를 제공합니다:
import { highContrastTheme } from 'krds-react-components'
<ThemeProvider theme={highContrastTheme}>
<App />
</ThemeProvider>TypeScript 지원
모든 컴포넌트는 완전한 TypeScript 지원을 제공합니다:
import { ButtonProps, InputProps, TableColumn } from 'krds-react-components'
// 컴포넌트 props 타입 확장
interface CustomButtonProps extends ButtonProps {
customProp?: string
}
// 테이블 컬럼 타입 정의
const columns: TableColumn[] = [
{
key: 'name',
title: '이름',
dataIndex: 'name',
render: (value: string) => <strong>{value}</strong>
}
]패키지 빌드 및 배포
개발환경 설정
# 의존성 설치
npm install
# 개발 서버 시작 (Storybook)
npm run dev
# 빌드
npm run build
# 테스트
npm test
# 린트
npm run lint
# 타입 체크
npm run type-checkNPM 배포
# 빌드
npm run build
# 배포
npm publish다른 프로젝트에서 사용
# 설치
npm install krds-react-components styled-components
# 또는 로컬 개발용
npm install file:../krds-react접근성
KRDS 컴포넌트는 웹 접근성 지침(WCAG 2.1 AA)을 준수합니다:
지원하는 접근성 기능
- 키보드 내비게이션: 모든 인터랙티브 요소는 키보드로 접근 가능
- 스크린 리더 호환: 적절한 ARIA 속성과 시맨틱 마크업 사용
- 색상 대비: WCAG AA 기준 이상의 색상 대비 제공
- 포커스 관리: 명확한 포커스 표시 및 논리적 탭 순서
- 다국어 지원: 한국어 기본, 영어 지원
접근성 사용 예제
// 스크린 리더용 텍스트
<Button>
저장
<span className="sr-only">현재 문서를</span>
</Button>
// ARIA 레이블 사용
<Input
label="검색어"
aria-describedby="search-help"
/>
<div id="search-help">
검색할 키워드를 입력하세요
</div>
// 키보드 단축키 지원
<Modal>
<p>ESC 키를 눌러 모달을 닫을 수 있습니다.</p>
</Modal>브라우저 지원
- Chrome (최신 2개 버전)
- Firefox (최신 2개 버전)
- Safari (최신 2개 버전)
- Edge (최신 2개 버전)
- Internet Explorer 11+
성능 최적화
Tree Shaking
필요한 컴포넌트만 import하여 번들 크기를 최적화할 수 있습니다:
// ✅ 권장: 개별 import
import { Button } from 'krds-react-components/Button'
import { Input } from 'krds-react-components/Input'
// ✅ 가능: 전체 import (Tree shaking 지원)
import { Button, Input } from 'krds-react-components'
// ❌ 비권장: 전체 라이브러리 import
import * as KRDS from 'krds-react-components'코드 분할
import { lazy, Suspense } from 'react'
// 필요한 시점에 로드
const Table = lazy(() => import('krds-react-components/Table'))
function DataPage() {
return (
<Suspense fallback={<div>로딩 중...</div>}>
<Table columns={columns} dataSource={data} />
</Suspense>
)
}문제 해결
스타일이 적용되지 않는 경우
- ThemeProvider가 올바르게 설정되었는지 확인
- GlobalStyle이 포함되었는지 확인
- styled-components 버전 호환성 확인
// 올바른 설정
import { ThemeProvider } from 'styled-components'
import { lightTheme, GlobalStyles } from 'krds-react-components'
<ThemeProvider theme={lightTheme}>
<GlobalStyles />
<App />
</ThemeProvider>TypeScript 오류
- @types/styled-components 설치 확인
- tsconfig.json 설정 확인
{
"compilerOptions": {
"jsx": "react-jsx",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true
}
}라이센스
MIT License
기여하기
- 이 저장소를 Fork합니다
- 기능 브랜치를 생성합니다 (
git checkout -b feature/amazing-feature) - 변경사항을 커밋합니다 (
git commit -m 'Add some amazing feature') - 브랜치에 Push합니다 (
git push origin feature/amazing-feature) - Pull Request를 생성합니다
지원 및 문의
- 이슈 보고: GitHub Issues
- 문서 사이트: KRDS React 문서
- 스토리북: 컴포넌트 카탈로그
- 이메일: [email protected]
변경 이력
v1.0.0 (2025-08-14)
- 🎉 초기 릴리즈
- ✨ 모든 기본 컴포넌트 포함 (Button, Input, Table, Modal 등)
- 🎨 KRDS 디자인 시스템 완전 구현
- ♿ WCAG 2.1 AA 접근성 기준 준수
- 🔧 TypeScript 완전 지원
- 📱 반응형 디자인 지원
- 🌙 라이트/고대비 테마 지원
- 📚 Storybook 문서화
