From 15b43500510a80c7655ec33496f246a98fcf44ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B6=8C=ED=98=81=EC=84=B1?= Date: Thu, 29 Jan 2026 07:44:10 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20accordion=20UI=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - @radix-ui/react-accordion 패키지 설치 - accordion.tsx 컴포넌트 생성 (shadcn/ui 패턴) - globals.css에 accordion 애니메이션 추가 --- package-lock.json | 43 +++++++++++++++------ package.json | 1 + src/app/globals.css | 12 ++++++ src/components/ui/accordion.tsx | 66 +++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 11 deletions(-) create mode 100644 src/components/ui/accordion.tsx diff --git a/package-lock.json b/package-lock.json index 88a82e40..f3fed8ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@capacitor/core": "^8.0.0", "@capacitor/push-notifications": "^8.0.0", "@hookform/resolvers": "^5.2.2", + "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-checkbox": "^1.3.3", "@radix-ui/react-collapsible": "^1.1.12", @@ -1568,6 +1569,37 @@ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", "license": "MIT" }, + "node_modules/@radix-ui/react-accordion": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.12.tgz", + "integrity": "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collapsible": "1.1.12", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-alert-dialog": { "version": "1.1.15", "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.15.tgz", @@ -8377,17 +8409,6 @@ } } }, - "node_modules/next-intl/node_modules/@swc/helpers": { - "version": "0.5.18", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.18.tgz", - "integrity": "sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==", - "license": "Apache-2.0", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.8.0" - } - }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", diff --git a/package.json b/package.json index b2f4b8aa..f547f5f8 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@capacitor/core": "^8.0.0", "@capacitor/push-notifications": "^8.0.0", "@hookform/resolvers": "^5.2.2", + "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-checkbox": "^1.3.3", "@radix-ui/react-collapsible": "^1.1.12", diff --git a/src/app/globals.css b/src/app/globals.css index b74d3dd4..b5f4a7dd 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -171,6 +171,8 @@ } @theme inline { + --animate-accordion-down: accordion-down 0.2s ease-out; + --animate-accordion-up: accordion-up 0.2s ease-out; --color-background: var(--background); --color-foreground: var(--foreground); --color-card: var(--card); @@ -469,6 +471,16 @@ html { to { opacity: 0; } } +@keyframes accordion-down { + from { height: 0; } + to { height: var(--radix-accordion-content-height); } +} + +@keyframes accordion-up { + from { height: var(--radix-accordion-content-height); } + to { height: 0; } +} + /* Sheet Content - Right side slide animation (기본값, right-0 클래스) */ [data-slot="sheet-content"].right-0[data-state="open"] { animation: slideInFromRight 300ms cubic-bezier(0.16, 1, 0.3, 1) forwards; diff --git a/src/components/ui/accordion.tsx b/src/components/ui/accordion.tsx new file mode 100644 index 00000000..9ace7684 --- /dev/null +++ b/src/components/ui/accordion.tsx @@ -0,0 +1,66 @@ +"use client" + +import * as React from "react" +import * as AccordionPrimitive from "@radix-ui/react-accordion" +import { ChevronDownIcon } from "lucide-react" + +import { cn } from "@/lib/utils" + +function Accordion({ + ...props +}: React.ComponentProps) { + return +} + +function AccordionItem({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AccordionTrigger({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + svg]:rotate-180", + className + )} + {...props} + > + {children} + + + + ) +} + +function AccordionContent({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + +
{children}
+
+ ) +} + +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } \ No newline at end of file