Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 180 additions & 0 deletions apps/web/MIGRATION_STATUS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
# PandaCSS → Tailwind CSS 마이그레이션 진행 상황

**마지막 업데이트**: 2026-01-14

## 진행률 요약

- **시작 시점**: 162개 파일 (PandaCSS 임포트)
- **현재 남은 파일**: 0개 파일
- **완료율**: **100%** ✅

---

## 완료된 섹션

### ✅ Landing 섹션 (3개 파일 완료)

| 파일 | 상태 |
| ---------------------------------------------------------------------- | ------- |
| `src/app/[locale]/landing/MainSection/MainSection.tsx` | ✅ 완료 |
| `src/app/[locale]/landing/ChoosePetSection/ChoosePetSection.tsx` | ✅ 완료 |
| `src/app/[locale]/landing/AvailablePetSection/AvailablePetSection.tsx` | ✅ 완료 |

### ✅ Components 섹션 (4개 파일 완료)

| 파일 | 상태 |
| --------------------------------------------------- | ------- |
| `src/components/AnimalCard/AnimalCard.tsx` | ✅ 완료 |
| `src/components/SortSelect/SortDirectionSelect.tsx` | ✅ 완료 |
| `src/components/SortSelect/OrderTypeSelect.tsx` | ✅ 완료 |
| `src/components/MediaQuery/MediaQuery.tsx` | ✅ 완료 |

### ✅ Guild 페이지 (7개 파일 완료)

| 파일 | 상태 |
| --------------------------------------------------------------------- | ------- |
| `src/app/[locale]/guild/_components/SortSelect.tsx` | ✅ 완료 |
| `src/app/[locale]/guild/_components/GuildPetSelectDialog.tsx` | ✅ 완료 |
| `src/app/[locale]/guild/(subpage)/detail/[id]/page.tsx` | ✅ 완료 |
| `src/app/[locale]/guild/(subpage)/create/GuildCreate.tsx` | ✅ 완료 |
| `src/app/[locale]/guild/(subpage)/[id]/setting/member/MemberCard.tsx` | ✅ 완료 |
| `src/app/[locale]/guild/(subpage)/[id]/MoreMenu.tsx` | ✅ 완료 |
| `src/app/[locale]/guild/(subpage)/[id]/CopyGuildImgButton.tsx` | ✅ 완료 |

### ✅ Dev 페이지 및 Laboratory (6개 파일 완료)

| 파일 | 상태 | 비고 |
| -------------------------------------------------------- | ------- | ---------------- |
| `src/app/[locale]/dev/page.tsx` | ✅ 완료 | dev 페이지 |
| `src/app/[locale]/dev/Client.tsx` | ✅ 완료 | dev 클라이언트 |
| `src/app/[locale]/dev/token/token.style.ts` | ✅ 완료 | 토큰 스타일 |
| `src/app/[locale]/dev/token/page.tsx` | ✅ 완료 | 토큰 페이지 |
| `src/app/[locale]/dev/component/page.tsx` | ✅ 완료 | 컴포넌트 페이지 |
| `src/app/[locale]/laboratory/_component/AlertDialog.tsx` | ✅ 완료 | Alert 다이얼로그 |

---

## 완료된 작업

### 백그라운드 에이전트 작업 결과

| 작업 ID | 내용 | 상태 |
| ------- | ---------------------------- | ------------------ |
| ab99674 | Landing styles (6개 파일) | ✅ 완료 |
| a988b66 | Landing components | ✅ 완료 |
| abdd937 | Guild page files (8개 파일) | ✅ 완료 |
| aeebca2 | Event page files (12개 파일) | ✅ 완료 |
| a6a13a4 | Mypage files | ⚠️ Rate limit 중단 |
| a49d6dc | Ranking section | ⚠️ Rate limit 중단 |
| af69c09 | Quiz game files | ⚠️ Rate limit 중단 |
| a8ee052 | Guild subpage files | ⚠️ Rate limit 중단 |
| a1f8080 | Component files | ⚠️ Rate limit 중단 |

### 수동 마이그레이션 완료 파일

- `src/app/[locale]/error.tsx`
- `src/app/[locale]/auth/page.tsx`
- `src/app/[locale]/auth/signOut/page.tsx`
- `src/components/Pagination/PaginationServer.tsx`
- `src/components/Global/useDialog.tsx`
- `src/components/Global/FeedbackForm.tsx` (읽기만 완료)

---

## 마이그레이션 패턴 참조

