Skip to content

[Feat] WTH-163-dialog alert 모달 구현#7

Open
dalzzy wants to merge 6 commits intodevelopfrom
WTH-163-dialog-alert-모달-구현

Hidden character warning

The head ref may contain hidden characters: "WTH-163-dialog-alert-\ubaa8\ub2ec-\uad6c\ud604"
Open

[Feat] WTH-163-dialog alert 모달 구현#7
dalzzy wants to merge 6 commits intodevelopfrom
WTH-163-dialog-alert-모달-구현

Conversation

@dalzzy
Copy link
Collaborator

@dalzzy dalzzy commented Feb 25, 2026

✅ PR 유형

어떤 변경 사항이 있었나요?

  • 새로운 기능 추가
  • 버그 수정
  • 코드에 영향을 주지 않는 변경사항(오타 수정, 탭 사이즈 변경, 변수명 변경)
  • 코드 리팩토링
  • 주석 추가 및 수정
  • 문서 수정
  • 빌드 부분 혹은 패키지 매니저 수정
  • 파일 혹은 폴더명 수정
  • 파일 혹은 폴더 삭제

📌 관련 이슈번호


✅ Key Changes

  • alert dialog 모달 구현

📸 스크린샷 or 실행영상

2026-02-26.2.01.09.mov

🎸 기타 사항 or 추가 코멘트

유진님이 전에 작업하신거까지 올라와버렸는데 components/ui 안에 있는 파일들이랑 svg 파일들만 봐주시면 될 것 같습니다!!

피그마에 나와 있는 디자인대로 status별 기본 텍스트로 설정해두었습니다!

Default(기본 텍스트 사용 시)

<AlertDialog trigger={<Button>저장</Button>}>
  <AlertDialogAction>확인</AlertDialogAction>
  <AlertDialogCancel>취소</AlertDialogCancel>
</AlertDialog>

Danger(기본 텍스트 사용 시)

<AlertDialog status="danger" trigger={<Button>삭제</Button>}>
  <AlertDialogAction>삭제</AlertDialogAction>
  <AlertDialogCancel>취소</AlertDialogCancel>
</AlertDialog>

텍스트 오버라이드

<AlertDialog
  status="danger"
  title="이 댓글을 삭제하시겠어요?"
  description="삭제된 댓글은 복구할 수 없습니다."
  trigger={<Button>삭제</Button>}
>
  <AlertDialogAction>삭제</AlertDialogAction>
  <AlertDialogCancel>취소</AlertDialogCancel>
</AlertDialog>

구조를 완전히 커스텀해야 하는 경우
trigger prop 없이 사용하면 기존 compound 패턴 그대로 동작합니다.

<AlertDialog status="danger">
  <AlertDialogTrigger asChild>
    <Button>삭제</Button>
  </AlertDialogTrigger>
  <AlertDialogContent>
    <AlertDialogHeader>
      <AlertDialogTitle>커스텀 타이틀</AlertDialogTitle>
      <AlertDialogDescription>커스텀 설명</AlertDialogDescription>
    </AlertDialogHeader>
    <AlertDialogFooter>
      <AlertDialogAction>확인</AlertDialogAction>
      <AlertDialogCancel>취소</AlertDialogCancel>
    </AlertDialogFooter>
  </AlertDialogContent>
</AlertDialog>

@dalzzy dalzzy self-assigned this Feb 25, 2026
@dalzzy dalzzy added ✨ Feature 기능 개발 🎨 Html&css 마크업 & 스타일링 labels Feb 25, 2026
@github-actions
Copy link

PR 검증 결과

TypeScript: 실패
ESLint: 통과
Prettier: 실패
Build: 통과

⚠️ 일부 검증에 실패했습니다. 확인 후 수정해주세요.

@coderabbitai
Copy link

coderabbitai bot commented Feb 25, 2026

📝 Walkthrough

Walkthrough

프로젝트에 Figma-to-component 및 PR 자동화 에이전트 문서가 추가되었고, CI/CD 워크플로우(GitHub Actions 및 Amplify)가 구성되었습니다. AlertDialog 컴포넌트에 상태 기반 변형(default/danger)이 추가되었으며, Button에 danger 변형이 추가되었습니다.

Changes

