Featuring Design System

Installation

Featuring Design System 설치 및 기본 설정

시스템 요구사항

  • React: 18 이상
  • Node.js: 18 이상
  • 패키지 매니저: npm, yarn, pnpm 모두 지원
현재 패키지 버전
패키지버전
@featuring-corp/design-tokens0.1.1
@featuring-corp/icons0.1.8
@featuring-corp/components0.1.25
@featuring-corp/charts0.1.1
Peer Dependencies
패키지Peer범위
@featuring-corp/iconsreact^18 || ^19
@featuring-corp/iconsreact-dom^18 || ^19
@featuring-corp/componentsoverlayscrollbars^2
@featuring-corp/componentsoverlayscrollbars-react>=0.5
@featuring-corp/componentsreact^18 || ^19
@featuring-corp/componentsreact-dom^18 || ^19
@featuring-corp/chartsreact^18 || ^19
@featuring-corp/chartsreact-dom^18 || ^19
@featuring-corp/chartsrecharts^3.8.0

1. NPM Registry 설정

패키지는 GitHub Packages에 배포되어 있습니다. 프로젝트 루트에 .npmrc 파일을 생성하세요.

.npmrc
@featuring-corp:registry=https://npm.pkg.github.com
always-auth=true
//npm.pkg.github.com/:_authToken=<YOUR_TOKEN>

<YOUR_TOKEN>을 GitHub Personal Access Token (read

권한)으로 교체하세요.

2. 패키지 설치

npm install @featuring-corp/design-tokens @featuring-corp/components @featuring-corp/icons

토큰만, 아이콘만 필요하다면 개별 설치도 됩니다:

npm install @featuring-corp/design-tokens

차트를 쓴다면 @featuring-corp/charts 와 peer dependency recharts 를 함께 설치합니다.

npm install @featuring-corp/charts recharts

recharts ^3.8.0 이상이 요구됩니다. peer dependency이므로 소비자 프로젝트에서 직접 설치해야 합니다.

3. Peer Dependencies

일부 컴포넌트(CoreDropdown, CoreModal, CoreSelectPrim, CoreMultiSelectPrim)는 커스텀 스크롤바를 위해 OverlayScrollbars를 씁니다. 해당 컴포넌트를 사용한다면:

npm install overlayscrollbars overlayscrollbars-react

위 컴포넌트를 쓰지 않는다면 이 단계는 건너뛰세요.

4. CSS Preset Import

앱 진입점에서 Preset CSS를 import합니다. 필수 단계입니다.

앱 진입점 (_app.tsx, main.tsx, layout.tsx 등)
// Featuring 테마
import '@featuring-corp/components/preset/featuring';

// 또는 DataEffect 테마
import '@featuring-corp/components/preset/dataEffect';

Preset에 포함된 것

내용설명
@layer ft-reset브라우저 기본 스타일 초기화
@layer ft-normalize브라우저 간 렌더링 일관성
@layer ft-components컴포넌트 CSS 레이어
@layer ft-utilities$css prop 등 atomic CSS 유틸리티 레이어
브랜드 토큰Featuring(#5e51ff, primary-60) 또는 DataEffect(#0065ff, primary-60) CSS 변수

CSS Cascade Layers

Preset은 CSS Cascade Layers를 사용합니다.

ft-reset < ft-normalize < ft-components < ft-utilities < (unlayered — 소비자 CSS)

소비자 CSS는 레이어에 속하지 않으므로 항상 디자인 시스템 스타일보다 우선합니다. !important 없이 오버라이드하세요.

개별 Import (고급)

Preset 대신 개별 CSS를 직접 import할 수도 있습니다. Tailwind 등 자체 reset을 쓰는 프로젝트에 유용합니다.

import '@featuring-corp/design-tokens/style/reset.css';
import '@featuring-corp/design-tokens/style/normalize.css';
import '@featuring-corp/design-tokens/style/featuring.css';

개별 import 시 CSS Layer 순서가 자동 설정되지 않습니다. 특별한 이유가 없다면 Preset을 쓰세요.

5. Portal 스태킹 설정

Tooltip, Modal 등 Portal 기반 컴포넌트는 document.body에 렌더링됩니다. 앱 콘텐츠보다 항상 위에 표시되도록 앱 루트에 isolation: isolate를 추가하세요.

Vite (index.css)
#root {
  isolation: isolate;
}
Next.js Pages Router (globals.css)
#__next {
  isolation: isolate;
}
Next.js App Router (globals.css)
/* layout.tsx에서 <div id="app-root">로 감싼 경우 */
#app-root {
  isolation: isolate;
}