### 임포트 변환

```typescript
// Before
import { css, cx } from '_panda/css';
import { flex, center, grid } from '_panda/patterns';
import { Flex, Box } from '_panda/jsx';
import { Button, Dialog } from '@gitanimals/ui-panda';

// After
import { cn, Button, Dialog } from '@gitanimals/ui-tailwind';
```

### 스타일 변환 예시

```typescript
// Before (PandaCSS)
const style = css({
display: 'flex',
alignItems: 'center',
gap: '8px',
textStyle: 'glyph16.regular',
color: 'white.white_75',
_mobile: { padding: '8px' },
});

// After (Tailwind)
const style = cn('flex items-center gap-2', 'font-product text-glyph-16 text-white/75', 'max-mobile:p-2');
```

### 색상 토큰 매핑

| PandaCSS | Tailwind |
| ---------------- | ---------------- |
| `brand.canary` | `brand-canary` |
| `gray.gray_150` | `gray-150` |
| `white.white_75` | `white-white/75` |
| `black.black_50` | `black/50` |

### 반응형 프리픽스

| PandaCSS | Tailwind |
| -------------- | ------------- |
| `_mobile: {}` | `max-mobile:` |
| `_desktop: {}` | `desktop:` |

---

## ui-tailwind 구조적 개선 (2026-01-14)

### 문제점

- `@gitanimals/ui-tailwind`의 index.ts에 'use client' 배너가 있어서 서버 컴포넌트에서 `cn` 유틸리티 사용 시 빌드 에러 발생

### 해결책

1. **tsup 설정 분리**:

- `index.ts`, `components/index.ts`: 'use client' 배너 포함 (클라이언트 컴포넌트용)
- `utils/index.ts`: 'use client' 배너 없음 (서버 컴포넌트용)

2. **새로운 import 패턴**:

```typescript
// 클라이언트 컴포넌트에서 (기존과 동일)
import { cn, Button, Dialog } from '@gitanimals/ui-tailwind';

// 서버 컴포넌트에서 cn만 필요한 경우
import { cn } from '@gitanimals/ui-tailwind/utils';
```

3. **추가된 컴포넌트** (ui-tailwind):
- `Banner`, `BannerSkeleton`, `BannerSkeletonList`
- `LevelBanner`
- `BannerPetSelectMedium`
- `CommonDialog`
- `SearchBar`

### 수정된 서버 컴포넌트 파일 (70+ 파일)

- 모든 서버 컴포넌트에서 `cn` import를 `/utils` 경로로 변경
- 누락된 'use client' 지시문 추가

---

## 최종 단계 (마이그레이션 완료 후)