Cohort / File(s) Summary
Agent Documentation
.claude/agents/figma-to-component.md, .claude/agents/pr-writer.md
새로운 AI 에이전트 가이드 문서 추가: Figma 디자인을 React 컴포넌트로 변환하는 워크플로우와 PR 작성 자동화 프로세스를 정의합니다.
CI/CD 파이프라인
.github/workflows/ci.yml, amplify.yml
GitHub Actions CI 워크플로우 및 AWS Amplify 빌드 설정 추가. 타입스크립트 체크, ESLint, Prettier 검증 및 빌드 실행, PR 검증 결과 자동 댓글 기능을 포함합니다.
프로젝트 설정
CLAUDE.md, package.json
온보딩 문서를 간소화하고 npm 스크립트 추가(typecheck, format:check).
UI 컴포넌트 개선
src/components/ui/Button.tsx, src/components/ui/alert-dialog.tsx, src/components/ui/index.ts, src/app/globals.css
Button에 danger 변형 추가, AlertDialog에 상태 기반 변형(default/danger) 및 trigger/title/description props 추가, 새로운 dialog shadow 토큰 정의, 컴포넌트 내보내기 정리.
컴포넌트 사용 예제
src/app/(public)/(landing)/page.tsx
AlertDialog 상태 변형과 새로운 의미론적 레이블 적용(기본/삭제 경고 대화상자).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~35 minutes

Possibly related PRs

Suggested reviewers

  • woneeeee
  • nabbang6

Poem

🐰 Figma에서 컴포넌트로, 몇 단계만에!
위험한 빨강이 담겨있고, 대화상자는 똑똑해졌네요 🎨
CI 자동화로 품질도 쌔악, 마크다운 가이드는 쏘옥—
Weeth 디자인 시스템이 더욱 견고해지고 있어요! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description check ✅ Passed PR 설명이 템플릿 구조를 따르고 있으며, PR 유형을 명확히 선택했고, Key Changes와 스크린샷을 포함했습니다.
Title check ✅ Passed PR 제목이 변경 사항의 핵심인 alert dialog 모달 구현을 명확하게 설명하고 있으며, 실제 변경 내용과 일치합니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch WTH-163-dialog-alert-모달-구현

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (5)
CLAUDE.md (2)

13-18: 코드 블록에 언어 식별자를 추가하세요.

정적 분석 도구(markdownlint MD040)에서 경고가 발생했습니다. 코드 블록에 언어를 지정하면 린트 경고가 해소되고 구문 강조도 적용됩니다.