원리: isolation: isolate는 앱 루트를 하나의 stacking context로 만듭니다. 내부의 z-index 값은 그 안에서만 유효하고, Portal은 바깥에 렌더링되므로 자연스럽게 위에 표시됩니다.

6. 사용 시작

레이아웃 컴포넌트

import { Box, HStack, VStack, Typo } from '@featuring-corp/components';

function Card({ title, description }: { title: string; description: string }) {
  return (
    <VStack $css={{
      padding: '$spacing-400',
      borderRadius: '$radius-200',
      bgColor: '$background-1',
      borderWidth: '1px',
      borderStyle: 'solid',
      borderColor: '$border-default',
      gap: '$spacing-200',
    }}>
      <Typo variant="$heading-5" render={<h3 />}>{title}</Typo>
      <Typo variant="$body-2" $css={{ color: '$text-2' }}>{description}</Typo>
    </VStack>
  );
}

Button 컴포넌트

import { Button, IconButton } from '@featuring-corp/components';
import { IconSearchOutline, IconAddOutline } from '@featuring-corp/icons';

// 텍스트 버튼
<Button.Root variant="primary" size="md">
  <Button.Text>저장</Button.Text>
</Button.Root>

// 아이콘 + 텍스트 버튼
<Button.Root variant="secondary" size="md">
  <Button.Icon><IconSearchOutline /></Button.Icon>
  <Button.Text>검색</Button.Text>
</Button.Root>

// 아이콘 전용 버튼
<IconButton variant="tertiary" size="md">
  <IconAddOutline />
</IconButton>

Core 컴포넌트

import { CoreTextInput, CoreSelect, CoreTag } from '@featuring-corp/components';

<CoreTextInput
  label="이메일"
  placeholder="email@example.com"
  size="md"
  status="none"
  helperText="회사 이메일을 입력하세요"
/>

<CoreSelect label="역할" size="md" placeholderText="선택하세요">
  <CoreSelect.Item value="admin">관리자</CoreSelect.Item>
  <CoreSelect.Item value="member">멤버</CoreSelect.Item>
</CoreSelect>

<CoreTag tagType="primary" size="md" text="Active" />

아이콘

import { IconHomeFilled, IconSearchOutline, IconSettingsOutline } from '@featuring-corp/icons';

<IconHomeFilled size="$icon-xl" />
<IconSearchOutline size="$icon-lg" fill="$gray-60" />
<IconSettingsOutline size="$icon-md" />

시스템 아이콘은 currentColor를 사용하므로 부모의 color 속성을 상속합니다.

차트

import {
  BarChart,
  Bar,
  XAxis,
  YAxis,
  CartesianGrid,
  ChartTooltip,
  ResponsiveContainer,
} from '@featuring-corp/charts';

const data = [
  { month: '1월', revenue: 4200, expense: 2400 },
  { month: '2월', revenue: 3800, expense: 1398 },
  { month: '3월', revenue: 5200, expense: 4800 },
];

<ResponsiveContainer width="100%" height={280}>
  <BarChart data={data}>
    <CartesianGrid />
    <XAxis dataKey="month" />
    <YAxis />
    <Bar dataKey="revenue" fill="$primary-50" />
    <Bar dataKey="expense" fill="$gray-50" />
    <ChartTooltip />
  </BarChart>
</ResponsiveContainer>

fill, stroke$primary-50 같은 토큰을 그대로 전달하면 CSS 변수로 자동 해석됩니다.

디자인 토큰 직접 사용

/* CSS에서 직접 사용 */
.my-element {
  background-color: var(--semantic-color-background-1);
  color: var(--semantic-color-text-1);
  padding: var(--global-spacing-400);
  border-radius: var(--global-radius-200);
  box-shadow: var(--global-elevation-4);
}
// JavaScript에서 사용
import { global, semantic } from '@featuring-corp/design-tokens';

const spacing = global.spacing[400]; // '1rem'
const color = global.colors.red[50]; // '#e97259'

프레임워크별 설정

다음 단계