- [x] 모든 파일 마이그레이션 완료
- [x] `pnpm build:web` 빌드 성공 확인 ✅
- [ ] 시각적 회귀 테스트
- [ ] PandaCSS 의존성 제거
- `panda.config.ts` 삭제
- `styled-system/` 디렉토리 삭제
- `package.json`에서 PandaCSS 관련 의존성 제거
- `tsconfig.json`에서 `_panda` 경로 제거
4 changes: 4 additions & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
},
"dependencies": {
"@air/react-drag-to-select": "^5.0.11",
"@gitanimals/ui-tailwind": "workspace:*",
"@egjs/flicking-plugins": "^4.7.1",
"@egjs/react-flicking": "^4.11.3",
"@gitanimals/api": "workspace:*",
Expand Down Expand Up @@ -61,6 +62,9 @@
},
"devDependencies": {
"@chromatic-com/storybook": "^1.3.3",
"autoprefixer": "^10.4.21",
"postcss": "^8.5.6",
"tailwindcss": "^3.4.17",
"@gitanimals/eslint-config": "workspace:*",
"@gitanimals/typescript-config": "workspace:*",
"@gitanimals/util-common": "workspace:*",
Expand Down
9 changes: 9 additions & 0 deletions apps/web/postcss.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

export default config;
19 changes: 5 additions & 14 deletions apps/web/src/app/[locale]/auth/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';

import { useEffect } from 'react';
import { center } from '_panda/patterns';
import { cn } from '@gitanimals/ui-tailwind';
import { setRequestInterceptor, setResponseInterceptor } from '@gitanimals/api';
import { setRenderRequestInterceptor, setRenderResponseInterceptor } from '@gitanimals/api/src/_instance';

Expand Down Expand Up @@ -42,16 +42,7 @@ function JWTPage({

export default JWTPage;

const loadingContainerStyle = center({
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(255, 255, 255, 0.8)',
zIndex: 'loading',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
fontSize: '36px',
});
const loadingContainerStyle = cn(
'fixed inset-0 bg-white/80 z-loading',
'flex items-center justify-center text-[36px]'
);
17 changes: 2 additions & 15 deletions apps/web/src/app/[locale]/auth/signOut/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import { useEffect } from 'react';
import { signOut } from 'next-auth/react';
import { css } from '_panda/css';
import { Loader2 } from 'lucide-react';

export default function SignOutPage() {
Expand All @@ -11,21 +10,9 @@ export default function SignOutPage() {
}, []);

return (
<div
className={css({
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100vh',
})}
>
<div className="flex items-center justify-center h-screen">
{/* TODO: loading 애니메이션 추가 */}
<Loader2
className={css({
width: '100px',
height: '100px',
})}
/>
<Loader2 className="w-[100px] h-[100px]" />
</div>
);
}
19 changes: 4 additions & 15 deletions apps/web/src/app/[locale]/dev/Client.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
'use client';

import { Box } from '_panda/jsx';
import { flex } from '_panda/patterns';
import { Button } from '@gitanimals/ui-panda';
import { Button } from '@gitanimals/ui-tailwind';

import { Link } from '@/i18n/routing';
import { useDevMode } from '@/lib/devtools/devtools';
Expand All @@ -14,9 +12,9 @@ function DevClient() {
const { data: session, status } = useClientSession();

return (
<Box>
<div>
<li>devMode: {isDevMode}</li>
<ul className={listStyle}>
<ul className="mt-6 flex flex-col gap-6 bg-white w-[90%] font-sans">
<li>client session status : {status}</li>
<li>
client session user : <br /> {session?.user && JSON.stringify(session.user)}
Expand All @@ -38,21 +36,12 @@ function DevClient() {
</Link>
</li>
</ul>
</Box>
</div>
);
}

export default DevClient;

const listStyle = flex({
marginTop: '24px',
gap: '24px',
flexDir: 'column',
bg: 'white',
w: '90%',
fontFamily: 'sans-serif',
});

function GoogleSheet() {
const handleSubmit = async () => {
await sendLog({ test: 'test data 입니다 ' });
Expand Down
18 changes: 3 additions & 15 deletions apps/web/src/app/[locale]/dev/component/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
'use client';

import { css } from '_panda/css';
import { Select } from '@gitanimals/ui-panda';
import { Select } from '@gitanimals/ui-tailwind';

function DevComponentPage() {
return (
<div className={containerStyle}>
<div className="bg-[#2C2929] p-6 h-screen flex flex-col items-start gap-4">
<Select>
<Select.Trigger w="180px">
<Select.Trigger className="w-[180px]">
<Select.Value placeholder="Theme" />
</Select.Trigger>
<Select.Content>
Expand All @@ -21,14 +20,3 @@ function DevComponentPage() {
}

export default DevComponentPage;

const containerStyle = css({
backgroundColor: '#2C2929',
padding: '24px',
height: '100vh',

display: 'flex',
flexDirection: 'column',
alignItems: 'flex-start',
gap: '16px',
});
20 changes: 8 additions & 12 deletions apps/web/src/app/[locale]/dev/page.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { css } from '_panda/css';
import { Box } from '_panda/jsx';
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@gitanimals/ui-panda';
'use client';

import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@gitanimals/ui-tailwind';

import DevModePage from '@/components/DevMode/DevModePage';
import GNB from '@/components/GNB/GNB';

import DevClient from './Client';

async function DevPage() {
function DevPage() {
return (
<DevModePage>
<Box p={32}>
<div className="p-8">
<GNB />
<h1>server</h1>
<hr className={dividerStyle} />
<hr className="my-6" />
<h1>client</h1>
<DevClient />
<Accordion type="single" collapsible w="full">
<Accordion type="single" collapsible className="w-full">
<AccordionItem value="item-1">
<AccordionTrigger>Is it accessible?</AccordionTrigger>
<AccordionContent>Yes. It adheres to the WAI-ARIA design pattern.</AccordionContent>
Expand All @@ -34,13 +34,9 @@ async function DevPage() {
</AccordionContent>
</AccordionItem>
</Accordion>
</Box>
</div>
</DevModePage>
);
}

export default DevPage;

const dividerStyle = css({
margin: '24px 0',
});
Loading
Loading