💡 제안
-```
+```text
 src/
   app/globals.css        # 디자인 토큰 (CSS variables, `@utility`)
   components/ui/         # 재사용 UI 컴포넌트, index.ts에서 re-export
   lib/cn.ts              # className 병합 유틸
 ```
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CLAUDE.md` around lines 13 - 18, Add a language identifier to the fenced code
block that currently contains the "src/ … lib/cn.ts" tree (the block starting
with ``` and the "src/" line) to satisfy markdownlint MD040 and enable syntax
highlighting; update the opening fence to include a language token such as
```text (or ```bash) so the block becomes ```text followed by the existing lines
and the closing ```.

51-53: Git 컨벤션 코드 블록에도 언어 식별자를 추가하세요.

마찬가지로 markdownlint MD040 경고가 발생합니다.

💡 제안
-```
+```text
 feat / fix / style / refactor / ci / chore
 ```
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CLAUDE.md` around lines 51 - 53, The fenced code block that currently reads
``` feat / fix / style / refactor / ci / chore ``` should include a language
identifier to satisfy markdownlint MD040; update the block delimiter to include
an explicit language (for example change the opening fence to ```text) so the
block becomes ```text … ```; locate the fenced block containing "feat / fix /
style / refactor / ci / chore" in CLAUDE.md and add the language tag.
.github/workflows/ci.yml (1)

21-21: pnpm 버전을 고정하세요.

amplify.yml과 동일하게 version: latest 대신 특정 버전을 지정하면 CI 환경의 재현성이 향상됩니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/ci.yml at line 21, 현재 CI 워크플로의 pnpm 설정에서 "version:
latest"로 되어 있어 재현성이 떨어집니다; .github/workflows/ci.yml에서 "version: latest"를 특정 버전
문자열(예: amplify.yml에 사용된 동일한 pnpm 버전)으로 고정하도록 변경하고, 해당 키("version" under pnpm
setup) 값을 amplify.yml의 버전과 일치시키세요.
amplify.yml (1)

7-7: pnpm@latest 대신 특정 버전을 고정하는 것을 권장합니다.

pnpm@latest는 빌드 시점에 따라 다른 버전이 설치될 수 있어 재현 가능한 빌드를 보장하기 어렵습니다. package.jsonpackageManager 필드에 버전을 명시하고, 여기서는 해당 버전을 참조하거나 고정 버전(예: pnpm@9.x.x)을 사용하세요.

💡 제안
-        - corepack prepare pnpm@latest --activate
+        - corepack prepare pnpm@9.15.0 --activate

또는 package.json"packageManager": "pnpm@9.15.0" 필드를 추가하면 corepack prepare 없이도 corepack enable만으로 올바른 버전이 활성화됩니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@amplify.yml` at line 7, Replace the unstable "corepack prepare pnpm@latest
--activate" invocation with a pinned pnpm version or rely on package.json's
packageManager field: either change the command to "corepack prepare pnpm@9.x.x
--activate" (use the exact desired semver, e.g., 9.15.0) or remove the prepare
call and ensure package.json contains "packageManager": "pnpm@9.15.0" so that
"corepack enable" will activate the correct pnpm; update the line containing
corepack prepare pnpm@latest --activate accordingly.
.claude/agents/figma-to-component.md (1)

7-9: 에이전트 가이드에 프론트엔드 스택 제약을 명시해 주세요.

이 문서는 코드 생성 기준서 역할이라 Step 3 근처에 React 19 + Next.js 16(App Router) + Tailwind v4를 명시해 두면 결과 일관성이 더 좋아집니다.

As per coding guidelines **/*.{ts,tsx}: Use React 19 + TypeScript with Next.js 16 (App Router) for all frontend code; Use Tailwind CSS v4 and class-variance-authority (cva) for styling.

Also applies to: 33-63

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/agents/figma-to-component.md around lines 7 - 9, Add explicit
frontend stack constraints to the Figma-to-component agent guide: insert a
short, clear statement near Step 3 that all generated frontend code must target
"React 19 + Next.js 16 (App Router) + TypeScript" and use "Tailwind CSS v4 +
class-variance-authority (cva)" for styling, and also update the
coding-guidelines section referenced by the glob pattern "**/*.{ts,tsx}" so it
explicitly requires React 19, Next.js 16 (App Router), TypeScript, Tailwind v4
and cva; locate the Step 3 heading and the coding-guidelines block in
.claude/agents/figma-to-component.md (and the related paragraphs around lines
33-63) and add that exact stack constraint text to ensure consistency across
generated components.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/agents/figma-to-component.md:
- Around line 1-70: The CI failure is due to Prettier formatting errors in the
Markdown file named figma-to-component (frontmatter and content). Reformat the
file with your project's Prettier configuration (run prettier --write on
.claude/agents/figma-to-component.md or use your editor's format command),
ensuring the YAML frontmatter, code blocks, and inline code are correctly
indented and wrapped; then stage and commit the reformatted file so the Prettier
check passes.

In @.github/workflows/ci.yml:
- Around line 32-50: Add a final "verdict" step that runs unconditionally (if:
always()) after the PR comment step and inspects the outcomes of the earlier
steps by their IDs (typescript, eslint, prettier, build); if any of
steps.typescript.outcome, steps.eslint.outcome, steps.prettier.outcome, or
steps.build.outcome is not "success", exit non‑zero to fail the workflow (give
the step an id like final-verdict and a clear error message). This preserves the
per-step continue-on-error behavior for comment/logging but enforces a blocking
CI failure if any check actually failed.

In `@src/components/ui/alert-dialog.tsx`:
- Around line 55-57: The conditional currently checks only for trigger !==
undefined, which still allows trigger === null to render <AlertDialogTrigger
asChild>{trigger}</AlertDialogTrigger> and cause a runtime error; update the
check to exclude null as well (e.g., use trigger != null or trigger !==
undefined && trigger !== null or Boolean(trigger)) so that AlertDialogTrigger is
only rendered when trigger is a valid non-null value, referencing the trigger
prop and AlertDialogTrigger/asChild usage.
- Around line 13-38: The component currently branches on AlertStatus across
AlertStatus, defaultTexts, and AlertDialogProps; refactor to use cva variants
and VariantProps by replacing the AlertStatus union and scattered defaultTexts
with a cva() call that defines variants (e.g., variant: { default, danger }) and
defaultVariants, update the props interface to extend VariantProps<typeof
yourCva> and React.ComponentProps<typeof AlertDialogPrimitive.Root>, and use the
generated variant classNames/props inside AlertDialogContext and the component
to derive title/description (move defaultTexts into variant defaults or a
mapping keyed by variant) so all status behavior is centralized in the cva
variants configuration.
- Around line 5-11: Replace the direct SVG imports InfoIcon and DeleteIcon with
lucide-react icon components: remove "import InfoIcon from
'@/assets/icons/info.svg'" and "import DeleteIcon from
'@/assets/icons/delete_forever.svg'" and instead import the proper lucide-react
icons (e.g., "import { Info, Trash2 } from 'lucide-react'"). Then update the JSX
usages that render <InfoIcon .../> and <DeleteIcon .../> (the instances
referenced in this file) to use <Info .../> and <Trash2 .../> (preserving
className, size, strokeWidth or other props passed through cn or Button props)
so styling and accessibility remain unchanged.

In `@src/components/ui/Button.tsx`:
- Around line 16-17: In src/components/ui/Button.tsx update the danger variant
string (the 'danger' key in the exported variants) to replace the arbitrary
class bg-[var(--state-error)] with the design-token utility class bg-state-error
so it matches other variants (e.g. bg-button-primary, bg-button-neutral) and
avoids arbitrary values; keep the rest of the class list (text-text-strong
hover/active/disabled classes) unchanged to preserve behavior.

---

Nitpick comments:
In @.claude/agents/figma-to-component.md:
- Around line 7-9: Add explicit frontend stack constraints to the
Figma-to-component agent guide: insert a short, clear statement near Step 3 that
all generated frontend code must target "React 19 + Next.js 16 (App Router) +
TypeScript" and use "Tailwind CSS v4 + class-variance-authority (cva)" for
styling, and also update the coding-guidelines section referenced by the glob
pattern "**/*.{ts,tsx}" so it explicitly requires React 19, Next.js 16 (App
Router), TypeScript, Tailwind v4 and cva; locate the Step 3 heading and the
coding-guidelines block in .claude/agents/figma-to-component.md (and the related
paragraphs around lines 33-63) and add that exact stack constraint text to
ensure consistency across generated components.

In @.github/workflows/ci.yml:
- Line 21: 현재 CI 워크플로의 pnpm 설정에서 "version: latest"로 되어 있어 재현성이 떨어집니다;
.github/workflows/ci.yml에서 "version: latest"를 특정 버전 문자열(예: amplify.yml에 사용된 동일한
pnpm 버전)으로 고정하도록 변경하고, 해당 키("version" under pnpm setup) 값을 amplify.yml의 버전과
일치시키세요.

In `@amplify.yml`:
- Line 7: Replace the unstable "corepack prepare pnpm@latest --activate"
invocation with a pinned pnpm version or rely on package.json's packageManager
field: either change the command to "corepack prepare pnpm@9.x.x --activate"
(use the exact desired semver, e.g., 9.15.0) or remove the prepare call and
ensure package.json contains "packageManager": "pnpm@9.15.0" so that "corepack
enable" will activate the correct pnpm; update the line containing corepack
prepare pnpm@latest --activate accordingly.

In `@CLAUDE.md`:
- Around line 13-18: Add a language identifier to the fenced code block that
currently contains the "src/ … lib/cn.ts" tree (the block starting with ``` and
the "src/" line) to satisfy markdownlint MD040 and enable syntax highlighting;
update the opening fence to include a language token such as ```text (or
```bash) so the block becomes ```text followed by the existing lines and the
closing ```.
- Around line 51-53: The fenced code block that currently reads ``` feat / fix /
style / refactor / ci / chore ``` should include a language identifier to
satisfy markdownlint MD040; update the block delimiter to include an explicit
language (for example change the opening fence to ```text) so the block becomes
```text … ```; locate the fenced block containing "feat / fix / style / refactor
/ ci / chore" in CLAUDE.md and add the language tag.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5207f4d and 487123a.

⛔ Files ignored due to path filters (2)
  • src/assets/icons/delete_forever.svg is excluded by !**/*.svg
  • src/assets/icons/info.svg is excluded by !**/*.svg
📒 Files selected for processing (11)
  • .claude/agents/figma-to-component.md
  • .claude/agents/pr-writer.md
  • .github/workflows/ci.yml
  • CLAUDE.md
  • amplify.yml
  • package.json
  • src/app/(public)/(landing)/page.tsx
  • src/app/globals.css
  • src/components/ui/Button.tsx
  • src/components/ui/alert-dialog.tsx
  • src/components/ui/index.ts

Comment on lines +32 to +50
- name: TypeScript
id: typescript
continue-on-error: true
run: pnpm typecheck

- name: ESLint
id: eslint
continue-on-error: true
run: pnpm lint

- name: Prettier
id: prettier
continue-on-error: true
run: pnpm format:check

- name: Build
id: build
continue-on-error: true
run: pnpm build
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

모든 단계가 continue-on-error: true이므로 CI가 실패를 차단하지 않습니다.

현재 TypeScript, ESLint, Prettier, Build 모든 단계에 continue-on-error: true가 설정되어 있어, 모든 검증이 실패하더라도 워크플로우는 항상 성공으로 표시됩니다. PR 병합을 차단하는 게이트 역할을 하지 못합니다.

워크플로우 마지막에 최종 판정 단계를 추가하세요:

💡 최종 실패 단계 추가 제안
+      - name: Fail if any check failed
+        if: always()
+        run: |
+          if [[ "${{ steps.typescript.outcome }}" == "failure" || \
+                "${{ steps.eslint.outcome }}" == "failure" || \
+                "${{ steps.prettier.outcome }}" == "failure" || \
+                "${{ steps.build.outcome }}" == "failure" ]]; then
+            echo "One or more checks failed"
+            exit 1
+          fi

이 단계를 PR 코멘트 단계 뒤에 추가하면, 코멘트는 항상 작성되면서도 실패 시 워크플로우가 적절히 실패합니다.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: TypeScript
id: typescript
continue-on-error: true
run: pnpm typecheck
- name: ESLint
id: eslint
continue-on-error: true
run: pnpm lint
- name: Prettier
id: prettier
continue-on-error: true
run: pnpm format:check
- name: Build
id: build
continue-on-error: true
run: pnpm build
- name: TypeScript
id: typescript
continue-on-error: true
run: pnpm typecheck
- name: ESLint
id: eslint
continue-on-error: true
run: pnpm lint
- name: Prettier
id: prettier
continue-on-error: true
run: pnpm format:check
- name: Build
id: build
continue-on-error: true
run: pnpm build
- name: Fail if any check failed
if: always()
run: |
if [[ "${{ steps.typescript.outcome }}" == "failure" || \
"${{ steps.eslint.outcome }}" == "failure" || \
"${{ steps.prettier.outcome }}" == "failure" || \
"${{ steps.build.outcome }}" == "failure" ]]; then
echo "One or more checks failed"
exit 1
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/ci.yml around lines 32 - 50, Add a final "verdict" step
that runs unconditionally (if: always()) after the PR comment step and inspects
the outcomes of the earlier steps by their IDs (typescript, eslint, prettier,
build); if any of steps.typescript.outcome, steps.eslint.outcome,
steps.prettier.outcome, or steps.build.outcome is not "success", exit non‑zero
to fail the workflow (give the step an id like final-verdict and a clear error
message). This preserves the per-step continue-on-error behavior for
comment/logging but enforces a blocking CI failure if any check actually failed.

Comment on lines +5 to +11
import Image from 'next/image';

import { cn } from '@/lib/cn';
import { Button, type ButtonProps } from '@/components/ui/Button';

function AlertDialog({ ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
import InfoIcon from '@/assets/icons/info.svg';
import DeleteIcon from '@/assets/icons/delete_forever.svg';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# 1) Check if SVG files exist
fd 'info\.svg|delete_forever\.svg'

# 2) Check for SVG type declarations
rg -n "declare module ['\"].*\\.svg['\"]"

# 3) Check lucide-react dependency
rg -n "\"lucide-react\"" package.json

Repository: Team-Weeth/weeth-client

Length of output: 163


🏁 Script executed:

# Read the alert-dialog.tsx file to verify actual code state
wc -l src/components/ui/alert-dialog.tsx

Repository: Team-Weeth/weeth-client

Length of output: 105


🏁 Script executed:

# Get the file to see lines 5-11 and around 127-139
head -20 src/components/ui/alert-dialog.tsx

Repository: Team-Weeth/weeth-client

Length of output: 657


🏁 Script executed:

# Check full context around lines 127-139
sed -n '120,145p' src/components/ui/alert-dialog.tsx

Repository: Team-Weeth/weeth-client

Length of output: 807


코딩 가이드라인: Lucide React 아이콘으로 변경 필요

현재 SVG 파일은 모두 존재하므로 빌드 문제는 없습니다. 다만 코딩 가이드라인에 따라 직접 SVG import 대신 lucide-react를 사용해야 합니다. 라인 10-11의 info.svg, delete_forever.svg import와 라인 131, 138의 사용 부분을 Lucide 아이콘으로 교체하세요.

-import Image from 'next/image';
-import InfoIcon from '@/assets/icons/info.svg';
-import DeleteIcon from '@/assets/icons/delete_forever.svg';
+import { Info, Trash2 } from 'lucide-react';
-  const Icon = status === 'danger' ? DeleteIcon : InfoIcon;
+  const Icon = status === 'danger' ? Trash2 : Info;
-      <Image src={Icon} alt="" width={48} height={48} />
+      <span className="bg-container-neutral-interaction text-icon-normal flex h-12 w-12 items-center justify-center rounded-full">
+        <Icon size={24} aria-hidden />
+      </span>
🧰 Tools
🪛 GitHub Check: Lint & Build

[failure] 11-11:
Cannot find module '@/assets/icons/delete_forever.svg' or its corresponding type declarations.


[failure] 10-10:
Cannot find module '@/assets/icons/info.svg' or its corresponding type declarations.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/ui/alert-dialog.tsx` around lines 5 - 11, Replace the direct
SVG imports InfoIcon and DeleteIcon with lucide-react icon components: remove
"import InfoIcon from '@/assets/icons/info.svg'" and "import DeleteIcon from
'@/assets/icons/delete_forever.svg'" and instead import the proper lucide-react
icons (e.g., "import { Info, Trash2 } from 'lucide-react'"). Then update the JSX
usages that render <InfoIcon .../> and <DeleteIcon .../> (the instances
referenced in this file) to use <Info .../> and <Trash2 .../> (preserving
className, size, strokeWidth or other props passed through cn or Button props)
so styling and accessibility remain unchanged.

Comment on lines +13 to +38
type AlertStatus = 'default' | 'danger';

const AlertDialogContext = React.createContext<{ status: AlertStatus }>({
status: 'default',
});

const defaultTexts: Record<AlertStatus, { title: string; description: string }> = {
default: {
title: '변경 사항을 적용하시겠어요?',
description: "선택한 내용이 저장됩니다.\n진행하시려면 '확인'을 눌러주세요.",
},
danger: {
title: '이 게시글을 삭제하시겠어요?',
description: '삭제된 게시글은 복구할 수 없습니다.\n신중히 확인 후 진행해 주세요.',
},
};

interface AlertDialogProps extends React.ComponentProps<typeof AlertDialogPrimitive.Root> {
status?: AlertStatus;
/** 간소화 모드: trigger 엘리먼트를 전달하면 내부에서 Content/Header/Footer를 자동 렌더링 */
trigger?: React.ReactNode;
/** 기본값: status에 따라 자동 설정 */
title?: string;
/** 기본값: status에 따라 자동 설정 */
description?: string;
}
Copy link

@coderabbitai coderabbitai bot Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

상태 변형(status)을 cva + VariantProps 패턴으로 통합해 주세요.

현재는 상태별 분기가 여러 위치에 흩어져 있어 확장 시 유지보수 비용이 큽니다. UI 컴포넌트 규약대로 variants/defaultVariants로 정리하는 편이 안전합니다.

리팩터링 방향 예시
+import { cva, type VariantProps } from 'class-variance-authority';
...
+const alertDialogVariants = cva('', {
+  variants: { status: { default: '', danger: '' } },
+  defaultVariants: { status: 'default' },
+});
+
-interface AlertDialogProps extends React.ComponentProps<typeof AlertDialogPrimitive.Root> {
-  status?: AlertStatus;
+interface AlertDialogProps
+  extends React.ComponentProps<typeof AlertDialogPrimitive.Root>,
+    VariantProps<typeof alertDialogVariants> {
+  status?: AlertStatus;
   ...
 }

As per coding guidelines src/components/ui/**/*.{ts,tsx}: Implement component patterns using cva with variants, defaultVariants, and Props interface extending VariantProps and React.HTMLAttributes.

Also applies to: 179-188

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/ui/alert-dialog.tsx` around lines 13 - 38, The component
currently branches on AlertStatus across AlertStatus, defaultTexts, and
AlertDialogProps; refactor to use cva variants and VariantProps by replacing the
AlertStatus union and scattered defaultTexts with a cva() call that defines
variants (e.g., variant: { default, danger }) and defaultVariants, update the
props interface to extend VariantProps<typeof yourCva> and
React.ComponentProps<typeof AlertDialogPrimitive.Root>, and use the generated
variant classNames/props inside AlertDialogContext and the component to derive
title/description (move defaultTexts into variant defaults or a mapping keyed by
variant) so all status behavior is centralized in the cva variants
configuration.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호.. 이렇게 통합하는 게 유지 보수 시 더 좋겠네요!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JIN921 네, 맞습니다! cva 패턴으로 통합하면 variant가 추가될 때마다 한 곳에서만 관리할 수 있어서 훨씬 안전하고 명확해집니다. 😊

이 리팩토링을 제가 도와드릴까요? 원하신다면 ``를 통해 구체적인 변경 사항을 준비해드릴 수 있습니다. 아니면 직접 작업하시겠다면 제안드린 패턴을 참고하시면 됩니다!

   ∧_∧
  (◕‿◕)
  /    づ💡 Great catch!

🧠 Learnings used
Learnt from: CR
Repo: Team-Weeth/weeth-client PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-02-20T05:00:54.945Z
Learning: Applies to src/components/ui/**/*.{ts,tsx} : Implement component patterns using cva with variants, defaultVariants, and Props interface extending VariantProps and React.HTMLAttributes

💡 For code changes across multiple files, use @coderabbitai plan in an issue comment

Comment on lines +55 to +57
{trigger !== undefined ? (
<>
<AlertDialogTrigger asChild>{trigger}</AlertDialogTrigger>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

trigger={null} 케이스에서 asChild 런타임 오류가 날 수 있습니다.

undefined만 제외하면 null이 들어왔을 때도 간소화 모드로 진입합니다. null도 함께 배제해 주세요.

수정 제안
-        {trigger !== undefined ? (
+        {trigger != null ? (
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/ui/alert-dialog.tsx` around lines 55 - 57, The conditional
currently checks only for trigger !== undefined, which still allows trigger ===
null to render <AlertDialogTrigger asChild>{trigger}</AlertDialogTrigger> and
cause a runtime error; update the check to exclude null as well (e.g., use
trigger != null or trigger !== undefined && trigger !== null or
Boolean(trigger)) so that AlertDialogTrigger is only rendered when trigger is a
valid non-null value, referencing the trigger prop and
AlertDialogTrigger/asChild usage.

Comment on lines +16 to +17
danger:
'bg-[var(--state-error)] text-text-strong hover:opacity-90 active:opacity-80 disabled:bg-button-neutral disabled:text-text-disabled',
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Check the Button.tsx file around lines 16-17
head -30 src/components/ui/Button.tsx | cat -n

Repository: Team-Weeth/weeth-client

Length of output: 1603


🏁 Script executed:

# Check globals.css for state-error token registration
rg -n "state-error" src/app/globals.css -A 2 -B 2

Repository: Team-Weeth/weeth-client

Length of output: 374


🏁 Script executed:

# Also check the `@theme` section in globals.css
rg -n "@theme" src/app/globals.css -A 10 -B 2

Repository: Team-Weeth/weeth-client

Length of output: 756


🏁 Script executed:

# Check the complete `@theme` inline section to see all registered tokens
sed -n '275,350p' src/app/globals.css | cat -n

Repository: Team-Weeth/weeth-client

Length of output: 3433


bg-[var(--state-error)] 대신 디자인 토큰 유틸리티 클래스 bg-state-error를 사용하세요.

globals.css@theme inline--color-state-error: var(--state-error)가 등록되어 있으므로, Tailwind v4가 자동으로 생성하는 bg-state-error 유틸리티 클래스를 직접 사용할 수 있습니다. 다른 variant들(bg-button-primary, bg-button-neutral, bg-button-primary-interaction 등)과의 일관성을 위해 arbitrary value 사용을 피하세요.

💡 제안
        danger:
-          'bg-[var(--state-error)] text-text-strong hover:opacity-90 active:opacity-80 disabled:bg-button-neutral disabled:text-text-disabled',
+          'bg-state-error text-text-strong hover:opacity-90 active:opacity-80 disabled:bg-button-neutral disabled:text-text-disabled',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
danger:
'bg-[var(--state-error)] text-text-strong hover:opacity-90 active:opacity-80 disabled:bg-button-neutral disabled:text-text-disabled',
danger:
'bg-state-error text-text-strong hover:opacity-90 active:opacity-80 disabled:bg-button-neutral disabled:text-text-disabled',
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/ui/Button.tsx` around lines 16 - 17, In
src/components/ui/Button.tsx update the danger variant string (the 'danger' key
in the exported variants) to replace the arbitrary class bg-[var(--state-error)]
with the design-token utility class bg-state-error so it matches other variants
(e.g. bg-button-primary, bg-button-neutral) and avoids arbitrary values; keep
the rest of the class list (text-text-strong hover/active/disabled classes)
unchanged to preserve behavior.

@dalzzy dalzzy changed the title [FEAT] Wth-163-dialog alert 모달 구현 [Feat] WTH-163-dialog alert 모달 구현 Feb 25, 2026
Copy link
Collaborator

@JIN921 JIN921 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다! 코드래빗 수정사항만 잘 적용하면 문제 없을 거 같아요! CI는 왜 자꾸.. 저러는지.. 일단 이전 pr에서 제가 다시 설정을 손 봐 놨으니까.. 그거 적용하고도 문제가 계속 생기면 설정을 다시 해 보겠습니다 ㅜ.ㅜ!!

function AlertDialog({ ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
import InfoIcon from '@/assets/icons/info.svg';
import DeleteIcon from '@/assets/icons/delete_forever.svg';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거 빌드 에러 왜 뜰까요.....
Next.js가 next-env.d.ts를 통해 SVG 모듈을 자동 선언해주고 있어서, 파일만 있으면 TypeScript 타입 에러는 없습니다.
라고 하는데 로컬에서는 에러 안 나고 CI에서만 에러 나는 거면 경로에서 파일을 못 찾는 게 이유가 될 수 잇다구 해요,,

Comment on lines +13 to +38
type AlertStatus = 'default' | 'danger';

const AlertDialogContext = React.createContext<{ status: AlertStatus }>({
status: 'default',
});

const defaultTexts: Record<AlertStatus, { title: string; description: string }> = {
default: {
title: '변경 사항을 적용하시겠어요?',
description: "선택한 내용이 저장됩니다.\n진행하시려면 '확인'을 눌러주세요.",
},
danger: {
title: '이 게시글을 삭제하시겠어요?',
description: '삭제된 게시글은 복구할 수 없습니다.\n신중히 확인 후 진행해 주세요.',
},
};

interface AlertDialogProps extends React.ComponentProps<typeof AlertDialogPrimitive.Root> {
status?: AlertStatus;
/** 간소화 모드: trigger 엘리먼트를 전달하면 내부에서 Content/Header/Footer를 자동 렌더링 */
trigger?: React.ReactNode;
/** 기본값: status에 따라 자동 설정 */
title?: string;
/** 기본값: status에 따라 자동 설정 */
description?: string;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호.. 이렇게 통합하는 게 유지 보수 시 더 좋겠네요!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature 기능 개발 🎨 Html&css 마크업 & 스타일링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants