Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat] Button 컴포넌트 line variant 추가 #118

Merged
merged 8 commits into from
Feb 11, 2025
Merged

Conversation

kongnayeon
Copy link
Member

@kongnayeon kongnayeon commented Feb 10, 2025

관련 이슈

close #109

변경 사항

LineButton 컴포넌트 추가했습니다!
기존 Button 컴포넌트에 line variant를 추가하려 했지만 회전까지 넣으려니 가상선택자나 css trick으로는 한계가 있어 새로 컴포넌트를 만들게 되었습니다 😇...
최대한 기존 Button을 활용해서 만들었고, variant 속성 제외하고는 기존 Button의 props를 그대로 활용할 수 있어요!
그리고 Button에서 isLoading 상태가 바뀜에 따라 width가 변경되는 문제가 있었는데, spinner를 렌더링 할 때도 항상 children의 너비를 기준으로 계산하도록 수정해 일정한 길이를 유지할 수 있도록 했습니다!
image

레퍼런스

Summary by CodeRabbit

  • 신규 기능

    • “5개 더 생성하기” 버튼이 새롭게 추가되어 다양한 상태(로딩, 비활성화)에서 일관된 동작을 제공합니다.
    • 로딩 스피너와 버튼 내 콘텐츠 처리가 개선되어 사용자 경험이 향상되었습니다.
    • 새로운 보라색 계열 컬러 옵션이 추가되어 디자인 선택의 폭을 넓혔습니다.
    • 새로운 애니메이션 효과를 가진 LineButtonAnimate 컴포넌트가 추가되어 시각적 매력이 향상되었습니다.
  • 스타일

    • 버튼과 스피너의 레이아웃 및 애니메이션 효과가 강화되어 인터페이스가 더욱 세련되어졌습니다.

@kongnayeon kongnayeon self-assigned this Feb 10, 2025
Copy link

coderabbitai bot commented Feb 10, 2025

Walkthrough

이 PR은 웹 애플리케이션의 UI 컴포넌트에 변경을 적용합니다. 페이지에 "5개 더 생성하기" 버튼이 추가되어 다양한 크기와 상태(로딩, 비활성화)를 지원하며, 기존의 ImageManager 컴포넌트는 제거되었습니다. 또한, 테마 색상에 보라색 계열(purple100)이 추가되고, Button 컴포넌트에 'line' variant가 도입되어 스타일과 로딩 처리 방식이 개선되었습니다. Spinner 컴포넌트에도 신규 옵션과 클래스 확장이 적용되었으며, 애니메이션 효과를 제공하는 LineButtonAnimate 컴포넌트가 추가되었습니다.

Changes

파일(경로) 변경 내역 요약
apps/web/src/app/page.tsx "5개 더 생성하기" 라벨의 Button 컴포넌트(large, small, 로딩, 비활성화 버전) 추가 및 ImageManager 제거
packages/theme/.../colors.ts 색상 팔레트에 새로운 색상 purple100: '#F9F4FF' 추가
packages/ui/.../Button.css.ts
packages/ui/.../Button.tsx
Button 컴포넌트에 'line' variant 추가, 로딩 상태 렌더링 변경, buttonChildrenRecipe 및 spinner 레시피 도입, LineButtonAnimate 컴포넌트 조건부 적용
packages/ui/.../Spinner.css.ts
packages/ui/.../Spinner.tsx
Spinner 컴포넌트에 'line' variant 및 additional className prop 추가, 타입 확장
packages/ui/.../LineButtonAnimate.css.ts
packages/ui/.../LineButtonAnimate.tsx
새로운 LineButtonAnimate 컴포넌트 추가 및 관련 애니메이션, 스타일 정의

Sequence Diagram(s)

sequenceDiagram
    participant U as 사용자
    participant B as Button
    participant L as LineButtonAnimate
    participant S as Spinner

    U->>B: 버튼 클릭 또는 렌더링 요청
    alt Button variant가 'line'인 경우
        B->>L: LineButtonAnimate로 내용 래핑
        alt 로딩 상태인 경우
            L->>S: Spinner 표시 (line variant)
        else
            L-->>B: 버튼 콘텐츠 렌더링
        end
    else
        B->>B: 일반 Button 렌더링 (Spinner 포함 시 로딩 처리)
    end
Loading

Assessment against linked issues

Objective (목표) Addressed Explanation
Button 컴포넌트 line variant 추가 [#109]

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • minseong0324

Poem

안녕하세요, 작은 토끼예요,
코드 숲 속을 뛰놀며
버튼에 새 생명을 불어넣었죠,
선처럼 깔끔한 애니메이션과 함께,
스피너가 빙글빙글 춤을 추고,
보라빛 꿈을 담은 변경을 축하해요! 🐰
코드와 함께 달콤한 날들을 보내길!

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

packages/ui/src/components/Button/Button.tsx

Oops! Something went wrong! :(

ESLint: 9.17.0

Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@repo/eslint-config' imported from /eslint.config.mjs
at packageResolve (node:internal/modules/esm/resolve:839:9)
at moduleResolve (node:internal/modules/esm/resolve:908:18)
at defaultResolve (node:internal/modules/esm/resolve:1038:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:557:12)
at ModuleLoader.resolve (node:internal/modules/esm/loader:525:25)
at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:246:38)
at ModuleJob._link (node:internal/modules/esm/module_job:126:49)


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 1

🧹 Nitpick comments (4)
packages/ui/src/components/Spinner/Spinner.tsx (1)

11-13: JSDoc 업데이트 필요

현재 JSDoc 주석이 새로 추가된 'line' 색상 옵션과 className 속성을 반영하지 않고 있습니다.

다음과 같이 JSDoc을 업데이트하는 것을 제안합니다:

 /**
  * @param {SpinnerProps} props - 스피너 속성
- * @property {color} [color='white'] - 'black' | 'white' 스피너 색상
+ * @property {color} [color='white'] - 'black' | 'white' | 'line' | 'icon' 스피너 색상
  * @property {size} [size='small'] - 'small' | 'large' 스피너 크기
+ * @property {className} [className=''] - 추가 스타일링을 위한 CSS 클래스
  */
apps/web/src/components/common/LineButton/LineButton.tsx (1)

6-12: 성능 최적화 제안

무한 회전 애니메이션이 성능에 영향을 미칠 수 있습니다. 특히 여러 버튼이 동시에 사용될 경우 더욱 그렇습니다.

다음과 같은 최적화를 고려해보세요:

  1. will-change: transform을 추가하여 브라우저 렌더링 최적화
  2. 저사양 기기를 위한 prefers-reduced-motion 미디어 쿼리 지원
const backgroundVariants = {
  rest: { rotate: 0 },
  hover: {
    rotate: 360,
    transition: { duration: 2, ease: 'linear', repeat: Infinity },
+   willChange: 'transform',
  },
};
apps/web/src/components/common/LineButton/LineButton.css.ts (2)

26-38: 그라데이션 값 상수화 제안

하드코딩된 그라데이션 값과 크기 값들을 상수로 분리하면 유지보수성이 향상될 것 같습니다.

다음과 같은 구조로 변경을 제안합니다:

+ const GRADIENT_CONSTANTS = {
+   WIDTH: '600%',
+   HEIGHT: '600%',
+   TOP: '-250%',
+   LEFT: '-250%',
+   COLORS: {
+     START: '#B68AE7',
+     MIDDLE1: '#3348D6',
+     MIDDLE2: '#9290DC',
+     END: '#F8B3EC',
+   },
+ } as const;

export const gradient = style({
-  width: '600%',
-  height: '600%',
+  width: GRADIENT_CONSTANTS.WIDTH,
+  height: GRADIENT_CONSTANTS.HEIGHT,
  position: 'absolute',
-  top: '-250%',
-  left: '-250%',
+  top: GRADIENT_CONSTANTS.TOP,
+  left: GRADIENT_CONSTANTS.LEFT,
  transform: 'translate(-50%, -50%)',
  zIndex: -1,
  borderRadius: tokens.radius[12],
-  backgroundImage: `linear-gradient(115deg, #B68AE7 44.22%, #3348D6 48.73%, #9290DC 51.48%, #F8B3EC 55.15%);`,
+  backgroundImage: `linear-gradient(115deg, 
+    ${GRADIENT_CONSTANTS.COLORS.START} 44.22%, 
+    ${GRADIENT_CONSTANTS.COLORS.MIDDLE1} 48.73%, 
+    ${GRADIENT_CONSTANTS.COLORS.MIDDLE2} 51.48%, 
+    ${GRADIENT_CONSTANTS.COLORS.END} 55.15%
+  );`,
  backgroundOrigin: 'border-box',
  backgroundClip: 'padding-box, border-box',
  overflow: 'visible',
});

40-57: disabled 상태의 스타일 분리 제안

disabled 상태의 스타일을 별도의 상수로 분리하면 재사용성과 유지보수성이 향상될 것 같습니다.

다음과 같은 구조로 변경을 제안합니다:

+ const DISABLED_STYLES = {
+   backgroundColor: tokens.colors.grey0,
+   color: tokens.colors.grey200,
+   borderColor: tokens.colors.grey100,
+ } as const;

export const button = style({
  border: '0.2rem solid transparent',
  backgroundClip: 'padding-box',
  backgroundColor: tokens.colors.purple100,
  color: tokens.colors.primary800,

  selectors: {
    '&:hover': {
      color: tokens.colors.primary800,
      backgroundColor: tokens.colors.purple100,
    },
    '&:disabled': {
-     backgroundColor: tokens.colors.grey0,
-     color: tokens.colors.grey200,
-     borderColor: tokens.colors.grey100,
+     ...DISABLED_STYLES,
    },
  },
});
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2ac4e66 and ba7be17.

📒 Files selected for processing (8)
  • apps/web/src/app/page.tsx (2 hunks)
  • apps/web/src/components/common/LineButton/LineButton.css.ts (1 hunks)
  • apps/web/src/components/common/LineButton/LineButton.tsx (1 hunks)
  • packages/theme/src/tokens/colors.ts (1 hunks)
  • packages/ui/src/components/Button/Button.css.ts (3 hunks)
  • packages/ui/src/components/Button/Button.tsx (3 hunks)
  • packages/ui/src/components/Spinner/Spinner.css.ts (1 hunks)
  • packages/ui/src/components/Spinner/Spinner.tsx (2 hunks)
🔇 Additional comments (12)
packages/theme/src/tokens/colors.ts (1)

26-26: 구현이 적절합니다!

새로운 purple100 색상이 기존 색상 체계와 일관성 있게 추가되었습니다.

packages/ui/src/components/Button/Button.tsx (4)

11-11: ButtonVariant 타입에 'line' 추가가 적절히 이루어졌습니다.


25-25: SpinnerColor에 'line' 변형 추가가 적절합니다.


47-53: 로딩 상태의 스피너 위치가 적절한지 확인이 필요합니다.

스피너가 버튼 내에서 중앙에 위치하는지 확인해주세요.


54-58: 버튼 자식 요소들의 래핑이 개선되었습니다.

구조적으로 더 명확해졌으며, 로딩 상태에서의 가시성 처리가 적절합니다.

packages/ui/src/components/Spinner/Spinner.css.ts (1)

80-82: 스피너의 'line' 변형 스타일이 적절히 구현되었습니다.

primary800 색상을 사용한 것이 디자인 시스템과 일관성이 있습니다.

packages/ui/src/components/Button/Button.css.ts (4)

8-8: 버튼의 기본 스타일에 position: 'relative' 추가가 적절합니다.

스피너 위치 지정을 위한 필수적인 변경입니다.


84-84: 'line' 변형이 비어있습니다.

스타일 정의가 필요할 수 있습니다. 의도된 것인지 확인해주세요.


97-127: buttonChildrenRecipe가 잘 구현되었습니다.

로딩 상태와 크기에 따른 스타일링이 적절히 처리되었습니다.


129-163: 스피너 레시피가 적절히 구현되었습니다.

위치 지정과 크기별 변형이 잘 정의되어 있습니다.

apps/web/src/app/page.tsx (2)

317-338: LineButton 컴포넌트의 다양한 상태가 잘 구현되었습니다.

큰 사이즈의 버튼에 대해 정상, 로딩, 비활성 상태가 모두 테스트되어 있습니다.


328-338: 작은 사이즈의 LineButton도 적절히 구현되었습니다.

모든 상태가 큰 사이즈와 동일하게 테스트되어 있습니다.

apps/web/src/components/common/LineButton/LineButton.tsx Outdated Show resolved Hide resolved
@@ -84,6 +81,7 @@ export const buttonRecipe = recipe({
},
},
},
line: {},
Copy link
Contributor

