Featuring Design System

Installation

Featuring Design System 설치 및 기본 설정 방법

시스템 요구사항

  • React: 18 이상
  • Node.js: 18 이상
  • 패키지 매니저: npm, yarn, pnpm 모두 지원

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

3. Peer Dependencies 설치

일부 컴포넌트(CoreDropdown, CoreModal, CoreSelectPrim, CoreMultiSelectPrim)는 커스텀 스크롤바를 위해 OverlayScrollbars를 사용합니다. 해당 컴포넌트를 사용하는 경우 별도 설치가 필요합니다.

npm install overlayscrollbars overlayscrollbars-react

위 컴포넌트를 사용하지 않는다면 이 단계를 건너뛸 수 있습니다.

4. CSS Preset Import

앱 진입점에서 Preset CSS를 import합니다. 이 단계는 필수입니다. Preset 하나로 CSS Reset, Normalize, 브랜드 토큰, CSS Layer 순서가 모두 설정됩니다.

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

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

Preset이 포함하는 것

내용설명
@layer ft.reset브라우저 기본 스타일 초기화 (design-tokens의 reset.css)
@layer ft.normalize브라우저 간 렌더링 일관성 (design-tokens의 normalize.css)
@layer ft.components컴포넌트 CSS가 속하는 레이어 (자동 적용)
@layer ft.utilities$css prop 등 atomic CSS 유틸리티 레이어 (rainbow-sprinkles)
브랜드 토큰Featuring(#5e51ff) 또는 DataEffect(#0065ff) 테마의 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을 사용하는 프로젝트에 유용합니다.

// design-tokens에서 개별 import
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 순서가 자동으로 설정되지 않으므로, 소비자 CSS 오버라이드가 보장되지 않습니다. 특별한 이유가 없다면 Preset 사용을 권장합니다.

5. Portal 스태킹 설정

Tooltip, Modal 등 Portal 기반 컴포넌트는 document.body에 렌더링됩니다. 앱 콘텐츠보다 항상 위에 표시되도록 앱 루트 요소에 CSS 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;
}

이 설정으로 앱 내부의 z-index 값들이 Portal과 경쟁하지 않게 됩니다. 별도의 z-index 관리가 필요 없습니다.

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

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, IconPlusOutline } 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">
  <IconPlusOutline />
</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="24px" />
<IconSearchOutline size="20px" fill="var(--global-colors-gray-60)" />
<IconSettingsOutline size="16px" />

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

디자인 토큰 직접 사용

/* 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'

프레임워크별 설정

프레임워크에 따라 추가 설정이 필요할 수 있습니다.

다음 단계