Guides

Styling Integration

PAI Design를 앱의 theme, CSS, Tailwind 흐름에 연결하는 방법을 소개해요.

이 문서는 Getting started에서 첫 렌더를 마친 뒤, PAI Design을 실제 앱 스타일 구조에 어떻게 연결하면 좋은지 설명해요. 설치 순서보다 테마 연결 기준, CSS variable 사용 방식, Tailwind와의 연결 방법이 궁금할 때 읽으면 좋아요.

Overview

PAI Design를 앱에 연결할 때 핵심 기준은 아래 4가지예요.

항목무엇을 하나요기본 기준
@pai-design/react/styles.css토큰과 레시피 스타일을 한 번에 불러와요앱 진입점에서 한 번만 import해요.
.dark / .light class테마 토큰을 light / dark 모드에 맞게 바꿔요ThemeProvider 대신 class contract를 사용해요.
앱 루트 font family컴포넌트가 상속할 기본 font를 정해요컴포넌트 레시피는 inherit를 사용해 앱 font를 따라가요.
@pai-design/tokenscustom UI와 layout에 토큰을 직접 연결해요공개 컴포넌트가 없는 제품 전용 UI에서 사용해요.

스타일 한 번만 불러오기

@pai-design/react를 사용한다면 앱 진입점에서 styles.css를 한 번만 import하면 돼요.

import "@pai-design/react/styles.css";

여기에는 토큰 CSS variable과 레시피 스타일이 함께 들어 있어요. @pai-design/tokens/styles.css@pai-design/recipes/styles.css를 따로 나눠 불러올 필요는 없어요.

Theme 연결하기

PAI Design은 ThemeProvider를 제공하지 않아요. 대신 .dark.light class를 기준으로 토큰 값을 바꾸는 contract를 제공해요.

import "@pai-design/react/styles.css";
import { Button } from "@pai-design/react";

export function App() {
  return (
    <div className="dark">
      <Button>저장하기</Button>
    </div>
  );
}

보통은 html이나 앱 루트 컨테이너에 .dark를 두고, 화면 일부만 다른 theme로 보여주고 싶다면 특정 wrapper에만 .dark 또는 .light를 둘 수 있어요.

테마 상태를 어디에 저장하고 어떻게 토글할지는 앱이 맡아요. next-themes 같은 도구를 사용해 class만 일관되게 붙여주면 충분해요.

Font 연결하기

PAI Design 컴포넌트는 앱 font family를 상속해요. 시스템이 강제로 폰트를 덮어쓰지 않기 때문에, 제품 전체 font를 앱 루트에서 정하면 컴포넌트도 같은 기준을 따라가요.

공용 sans stack을 그대로 쓰고 싶다면 앱 루트에 아래처럼 둘 수 있어요.

html {
  font-family: var(--pai-font-family-sans);
}

별도 브랜드 폰트를 쓰고 있다면 앱 루트에서 그 font를 지정하면 돼요. 컴포넌트 레시피는 font-family: inherit를 사용하므로 추가 설정 없이 따라가요.

Token을 직접 사용하는 방법

공개 컴포넌트가 없는 제품 전용 UI나 layout shell은 @pai-design/tokens를 사용해 연결할 수 있어요.

import { tokenVars } from "@pai-design/tokens";

const panelStyle = {
  background: tokenVars["color.bg.surface"],
  maxWidth: tokenVars["size.surface.md"],
  padding: tokenVars["space.4"],
};

plain CSS에서는 생성된 CSS variable을 직접 사용할 수 있어요.

.panel {
  background: var(--pai-color-bg-surface);
  max-width: var(--pai-size-surface-md);
  padding: var(--pai-space-4);
}

역할이 이미 정해진 값이라면 raw px나 hex 값보다 semantic token을 먼저 사용해요.

Tailwind와 같이 쓸 때

PAI Design 자체는 Tailwind를 요구하지 않아요. plain CSS, CSS Modules, CSS-in-JS처럼 앱이 이미 쓰는 방식을 그대로 선택해도 괜찮아요.

앱이 Tailwind를 사용한다면, layout과 구조는 Tailwind utility로 두고 시각 값은 token CSS variable로 연결하는 방식이 가장 자연스러워요.

export function Panel({ children }: { children: React.ReactNode }) {
  return (
    <section className="bg-[var(--pai-color-bg-surface)] p-[var(--pai-space-4)]">
      {children}
    </section>
  );
}

이미 Button, Dialog처럼 공개 컴포넌트가 있는 경우에는 utility로 컴포넌트 핵심 위계를 다시 덮어쓰기보다, 먼저 제공된 public prop과 composition을 사용해요. Tailwind는 주변 layout과 page-specific composition에 쓰고, 컴포넌트 의미 자체는 시스템 contract를 따라가는 쪽이 더 안정적이에요.

무엇을 어디까지 시스템에 맡길지

  • 반복되는 공통 UI는 @pai-design/react 컴포넌트를 먼저 사용해요.
  • 제품 화면의 layout, section spacing, custom wrapper는 @pai-design/tokens로 연결해요.
  • theme 상태 저장과 토글은 앱이 맡고, 시스템은 class contract만 제공해요.
  • 이미 컴포넌트가 가진 의미를 product utility로 다시 정의하지 않아요.

이 경계가 분명할수록 시스템은 작고 안정적으로 유지되고, 앱은 필요한 부분만 유연하게 확장할 수 있어요.

다음에 읽으면 좋은 문서

  • token 구조와 layer 흐름은 Design Token에서 확인해요.
  • 첫 import와 첫 렌더 흐름은 Getting started에서 확인해요.
  • 색상과 spacing, typography 기준은 Foundation 문서에서 이어서 볼 수 있어요.

On this page