Choose a reason for hiding this comment

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

p3: 요거 지워도 될 듯하네요!

Copy link
Member Author

Choose a reason for hiding this comment

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

이거 line일 때는 LineButton에서 스타일을 주는데 Spinner color 같은 것들은 Button 컴포넌트에서 처리하려고 하다 보니 Button variant에 'line'을 추가했거든요! 그러다 보니 저렇게 빈 객체로 선언해 주지 않으면 타입 에러가 떠서 선언해 줬습니다...

@@ -77,6 +77,9 @@ export const circleRecipe = recipe({
white: {
stroke: `${tokens.colors.grey0}`,
},
line: {
Copy link
Contributor

Choose a reason for hiding this comment

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

p2: LineButton을 apps/web에서 구현했으니 관련 스타일을 모두 apps/web에서 적용시키는 게 어떨까요?

Copy link
Member Author

Choose a reason for hiding this comment

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

~ packages/ui로 끌어올리기로 구두 논의 완료 ~

@@ -2,8 +2,9 @@ import { forwardRef } from 'react';
import * as styles from './Spinner.css';

export type SpinnerProps = {
color?: 'black' | 'white' | 'icon';
color?: 'black' | 'white' | 'line' | 'icon';
Copy link
Contributor

Choose a reason for hiding this comment

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

p3: LineButton을 apps/web에서 구현했으니 관련 스타일을 모두 apps/web에서 적용시키는 게 어떨까요?

마찬가지 입니다!

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: 4

🧹 Nitpick comments (1)
packages/ui/src/components/LineButton/LineButton.css.ts (1)

5-23: wrapper 스타일의 반응형 처리 개선 제안

현재 구현은 잘 되어있지만, 다음과 같은 개선을 고려해보세요:

  • width를 props로 받아 유연하게 조절할 수 있도록 하기
  • 모바일 환경을 고려한 반응형 스타일 추가
 export const wrapper = recipe({
   base: {
-    width: 'fit-content',
+    width: ({ width }) => width || 'fit-content',
     height: 'fit-content',
     position: 'relative',
     overflow: 'hidden',
     borderRadius: '1.2rem',
   },
   variants: {
+    responsive: {
+      true: {
+        '@media': {
+          'screen and (max-width: 768px)': {
+            width: '100%',
+          },
+        },
+      },
+    },
     size: {
       // ... existing size variants
     },
   },
 });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ba7be17 and e930b35.

📒 Files selected for processing (6)
  • apps/web/src/app/page.tsx (2 hunks)
  • packages/ui/package.json (1 hunks)
  • packages/ui/src/components/Button/Button.css.ts (3 hunks)
  • packages/ui/src/components/LineButton/LineButton.css.ts (1 hunks)
  • packages/ui/src/components/LineButton/LineButton.tsx (1 hunks)
  • packages/ui/src/components/LineButton/index.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/ui/src/components/LineButton/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/src/app/page.tsx
🔇 Additional comments (5)
packages/ui/src/components/LineButton/LineButton.tsx (2)

14-42: 구현이 깔끔하고 완성도가 높습니다!

  • forwardRef를 적절히 사용하여 ref를 전달
  • variant prop을 제외한 ButtonProps 타입 재사용
  • motion.div를 활용한 애니메이션 래퍼 구현이 잘 되어있습니다.

44-44: displayName 설정이 잘 되어있습니다!

디버깅 시 컴포넌트 식별이 용이하도록 displayName이 적절히 설정되어 있습니다.

packages/ui/src/components/LineButton/LineButton.css.ts (1)

40-57: button 스타일 구현이 잘 되어있습니다!

  • 테마 토큰을 일관성 있게 사용
  • hover와 disabled 상태에 대한 스타일이 적절히 정의되어 있습니다.
packages/ui/src/components/Button/Button.css.ts (1)

97-127: buttonChildrenRecipe 구현이 잘 되어있습니다!

로딩 상태와 사이즈별 스타일링이 잘 정의되어 있습니다.

packages/ui/package.json (1)

90-93: LineButton 컴포넌트 export 설정이 적절합니다!

타입과 구현체 경로가 올바르게 설정되어 있습니다.

@@ -0,0 +1,44 @@
import { Button, ButtonProps } from '@repo/ui/Button';
import { motion } from 'motion/react';
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

motion 라이브러리 import 경로 및 애니메이션 설정 검토 필요

  1. motion 라이브러리의 import 경로가 표준적이지 않습니다. '@Framer-motion'을 사용하는 것이 더 일반적입니다.
  2. 애니메이션 설정을 props로 받아 커스터마이징할 수 있게 하면 좋을 것 같습니다.

Also applies to: 6-12


🌐 Web query:

What is the correct import path for framer-motion?

💡 Result:

The correct import path for Framer Motion in a React project is:

import { motion } from "framer-motion";

This standard import is shown consistently across multiple sources[1][2][4][5][8][10]. For advanced features like exit animations and component presence tracking, you might also need to import AnimatePresence:

import { motion, AnimatePresence } from "framer-motion";

Key details:

  • Installed via npm install framer-motion or yarn add framer-motion[1][2][5][8]
  • Used by prefixing HTML/SVG elements with motion. (e.g., <motion.div> or <motion.path>)[1][4][7]
  • Supports both functional components and TypeScript projects[8]

The import path remains consistent whether using basic animations or advanced SVG path animations[1][4][7].

Citations:


모션 라이브러리의 올바른 import 경로와 애니메이션 커스터마이징 개선 필요

  • 현재 파일에서는 import { motion } from 'motion/react';를 사용 중인데, 최신 Framer Motion 사용법에 따르면 아래와 같이 수정해야 합니다:

    import { motion } from "framer-motion";
  • 또한, 애니메이션 설정은 컴포넌트의 props로 받아 커스터마이징할 수 있도록 개선하는 것을 고려해보면 좋겠습니다.

→ 관련 파일: packages/ui/src/components/LineButton/LineButton.tsx (특히 2번 라인 및 6-12번 라인)

packages/ui/src/components/LineButton/LineButton.css.ts Outdated Show resolved Hide resolved
packages/ui/src/components/Button/Button.css.ts Outdated Show resolved Hide resolved
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: 1

🧹 Nitpick comments (6)
packages/ui/src/components/Button/LineButtonAnimate.css.ts (2)

26-31: 그라데이션 크기와 위치 최적화 필요

그라데이션의 크기(600%)와 위치(-250%)가 과도하게 설정되어 있습니다. 이는 불필요한 오버헤드를 발생시킬 수 있습니다.

다음과 같이 수정하는 것을 제안합니다:

-  width: '600%',
-  height: '600%',
+  width: '300%',
+  height: '300%',
   position: 'absolute',
-  top: '-250%',
-  left: '-250%',
+  top: '-100%',
+  left: '-100%',

25-38: 성능 최적화 속성 추가 필요

그라데이션 애니메이션의 성능을 최적화하기 위한 속성이 누락되어 있습니다.

다음 속성들을 추가하는 것을 제안합니다:

 export const gradient = style({
   // ... existing styles
+  willChange: 'transform',
+  backfaceVisibility: 'hidden',
+  transform: 'translate(-50%, -50%) translateZ(0)',
 });
packages/ui/src/components/Button/LineButtonAnimate.tsx (1)

6-12: 타입 안전성 개선 필요

backgroundVariants에 대한 타입 정의가 누락되어 있습니다.

다음과 같이 타입을 추가하는 것을 제안합니다:

+type BackgroundVariants = {
+  rest: { rotate: number };
+  hover: {
+    rotate: number;
+    transition: {
+      duration: number;
+      ease: string;
+      repeat: number;
+    };
+  };
+};

-const backgroundVariants = {
+const backgroundVariants: BackgroundVariants = {
   rest: { rotate: 0 },
   hover: {
     rotate: 360,
     transition: { duration: 2, ease: 'linear', repeat: Infinity },
   },
 };
packages/ui/src/components/Button/Button.tsx (2)

22-27: SpinnerColor 타입 안전성 개선 필요

SpinnerColor 매핑의 타입 안전성이 부족합니다.

다음과 같이 수정하는 것을 제안합니다:

-const SpinnerColor: Record<ButtonVariant, SpinnerProps['color']> = {
+const SpinnerColor = {
   primary: 'white',
   neutral: 'white',
   text: 'black',
   line: 'line',
-};
+} as const satisfies Record<ButtonVariant, SpinnerProps['color']>;

43-64: 성능 최적화를 위한 content 메모이제이션 필요

content가 매 렌더링마다 재생성되고 있습니다.

다음과 같이 useMemo를 사용하여 최적화하는 것을 제안합니다:

+import { useMemo } from 'react';

 export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
   ({
     size,
     variant = 'primary',
     isLoading = false,
     leftAddon,
     rightAddon,
     children,
     className = '',
     ...rest
   }, ref) => {
-    const content = (
+    const content = useMemo(() => (
       <button
         ref={ref}
         className={`${buttonRecipe({ size, variant, isLoading })} ${className}`}
         {...rest}
       >
         {isLoading && (
           <Spinner
             className={spinner({ size, isLoading })}
             color={SpinnerColor[variant]}
             size={size}
           />
         )}
         <div className={`${buttonChildrenRecipe({ size, isLoading })}`}>
           {leftAddon && <div className={addonRootStyle[size]}>{leftAddon}</div>}
           {children}
           {rightAddon && (
             <div className={addonRootStyle[size]}>{rightAddon}</div>
           )}
         </div>
       </button>
-    );
+    ), [size, variant, isLoading, className, ref, rest, leftAddon, rightAddon, children]);
packages/ui/src/components/Button/Button.css.ts (1)

84-101: line variant 스타일 개선 필요

line variant에 hover 트랜지션과 일관된 단위 사용이 필요합니다.

다음과 같이 수정하는 것을 제안합니다:

 line: {
-  border: '0.2rem solid transparent',
+  border: '2px solid transparent',
   backgroundClip: 'padding-box',
   backgroundColor: tokens.colors.purple100,
   color: tokens.colors.primary800,
+  transition: 'all 0.2s ease-in-out',

   selectors: {
     '&:hover': {
       color: tokens.colors.primary800,
       backgroundColor: tokens.colors.purple100,
+      transform: 'scale(1.02)',
     },
     '&:disabled': {
       backgroundColor: tokens.colors.grey0,
       color: tokens.colors.grey200,
       borderColor: tokens.colors.grey100,
     },
   },
 },
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e930b35 and 92cbba2.

📒 Files selected for processing (5)
  • apps/web/src/app/page.tsx (1 hunks)
  • packages/ui/src/components/Button/Button.css.ts (3 hunks)
  • packages/ui/src/components/Button/Button.tsx (3 hunks)
  • packages/ui/src/components/Button/LineButtonAnimate.css.ts (1 hunks)
  • packages/ui/src/components/Button/LineButtonAnimate.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/src/app/page.tsx
🔇 Additional comments (1)
packages/ui/src/components/Button/Button.css.ts (1)

156-164: spinner 레시피의 빈 variant 스타일 정의 필요

size와 isLoading variant에 대한 스타일이 정의되어 있지 않습니다.

) : (
<>
) => {
const content = (
Copy link
Contributor

Choose a reason for hiding this comment

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

p5: 변수명 buttonElement가 어떨까요?

Copy link
Member Author

Choose a reason for hiding this comment

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

좋습니다 👍🏻

@kongnayeon kongnayeon changed the title [Feat] LineButton 컴포넌트 추가 [Feat] Button 컴포넌트 line variant 추가 Feb 11, 2025
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: 0

🧹 Nitpick comments (1)
packages/ui/src/components/Button/Button.tsx (1)

66-69: line 변형에 대한 조건부 렌더링 로직이 명확합니다.

line 변형일 경우 LineButtonAnimate로 래핑하는 로직이 깔끔하게 구현되었습니다. 다만, 이 부분에 대한 단위 테스트 추가를 고려해보시면 좋겠습니다.

다음 테스트 케이스들을 고려해보시기 바랍니다:

  1. line 변형 시 LineButtonAnimate가 정상적으로 렌더링되는지
  2. 다른 변형에서는 LineButtonAnimate가 렌더링되지 않는지
  3. size prop이 LineButtonAnimate에 올바르게 전달되는지

테스트 코드 작성에 도움이 필요하시다면 말씀해 주세요.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 92cbba2 and 126dd0c.

📒 Files selected for processing (1)
  • packages/ui/src/components/Button/Button.tsx (3 hunks)
🔇 Additional comments (4)
packages/ui/src/components/Button/Button.tsx (4)

2-9: CSS 모듈과 컴포넌트 임포트가 잘 구성되어 있습니다.

CSS 모듈과 컴포넌트를 분리하여 임포트하는 구조가 깔끔합니다.


12-12: ButtonVariant 타입 확장이 적절합니다.

'line' 변형이 추가되어 버튼의 다양성이 향상되었습니다.


26-26: line 변형에 대한 Spinner 색상이 적절히 매핑되었습니다.

SpinnerColor 레코드에 line 변형에 대한 매핑이 추가되었습니다.


43-64: 버튼 엘리먼트 구조가 개선되었습니다.

buttonElement 변수를 사용하여 코드의 가독성이 향상되었고, 로딩 상태 처리가 더 명확해졌습니다.

이전 리뷰에서 제안된 'buttonElement' 변수명을 채택한 것이 좋습니다.

@kongnayeon kongnayeon merged commit ef54c49 into develop Feb 11, 2025
2 checks passed
@kongnayeon kongnayeon deleted the feat/#a0ca4f253 branch February 11, 2025 20:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature] Button 컴포넌트 line variant 추가
2 participants