-
Notifications
You must be signed in to change notification settings - Fork 2
Feat 10 #12
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
base: main
Are you sure you want to change the base?
Feat 10 #12
Conversation
๐ WalkthroughWalkthroughThis PR establishes a foundational design system with CSS tokens and typography utilities, introduces a main app layout structure with supporting pages, and adds an extensive library of reusable UI components across feature areas including book stories, profiles, news, search, settings, and home features. Changes
Estimated code review effort๐ฏ 3 (Moderate) | โฑ๏ธ ~25 minutes Poem
Pre-merge checks and finishing touchesโ Failed checks (1 warning, 1 inconclusive)
โ Passed checks (1 passed)
โจ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary of ChangesHello @hongik-luke, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! ์ด PR์ ์ ํ๋ฆฌ์ผ์ด์ ์ ํต์ฌ UI ์ปดํฌ๋ํธ์ ๊ธฐ๋ณธ ๋ ์ด์์์ ๊ตฌ์ถํ๋ ๋ฐ ์ค์ ์ ๋ก๋๋ค. ๋ค์ํ ํ์ด์ง์ ํ์ํ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ UI ์์๋ค์ ์ ์ํ๊ณ , ์ผ๊ด๋ ๋์์ธ ์์คํ ์ ์ํ ๊ธ๋ก๋ฒ ์คํ์ผ ๋ฐ ํ์ดํฌ๊ทธ๋ํผ๋ฅผ ์ค์ ํ์ต๋๋ค. ์ด๋ฅผ ํตํด ํฅํ ๊ธฐ๋ฅ ๊ฐ๋ฐ์ ๊ธฐ๋ฐ์ ๋ง๋ จํ๊ณ ์ฌ์ฉ์ ๊ฒฝํ์ ์ผ๊ด์ฑ์ ํ๋ณดํ๋ ๊ฒ์ ๋ชฉํ๋ก ํฉ๋๋ค. Highlights
๐ง New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with ๐ and ๐ on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
์ด PR์ ์๋ก์ด UI ์ปดํฌ๋ํธ๋ฅผ ๋๊ฑฐ ์ถ๊ฐํ๊ณ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ธฐ๋ณธ ๊ตฌ์กฐ์ ์ ์ญ ์คํ์ผ์ ์ค์ ํ๋ ์ค์ํ ๋ณ๊ฒฝ์ฌํญ์ ๋ด๊ณ ์์ต๋๋ค. ์ ๋ฐ์ ์ธ ๊ตฌ์กฐ๋ ์ข์ง๋ง, ๋ช ๊ฐ์ง ๊ฐ์ ์ ์ด ํ์ํด ๋ณด์
๋๋ค. home_bookclub.tsx์์ ๋ก์ง ๋ฐ ์คํ์ผ๋ง๊ณผ ๊ด๋ จ๋ ๋ช ๊ฐ์ง ์ฌ๊ฐํ ๋ฌธ์ ๋ฅผ ๋ฐ๊ฒฌํ์ผ๋ฉฐ, button_without_img.tsx์์๋ hover ํจ๊ณผ ๊ตฌํ ๋ฐฉ์์ ๋ํ ๊ฐ์ ์ด ํ์ํฉ๋๋ค. ๋ํ ์ฌ๋ฌ ์ปดํฌ๋ํธ(news_list, notification_element)์ ๊ฑธ์ณ ์ฝ๋ ์ค๋ณต์ด ์๋นํ์ฌ ๋ฆฌํฉํ ๋ง์ด ํ์ํฉ๋๋ค. ๊ทธ ์ธ์๋ ํ๋์ฝ๋ฉ๋ ์์, ์ผ๊ด์ฑ ์๋ ์ด๋ฆ ์ง์ , ์ ๊ทผ์ฑ ๋ฌธ์ (๋์ฒด ํ
์คํธ/๋ ์ด๋ธ ๋๋ฝ) ๋ฑ์ด ๋ค์ ๋ฐ๊ฒฌ๋์์ต๋๋ค. ์์ธํ ๋ด์ฉ์ ๊ฐ๋ณ ์ฝ๋ฉํธ๋ฅผ ์ฐธ๊ณ ํด์ฃผ์ธ์.
| text-[13px] flex items-center justify-center gap-2" | ||
| > | ||
| <Image src="/icon_plus.svg" alt="icon_plus" width={24} height={24} /> | ||
| <span className="text-color-white Subhead_4_1">๋ชจ์ ์์ฑํ๊ธฐ</span> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| > | ||
| {open ? ( | ||
| <div className="flex items-center justify-center gap-1"> | ||
| <span className="text-[color:var(--Gray_7)] Body_1_2 font-weight: 500">์ ๊ธฐ</span> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
className ๋ฌธ์์ด ์์ font-weight: 500๊ณผ ๊ฐ์ ์ผ๋ฐ CSS ์์ฑ์ ์ฌ์ฉํ์ต๋๋ค. Tailwind CSS์์๋ font-medium๊ณผ ๊ฐ์ ์ ํธ๋ฆฌํฐ ํด๋์ค๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
| <span className="text-[color:var(--Gray_7)] Body_1_2 font-weight: 500">์ ๊ธฐ</span> | |
| <span className="text-[color:var(--Gray_7)] Body_1_2 font-medium">์ ๊ธฐ</span> |
| key={group.id} | ||
| className="flex w-[288px] h-[52px] py-3 px-4 items-center rounded-lg bg-white" | ||
| > | ||
| <span className="text-[color:var(--Gray--7)] h-6 Subhead_4_1 "> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CSS ๋ณ์ ์ด๋ฆ์ ์คํ๊ฐ ์์ต๋๋ค. --Gray--7์ด ์๋๋ผ --Gray_7์ด ์ฌ๋ฐ๋ฅธ ๋ณ์๋ช
์
๋๋ค. ์ด ์คํ๋ก ์ธํด ์คํ์ผ์ด ์ ์ฉ๋์ง ์์ต๋๋ค.
| <span className="text-[color:var(--Gray--7)] h-6 Subhead_4_1 "> | |
| <span className="text-[color:var(--Gray_7)] h-6 Subhead_4_1 "> |
|
|
||
| export default function HomeBookclub({ groups }: Props) { | ||
| const count = groups.length; | ||
| const isMany = count >= 5; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
๋ชจ์ ๋ชฉ๋ก์ ๋ณด์ฌ์ฃผ๋ ๋ก์ง์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. isMany์ ์กฐ๊ฑด์ด count >= 5์ธ๋ฐ, 5๊ฐ ๋๋ 6๊ฐ์ ๊ทธ๋ฃน์ด ์์ ๋ "์ ์ฒด๋ณด๊ธฐ" ๋ฒํผ์ด ํ์๋์ง๋ง, ์ค์ ๋ก๋ ๋ชจ๋ ํญ๋ชฉ์ด ์ด๋ฏธ ํ๋ฉด์ ๋ณด์ด๊ณ ์์ต๋๋ค. ์ฌ์ฉ์๊ฐ ํผ๋ํ์ง ์๋๋ก, "์ ์ฒด๋ณด๊ธฐ" ๋ฒํผ์ ์ค์ ๋ก ์จ๊ฒจ์ง ํญ๋ชฉ์ด ์์ ๋๋ง (์: count > 6) ๋ํ๋๋๋ก ์กฐ๊ฑด์ ์์ ํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
| const isMany = count >= 5; | |
| const isMany = count > 6; |
| "use client"; | ||
| import Image from "next/image"; | ||
|
|
||
| type NewsListProps = { | ||
| imageUrl: string; | ||
| title: string; | ||
| content: string; | ||
| date: string; // "2025-10-09" ๊ฐ์ ๋ฌธ์์ด | ||
| className?: string; | ||
| }; | ||
|
|
||
| export default function Setting_NewsList({ | ||
| imageUrl, | ||
| title, | ||
| content, | ||
| date, | ||
| className = "", | ||
| }: NewsListProps) { | ||
| return ( | ||
| <div | ||
| className={[ | ||
| "inline-flex w-full max-w-[1000px] p-[20px] items-start", | ||
| "rounded-[8px] border border-[color:var(--Subbrown_4,#EAE5E2)] bg-white gap-6", | ||
| className, | ||
| ].join(" ")} | ||
| > | ||
| {/* left image */} | ||
| <div className="relative w-[100px] h-[145px] shrink-0 "> | ||
| <Image | ||
| src={imageUrl} | ||
| alt={title} | ||
| fill | ||
| sizes="100px" | ||
| className="object-cover" | ||
| /> | ||
| </div> | ||
|
|
||
| {/* middle + right */} | ||
| <div className="flex flex-1 min-w-0 items-start"> | ||
| {/* middle text */} | ||
| <div className="flex flex-col gap-[8px] min-w-0 flex-1"> | ||
| <p className="text-[#000] Subhead_3 truncate">{title}</p> | ||
| <p className="text-[color:var(--Gray_4,#8D8D8D)] Body_1_2 line-clamp-6"> | ||
| {content} | ||
| </p> | ||
| </div> | ||
|
|
||
| {/* ์ต์ 120px ํ๋ณด + ๋ ์ง ์ค๋ฅธ์ชฝ ๊ณ ์ */} | ||
| <div className="shrink-0 min-w-[180px] text-right"> | ||
| <p className="text-[color:var(--Gray_3,#BBB)] Body_1_2">{date}</p> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
์ด ์ปดํฌ๋ํธ๋ src/components/base-ui/News/news_list.tsx์ max-w ํด๋์ค๋ฅผ ์ ์ธํ๊ณ ๊ฑฐ์ ๋์ผํฉ๋๋ค. ์ฝ๋ ์ค๋ณต์ ์ ์ง๋ณด์๋ฅผ ์ด๋ ต๊ฒ ๋ง๋ญ๋๋ค. ํ๋์ NewsList ์ปดํฌ๋ํธ๋ก ํตํฉํ๊ณ , className์ด๋ maxWidth ๊ฐ์ prop์ ํตํด ์คํ์ผ์ ๋์ ์ผ๋ก ์ ์ดํ๋ ๋ฐฉ์์ผ๋ก ๋ฆฌํฉํ ๋งํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค.
| <div className="flex flex-1 min-w-0 items-start"> | ||
| {/* middle text */} | ||
| <div className="flex flex-col gap-[8px] min-w-0 flex-1"> | ||
| <p className="text-[#000] Subhead_3 truncate">{title}</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
์์ ๊ฐ #000์ด ํ๋์ฝ๋ฉ๋์ด ์์ต๋๋ค. globals.css์ ์ ์๋ --Black CSS ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ๋์์ธ ์์คํ
์ ์ผ๊ด์ฑ์ ์ ์งํด์ฃผ์ธ์.
| <p className="text-[#000] Subhead_3 truncate">{title}</p> | |
| <p className="text-[color:var(--Black)] Subhead_3 truncate">{title}</p> |
| authorNickname: string; | ||
| authorId: string | number; | ||
|
|
||
| profileImgSrc?: string; // ๊ธฐ๋ณธ: "/profile.svg" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
profileImgSrc prop์ ๊ธฐ๋ณธ๊ฐ์ ๋ํ ์ฃผ์์ด ์ค์ ์ฝ๋์ ์ผ์นํ์ง ์์ต๋๋ค. ์ฃผ์์๋ "/profile.svg"๋ก ๋์ด์์ง๋ง, ์ฝ๋์์๋ "/profile2.svg"๋ฅผ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ์ฃผ์์ ์ค์ ์ฝ๋์ ๋ง๊ฒ ์์ ํ์ฌ ํผ๋์ ๋ฐฉ์งํด์ฃผ์ธ์.
| profileImgSrc?: string; // ๊ธฐ๋ณธ: "/profile.svg" | |
| profileImgSrc?: string; // ๊ธฐ๋ณธ: "/profile2.svg" |
| </div> | ||
| ) : ( | ||
| <div className="flex items-center justify-center gap-1"> | ||
| <span className="text-[color:var(--Gray_7)] Body_1_2 Body_1_2">์ ์ฒด๋ณด๊ธฐ</span> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| border border-[color:var(--premary_2,#9A7A6B)] | ||
| bg-[color:var(--background,#F9F7F6)] | ||
| text-[color:var(--premary_2,#9A7A6B)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CSS ๋ณ์ ์ด๋ฆ์ ์คํ๊ฐ ์์ต๋๋ค. premary_2๊ฐ ์๋๋ผ primary_2๊ฐ ์ฌ๋ฐ๋ฅธ ๋ณ์๋ช
์
๋๋ค. ์ด ์คํ๋ก ์ธํด ์คํ์ผ์ด ์ฌ๋ฐ๋ฅด๊ฒ ์ ์ฉ๋์ง ์์ ์ ์์ต๋๋ค.
| border border-[color:var(--premary_2,#9A7A6B)] | |
| bg-[color:var(--background,#F9F7F6)] | |
| text-[color:var(--premary_2,#9A7A6B)] | |
| border border-[color:var(--primary_2,#9A7A6B)] | |
| bg-[color:var(--background,#F9F7F6)] | |
| text-[color:var(--primary_2,#9A7A6B)] |
| <p className="text-[#000] Subhead_3 truncate">{bookName}</p> | ||
| <p className="text-[#757575] Subhead_4_1 truncate">{author}</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
์์ ๊ฐ์ด ํ๋์ฝ๋ฉ๋์ด ์์ต๋๋ค. ๋์์ธ ์์คํ
์ ์ผ๊ด์ฑ์ ์ ์งํ๊ธฐ ์ํด globals.css์ ์ ์๋ CSS ๋ณ์(์: var(--Black), var(--Gray_5))๋ฅผ ์ฌ์ฉํด์ฃผ์ธ์.
| <p className="text-[#000] Subhead_3 truncate">{bookName}</p> | |
| <p className="text-[#757575] Subhead_4_1 truncate">{author}</p> | |
| <p className="text-[color:var(--Black)] Subhead_3 truncate">{bookName}</p> | |
| <p className="text-[color:var(--Gray_5)] Subhead_4_1 truncate">{author}</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 11
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
โป๏ธ Duplicate comments (2)
src/components/base-ui/home/notification_element.tsx (1)
1-47: LGTM!The component logic is correct. The conditional rendering for the latest notification indicator and the message construction based on type are well-implemented. Note: duplication with
Profile/notification_element.tsxwas flagged in the other file's review.src/components/base-ui/News/news_list.tsx (1)
1-55: Code duplication with Setting_NewsList component.This component is nearly identical to
src/components/base-ui/Settings/setting_news_list.tsx. The duplication concern and refactoring recommendation have been documented in the review of that file.
๐ก Minor comments (10)
src/components/base-ui/home/home_bookclub.tsx-72-72 (1)
72-72: Remove duplicate class.
Body_1_2is specified twice.๐ Proposed fix
- <span className="text-[color:var(--Gray_7)] Body_1_2 Body_1_2">์ ์ฒด๋ณด๊ธฐ</span> + <span className="text-[color:var(--Gray_7)] Body_1_2">์ ์ฒด๋ณด๊ธฐ</span>src/components/base-ui/home/home_bookclub.tsx-49-51 (1)
49-51: Fix CSS variable name typo.
--Gray--7(double dash) should be--Gray_7(underscore) to match the design system convention used elsewhere.๐ Proposed fix
- <span className="text-[color:var(--Gray--7)] h-6 Subhead_4_1 "> + <span className="text-[color:var(--Gray_7)] h-6 Subhead_4_1">src/components/base-ui/home/home_bookclub.tsx-67-68 (1)
67-68: Invalid CSS syntax in className.
font-weight: 500is CSS syntax, not a valid Tailwind class. Usefont-mediuminstead.๐ Proposed fix
- <span className="text-[color:var(--Gray_7)] Body_1_2 font-weight: 500">์ ๊ธฐ</span> + <span className="text-[color:var(--Gray_7)] Body_1_2 font-medium">์ ๊ธฐ</span>src/components/base-ui/home/home_bookclub.tsx-63-63 (1)
63-63: Fix CSS variable name typo.
--Gray--3should be--Gray_3to match the design system convention.๐ Proposed fix
- className="w-full h-[38px] rounded-[6px] bg-transparent text-[13px] flex items-center justify-center gap-[6px] text-[color:var(--Gray--3)]" + className="w-full h-[38px] rounded-[6px] bg-transparent text-[13px] flex items-center justify-center gap-[6px] text-[color:var(--Gray_3)]"src/components/base-ui/home/list_subscribe_element.tsx-24-32 (1)
24-32: Fixsizesprop mismatch.The container is
32x32butsizes="42px". These should match for optimal image loading.๐ Proposed fix
- sizes="42px" + sizes="32px"src/components/base-ui/home/home_bookclub.tsx-32-33 (1)
32-33: Fix image path and use Next.js Image component.The
srcis missing a leading/and uses a native<img>instead of Next.jsImage, which is inconsistent with the rest of the component.๐ Proposed fix
- <img src="logo2.svg" alt= "๋ก๊ณ " className="mx-auto mb-4 mt-[118px]" /> + <Image src="/logo2.svg" alt="๋ก๊ณ " width={100} height={100} className="mx-auto mb-4 mt-[118px]" />Committable suggestion skipped: line range outside the PR's diff.
src/components/base-ui/Profile/mypage_profile.tsx-7-7 (1)
7-7: Update comment to match implementation.The comment states the default is
/profile.svg, but line 25 uses/profile3.svgas the default value.๐ Fix comment
- profileImgSrc?: string; // default: /profile.svg + profileImgSrc?: string; // default: /profile3.svgsrc/components/base-ui/Profile/mypage_profile.tsx-6-22 (1)
6-22: Export the MypageProfileProps type.The type is not exported, making it unavailable to consumers who might need it for type-safe prop passing or composition. This is inconsistent with the PR summary, which indicates the type should be part of the public API surface.
๐ Add export keyword
-type MypageProfileProps = { +export type MypageProfileProps = { profileImgSrc?: string; // default: /profile.svg name: string;src/components/base-ui/Search/search_bookresult.tsx-55-55 (1)
55-55: Fix typo:flex1should beflex-1.The className
flex1is not a valid Tailwind utility. This should beflex-1to apply the flexbox grow property.๐ Proposed fix
- <p className="flex1 h-full text-[color:var(--Gray_4,#8D8D8D)] Body_1_2 line-clamp-6"> + <p className="flex-1 h-full text-[color:var(--Gray_4,#8D8D8D)] Body_1_2 line-clamp-6"> {clippedDetail} </p>src/components/base-ui/Search/search_recommendbook.tsx-35-35 (1)
35-35: Imagesizesattribute doesn't match container dimensions.The container width is
332px, but thesizesattribute is set to"244px". This mismatch may cause Next.js to fetch a suboptimally-sized image, affecting performance and quality.๐ Suggested fix
- <Image src={coverSrc} alt={title} fill sizes="244px" className="object-cover" /> + <Image src={coverSrc} alt={title} fill sizes="332px" className="object-cover" />Alternatively, if the image area is intended to be smaller due to padding or other factors, adjust the sizes value to match the actual rendered width.
๐งน Nitpick comments (21)
src/components/base-ui/Profile/notification_element.tsx (1)
1-47: Consolidate duplicate notification components.This component is nearly identical to
src/components/base-ui/home/notification_element.tsx. Both define the same types (NotificationType,NotificationElementProps), the same logic, and the same rendering. Consider extracting a single sharedNotificationElementcomponent (e.g., in acommon/orshared/folder) and importing it where needed, rather than maintaining two copies.src/components/base-ui/Profile/others_profile.tsx (2)
17-17: Remove unusedonSettingsprop.
onSettingsis declared in the type but never destructured or used in the component.๐ Proposed fix
- onSettings?: () => void;
100-103: Consider guarding optional callback.
onReportClickis optional, but unlikeonToggleSubscribe, it's passed directly toonClick. For consistency and to prevent potential issues, consider using optional chaining.๐ Proposed fix
- onClick={onReportClick} + onClick={() => onReportClick?.()}src/components/base-ui/home/list_subscribe_element.tsx (1)
49-49: Remove redundant color classes.
text-whiteandtext-[color:var(--White,#FFF)]are redundant; keep one for consistency with the design system.๐ Proposed fix
- className="flex px-[17px] py-[8px] justify-center items-center gap-[10px] rounded-[8px] bg-[#9A7A6B] text-white text-[color:var(--White,#FFF)] text-[12px] font-semibold leading-[100%] tracking-[-0.012px] whitespace-nowrap" + className="flex px-[17px] py-[8px] justify-center items-center gap-[10px] rounded-[8px] bg-[color:var(--primary_2,#9A7A6B)] text-[color:var(--White,#FFF)] text-[12px] font-semibold leading-[100%] tracking-[-0.012px] whitespace-nowrap"src/components/base-ui/BookStory/bookstory_text.tsx (3)
20-27: Consider a flicker-free approach for textarea auto-resize.Setting
heightto"0px"forces a reflow and can cause a visible flash as the textarea shrinks momentarily before expanding toscrollHeight. Consider usingheight: "auto"instead or maintaining a minimum height to reduce this flicker.๐ Alternative approach to reduce flicker
useLayoutEffect(() => { const el = textareaRef.current; if (!el) return; - el.style.height = "0px"; // ๋จผ์ ์ค์ฌ์ scrollHeight ์ ํํ ๊ณ์ฐ + el.style.height = "auto"; // Avoids visible shrinking el.style.height = `${el.scrollHeight}px`; }, [detail]);
82-82: Remove redundantrowsattribute.Since the textarea height is dynamically controlled via the
useLayoutEffecthook, therows={6}attribute has no practical effect and can be removed for clarity.๐ Suggested cleanup
<textarea ref={textareaRef} value={detail} onChange={(e) => onChangeDetail(e.target.value)} onKeyDown={handleDetailKeyDown} placeholder="๋ด์ฉ์ ์์ ๋กญ๊ฒ ์ ๋ ฅํด์ฃผ์ธ์." - rows={6} className=" w-full resize-none bg-transparent outline-none text-[color:var(--Gray_7,#2C2C2C)] Subhead_4_1 placeholder:text-[color:var(--Gray_3,#BBB)] whitespace-pre-wrap " />
5-10: Consider usingexport typefor type-only exports.For better tree-shaking and explicit intent, use the
export typesyntax when exporting type definitions.๐ TypeScript best practice
-type BookstoryTextProps = { +export type BookstoryTextProps = { title: string; detail: string; onChangeTitle: (v: string) => void; onChangeDetail: (v: string) => void; };src/components/base-ui/BookStory/bookstory_choosebook.tsx (1)
13-49: Consider simplifying CSS variable syntax for Tailwind v4.The component structure and Next.js Image usage are solid. However, Tailwind CSS v4 introduces a cleaner syntax for CSS variables: you can use
border-(--Subbrown_4)andtext-(--Gray_4)instead ofborder-[color:var(--Subbrown_4)]andtext-[color:var(--Gray_4)]. The current syntax still works but is more verbose than necessary.Optional: Tailwind v4 CSS variable syntax
- <div className={`w-full max-w-[1040px] flex items-center p-[20px] ${className} bg-white border border-[color:var(--Subbrown_4)] rounded-[8px]`}> + <div className={`w-full max-w-[1040px] flex items-center p-[20px] ${className} bg-white border border-(--Subbrown_4) rounded-[8px]`}>- <p className="mt-[12px] text-[color:var(--Gray_4,#8D8D8D)] Body_1_2 line-clamp-4 overflow-hidden"> + <p className="mt-[12px] text-(--Gray_4) Body_1_2 line-clamp-4 overflow-hidden">Note: If you want to keep the fallback color
#8D8D8D, you can define it in your@themedirective or keep the current syntax.src/components/base-ui/Profile/mypage_profile.tsx (3)
38-42: Consider simplifying className concatenation.The array-join pattern for className composition is verbose. Template literals or a utility like
clsx/cnwould be more concise and maintainable.Alternative approaches
Using template literal:
className={`w-[734px] h-[244px] flex flex-col ${className}`}Or with clsx (if available in the project):
className={clsx("w-[734px] h-[244px] flex flex-col", className)}
60-60: Consider extracting hard-coded strings for internationalization.Multiple UI strings are hard-coded in Korean ("๊ตฌ๋ ์ค", "๊ตฌ๋ ์", "ํ๋กํ ํธ์ง", "์ฑ ์ด์ผ๊ธฐ ์ฐ๊ธฐ", "์์ ๋ฌธ์ํ๊ธฐ"). While this may be acceptable for the current scope, consider extracting these strings to support future internationalization or easier text updates.
Also applies to: 66-66, 94-94, 123-123, 138-138
111-139: Consider extracting shared button styles.The two action buttons have identical styling with only content and click handlers differing. Consider extracting to a shared component or constant, or leveraging the
ButtonWithoutImgcomponent mentioned in the PR description.Example refactor
const actionButtonClass = ` flex w-[355px] h-[48px] px-[16px] py-[12px] justify-center items-center gap-[10px] rounded-[8px] bg-[color:var(--Primary_1,#7B6154)] text-[color:var(--White,#FFF)] Subhead_4_1 whitespace-nowrap `; // Then use: <button onClick={onLeftButtonClick} className={actionButtonClass}> ์ฑ ์ด์ผ๊ธฐ ์ฐ๊ธฐ </button>src/components/base-ui/News/recommendbook_element.tsx (1)
5-15: Consider exporting the BookCoverCardProps type.The
BookCoverCardPropstype is not currently exported. If other components or tests need to reference this type externally, consider addingexportbeforetype.๐ Proposed fix to export the type
-type BookCoverCardProps = { +export type BookCoverCardProps = {src/components/base-ui/BookStory/bookstory_detail.tsx (1)
7-24: Consider exporting the BookstoryDetailProps type.Similar to the News component, the
BookstoryDetailPropstype is not exported. If external components or tests need to reference this type, consider adding theexportkeyword.๐ Proposed fix to export the type
-type BookstoryDetailProps = { +export type BookstoryDetailProps = {src/app/globals.css (1)
70-70: Consider separating truncate from Body_1.The
Body_1utility includestruncate, which forces all text using this class to be truncated. This may not be desirable in all use cases. Consider creating a separate variant (e.g.,Body_1_truncate) or removingtruncatefrom the base utility to allow more flexible usage.๐ Proposed refactor
/* Body */ - .Body_1 { @apply text-[14px] font-semibold leading-[145%] tracking-[-0.014px] truncate; } + .Body_1 { @apply text-[14px] font-semibold leading-[145%] tracking-[-0.014px]; } .Body_1_1 { @apply text-[14px] font-semibold leading-[145%] tracking-[-0.014px]; }This aligns
Body_1with the naming pattern of other variants (Body_1_1,Body_1_2, etc.) whereBody_1would be the base and you can add truncate inline where needed:Body_1 truncate.src/app/(main)/page.tsx (1)
1-3: Placeholder implementation detected.The home page currently renders an empty div. Based on the PR objectives mentioning home UI components (home_bookclub, list_subscribe_element, notification_element), this page should eventually integrate those components to display the actual home page content.
Would you like me to open an issue to track the integration of home UI components into this page?
src/components/layout/NavItem.tsx (1)
13-16: Consider using a className utility for cleaner conditional styling.The array
.join(" ")pattern works but is verbose. Consider usingclsxor acnutility function for more maintainable conditional className composition.๐ Refactor using clsx utility
First, install clsx if not already present:
npm install clsxThen refactor the component:
import Link from "next/link"; +import clsx from "clsx"; interface NavItemProps { href: string; label: string; active: boolean; } export function NavItem({ href, label, active }: NavItemProps) { return ( <Link href={href} - className={[ - "flex w-32 items-center justify-center gap-2.5 p-2.5", - active ? "border-b-2 border-white" : "border-b-2 border-transparent", - ].join(" ")} + className={clsx( + "flex w-32 items-center justify-center gap-2.5 p-2.5", + active ? "border-b-2 border-white" : "border-b-2 border-transparent" + )} > <span - className={[ - "text-center text-xl font-semibold leading-7", - active ? "text-white" : "text-gray-200", - ].join(" ")} + className={clsx( + "text-center text-xl font-semibold leading-7", + active ? "text-white" : "text-gray-200" + )} > {label} </span> </Link> ); }Also applies to: 19-22
src/components/base-ui/button_without_img.tsx (1)
52-77: Consider using CSS :hover instead of manual state.The manual hover state management with
useStatecauses re-renders on every mouse enter/leave event. Since you're already usingtransition-colors, you could simplify this with pure CSS using the:hoverpseudo-class and CSS variables.๐ Alternative CSS-only hover approach
export default function ButtonWithoutImg({ text, onClick, bgColorVar = "--primary_2", borderColorVar = "--primary_2", textColorVar = "--White", hoverBgColorVar, hoverBorderColorVar, hoverTextColorVar, width = 132, height = 44, disabled = false, type = "button", className = "", }: ButtonWithoutImgProps) { - const [isHover, setIsHover] = useState(false); - - const bg = toCssColor(isHover && hoverBgColorVar ? hoverBgColorVar : bgColorVar); - const border = toCssColor(isHover && hoverBorderColorVar ? hoverBorderColorVar : borderColorVar); - const textColor = toCssColor(isHover && hoverTextColorVar ? hoverTextColorVar : textColorVar); + const bg = toCssColor(bgColorVar); + const border = toCssColor(borderColorVar); + const textColor = toCssColor(textColorVar); + + const hoverBg = hoverBgColorVar ? toCssColor(hoverBgColorVar) : undefined; + const hoverBorder = hoverBorderColorVar ? toCssColor(hoverBorderColorVar) : undefined; + const hoverText = hoverTextColorVar ? toCssColor(hoverTextColorVar) : undefined; return ( <button type={type} disabled={disabled} onClick={disabled ? undefined : onClick} - onMouseEnter={disabled ? undefined : () => setIsHover(true)} - onMouseLeave={disabled ? undefined : () => setIsHover(false)} style={{ + '--bg-color': bg, + '--border-color': border, + '--text-color': textColor, + '--hover-bg-color': hoverBg || bg, + '--hover-border-color': hoverBorder || border, + '--hover-text-color': hoverText || textColor, width, height, - backgroundColor: bg, - borderColor: border, - color: textColor, - }} + } as React.CSSProperties} className={[ "flex px-[16px] py-[12px] justify-center items-center gap-[10px]", "rounded-[8px] border", "Body_1_2 whitespace-nowrap", + "[background-color:var(--bg-color)] [border-color:var(--border-color)] [color:var(--text-color)]", + "hover:[background-color:var(--hover-bg-color)] hover:[border-color:var(--hover-border-color)] hover:[color:var(--hover-text-color)]", "transition-colors", disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer", className, ].join(" ")} > {text} </button> ); }src/components/base-ui/Settings/setting_report_list.tsx (2)
22-28: Consider responsive width instead of fixed pixel width.The fixed
w-[1000px]will cause horizontal overflow on smaller screens. Consider usingw-full max-w-[1000px]to allow the component to adapt to narrower viewports.๐ Proposed fix
<div className={` - flex w-[1000px] p-[20px] items-start gap-[40px] + flex w-full max-w-[1000px] p-[20px] items-start gap-[40px] rounded-[8px] border border-[color:var(--Subbrown_4,#EAE5E2)] bg-[color:var(--White,#FFF)] ${className} `} >
46-46: Consider adding an avatar URL prop.The hard-coded
/profile5.svgavatar limits flexibility. Consider adding an optionalavatarUrlprop to allow customization per reporter.๐ Proposed enhancement
Update the props type:
type SettingReportListProps = { badgeText: string; reporterName: string; reportedAt: string; content: string; + avatarUrl?: string; className?: string; };Update the component:
export default function Setting_ReportList({ badgeText, reporterName, reportedAt, content, + avatarUrl = "/profile5.svg", className = "", }: SettingReportListProps) { // ... - <Image src="/profile5.svg" alt="" width={24} height={24} /> + <Image src={avatarUrl} alt="" width={24} height={24} />src/components/base-ui/Search/search_recommendbook.tsx (2)
5-15: Consider exporting the type for better reusability.The
BookCoverCardPropstype is well-structured. However, exporting it would allow parent components, tests, or documentation to reference the type explicitly, improving type safety and developer experience.๐ Optional: Export the type
-type BookCoverCardProps = { +export type BookCoverCardProps = { imgUrl?: string; title: string; author: string; liked: boolean; onLikeChange: (next: boolean) => void; onCardClick?: () => void; className?: string; };
38-47: Consider adding an accessible label to the like button.The like button functions correctly with proper event propagation handling. However, it lacks an
aria-labelor accessible text, which would improve screen reader support.๐ Optional: Add aria-label for accessibility
<button type="button" + aria-label={liked ? "Unlike this book" : "Like this book"} onClick={(e) => { e.stopPropagation(); onLikeChange(!liked); }} className="w-[24px] h-[24px] shrink-0" > <Image src={liked ? "/red_heart.svg" : "/gray_heart.svg"} alt="" width={24} height={24} /> </button>
๐ Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
โ Files ignored due to path filters (20)
package-lock.jsonis excluded by!**/package-lock.jsonpublic/ArrowDown.svgis excluded by!**/*.svgpublic/ArrowTop.svgis excluded by!**/*.svgpublic/Edit_icon.svgis excluded by!**/*.svgpublic/Setting_icon.svgis excluded by!**/*.svgpublic/booksample.svgis excluded by!**/*.svgpublic/gray_heart.svgis excluded by!**/*.svgpublic/icon_plus.svgis excluded by!**/*.svgpublic/logo.svgis excluded by!**/*.svgpublic/logo2.svgis excluded by!**/*.svgpublic/notification.svgis excluded by!**/*.svgpublic/pencil_icon.svgis excluded by!**/*.svgpublic/plus.svgis excluded by!**/*.svgpublic/profile.svgis excluded by!**/*.svgpublic/profile2.svgis excluded by!**/*.svgpublic/profile3.svgis excluded by!**/*.svgpublic/profile4.svgis excluded by!**/*.svgpublic/profile5.svgis excluded by!**/*.svgpublic/red_heart.svgis excluded by!**/*.svgpublic/search.svgis excluded by!**/*.svg
๐ Files selected for processing (27)
.github/ISSUE_TEMPLATE/custom.mdsrc/app/(main)/layout.tsxsrc/app/(main)/page.tsxsrc/app/(main)/ui-test/page.tsxsrc/app/globals.csssrc/app/layout.tsxsrc/app/page.backup.tsxsrc/components/base-ui/BookStory/bookstory_choosebook.tsxsrc/components/base-ui/BookStory/bookstory_detail.tsxsrc/components/base-ui/BookStory/bookstory_text.tsxsrc/components/base-ui/News/news_list.tsxsrc/components/base-ui/News/recommendbook_element.tsxsrc/components/base-ui/Profile/mypage_profile.tsxsrc/components/base-ui/Profile/notification_element.tsxsrc/components/base-ui/Profile/others_profile.tsxsrc/components/base-ui/Profile/subscribe_element.tsxsrc/components/base-ui/Search/search_bookresult.tsxsrc/components/base-ui/Search/search_recommendbook.tsxsrc/components/base-ui/Settings/setting_news_list.tsxsrc/components/base-ui/Settings/setting_report_list.tsxsrc/components/base-ui/button_without_img.tsxsrc/components/base-ui/home/home_bookclub.tsxsrc/components/base-ui/home/list_subscribe_element.tsxsrc/components/base-ui/home/notification_element.tsxsrc/components/layout/Header.tsxsrc/components/layout/NavItem.tsxtsconfig.json
๐ค Files with no reviewable changes (1)
- src/app/layout.tsx
๐งฐ Additional context used
๐งฌ Code graph analysis (3)
src/app/(main)/layout.tsx (1)
src/components/layout/Header.tsx (1)
Header(15-97)
src/components/layout/Header.tsx (1)
src/components/layout/NavItem.tsx (1)
NavItem(9-28)
src/app/(main)/ui-test/page.tsx (1)
src/components/base-ui/Settings/setting_report_list.tsx (1)
Setting_ReportList(14-65)
๐ Additional comments (28)
src/components/base-ui/Profile/subscribe_element.tsx (1)
1-55: LGTM!The component is well-structured with proper TypeScript types, safe optional callback invocation via
onToggleSubscribe?.(!isSubscribed), and correct usage of Next.jsImagewithfillandsizes. The conditional button styling based on subscription state is clear.src/components/base-ui/Profile/others_profile.tsx (1)
6-118: LGTM overall!The component structure is clean with proper TypeScript typing, correct Next.js
Imageusage withfillandsizes, and well-organized layout. The conditional styling for the subscribe button based onisSubscribedstate is well-implemented.src/components/base-ui/home/list_subscribe_element.tsx (1)
1-55: LGTM overall!The component is well-structured with proper TypeScript types and correct Next.js
Imageusage. The layout and styling are consistent with other subscribe-related components in the PR.src/components/base-ui/BookStory/bookstory_choosebook.tsx (3)
1-2: LGTM!Imports are correct. The explicit React import is harmless and works fine with React 19's JSX transform.
4-11: LGTM!The type definition is well-structured with appropriate field types and optional props for extensibility.
70-75: LGTM!JSX structure is correctly balanced with all opening and closing tags properly matched.
.github/ISSUE_TEMPLATE/custom.md (1)
5-27: LGTM!The issue template improvements add helpful guidance text and a new issue type option, making the template more user-friendly.
tsconfig.json (1)
38-39: LGTM!The additions of
.next/types/**/*.tsand.next/dev/types/**/*.tsproperly support Next.js 16's generated type declarations, ensuring full TypeScript coverage for the framework-generated types.src/components/base-ui/News/recommendbook_element.tsx (1)
26-56: LGTM!The component implementation follows Next.js best practices:
- Proper default fallback for missing images
- Correct use of
fillwith explicitsizesfor optimization- Event propagation correctly managed for nested click handlers
- Text overflow handled appropriately with truncate and min-w-0
src/components/base-ui/BookStory/bookstory_detail.tsx (1)
40-107: LGTM!The component follows Next.js and React best practices:
- Proper default values for optional props
- Correct Image usage with explicit parent dimensions and sizes
- Meaningful alt attributes for accessibility
- Proper text truncation with flex layout (min-w-0)
- Link component used appropriately for navigation
src/app/globals.css (2)
4-33: LGTM!The design token structure is well-organized with a comprehensive color palette. The custom property naming convention (using underscores) is consistent throughout the codebase and properly referenced by components.
52-52: LGTM!The font family update to Pretendard with proper fallbacks provides excellent Korean typography support while maintaining system font fallbacks.
src/components/layout/NavItem.tsx (1)
1-7: LGTM!The interface definition is clear and includes all necessary props for a navigation item component.
src/app/(main)/layout.tsx (1)
1-11: LGTM!The layout implementation is clean and follows Next.js App Router conventions. It properly integrates the Header component and wraps children in a semantic
<main>element.src/app/(main)/ui-test/page.tsx (1)
10-18: LGTM!The test page correctly demonstrates the
Setting_ReportListcomponent with intentionally long content to verify text wrapping and overflow behavior.src/components/layout/Header.tsx (4)
1-7: LGTM!The imports are appropriate, and the
"use client"directive is correctly placed since the component uses theusePathnamehook.
8-13: LGTM!The navigation structure is well-defined with clear labels and corresponding routes.
36-39: Active state logic works but has a potential edge case.The current logic uses
pathname.startsWith(item.href)for non-root routes. This could cause issues if you add nested or similarly-named routes in the future (e.g.,/groupsand/groups-adminwould both match when visiting/groups-admin).Consider whether you need more precise matching in the future. For now, this works with the current route structure.
24-91: All required image assets are present in the public directory (logo.svg,search.svg,notification.svg,profile.svg). No 404 errors will occur from these assets.src/components/base-ui/button_without_img.tsx (2)
25-31: LGTM: Color normalization helper.The
toCssColorhelper correctly handles multiple color formats (CSS variables,--prefixes, and raw values).
33-51: LGTM: Well-structured component props.The component signature is clear, type-safe, and provides sensible defaults for colors and dimensions.
src/components/base-ui/Search/search_bookresult.tsx (3)
44-45: Verify remotePatterns for external book cover images.The
imgUrlprop can contain external URLs. Ensure yournext.config.jsincludes appropriateremotePatternsfor book cover image sources (e.g., book API domains).
35-43: LGTM: Card click handling.The optional
onCardClickhandler and conditional cursor styling are implemented correctly.
61-91: LGTM: Button event handling with stopPropagation.The like and pencil buttons correctly use
stopPropagation()to prevent triggering the card'sonCardClickhandler. The optionalonPencilClickis safely handled with optional chaining.src/components/base-ui/Settings/setting_report_list.tsx (1)
14-20: LGTM: Clear component props definition.The props are well-documented with inline comments showing expected formats, and the default className is handled appropriately.
src/components/base-ui/Search/search_recommendbook.tsx (3)
1-4: LGTM!Correct setup for a client-side component with Next.js Image.
17-26: LGTM!Component signature and fallback logic are correct. The coverSrc resolution properly handles missing or empty imgUrl values.
49-52: LGTM!Text content rendering correctly follows the established CSS conventions (color tokens and typography classes) and includes proper overflow handling with truncate.
| "use client"; | ||
| import React from "react"; | ||
| import { useState } from "react"; | ||
| import Subscribe_elements from "@/components/base-ui/Profile/subscribe_element"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
๐ ๏ธ Refactor suggestion | ๐ Major
Remove unused import and state.
The Subscribe_elements import and the subs state variable are declared but never used in the component.
๐ Remove unused code
"use client";
import React from "react";
-import { useState } from "react";
-import Subscribe_elements from "@/components/base-ui/Profile/subscribe_element";
import Setting_ReportList from "@/components/base-ui/Settings/setting_report_list";
export default function UiTestClient() {
- const [subs, setSubs] = useState(false);
-
return (
<div className="h-[2000px] bg-gray-100 p-8">If you plan to use these later for testing Subscribe_elements, keep them and add a comment explaining the future intent.
Also applies to: 8-8
๐ค Prompt for AI Agents
In src/app/(main)/ui-test/page.tsx around lines 4 and 8, the import
Subscribe_elements and the subs state variable are declared but unused; remove
the unused import line and the subs state declaration (or, if you intend to use
them later, keep both and add a clear comment explaining the future intent),
then run TypeScript/ESLint to ensure no remaining unused-symbol errors.
| .Headline_1 { @apply text-[48px] font-bold leading-[135%] tracking-[-0.1%]; } | ||
| .Headline_2 { @apply text-[36px] font-bold leading-[135%] tracking-[-0.1%]; } | ||
| .Headline_3 { @apply text-[32px] font-bold leading-[135%] tracking-[-0.1%]; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Invalid tracking (letter-spacing) percentage values.
Lines 57-59 and 62-67 use tracking-[-0.1%], but the CSS letter-spacing property does not accept percentage valuesโonly length units (px, em, rem, etc.) are valid. These declarations will be ignored by browsers, causing the intended letter-spacing to not apply.
๐ Proposed fix
The value -0.1% likely intends -0.001em (which is roughly 0.1% of the font size). Update all instances:
/* Headline */
- .Headline_1 { @apply text-[48px] font-bold leading-[135%] tracking-[-0.1%]; }
- .Headline_2 { @apply text-[36px] font-bold leading-[135%] tracking-[-0.1%]; }
- .Headline_3 { @apply text-[32px] font-bold leading-[135%] tracking-[-0.1%]; }
+ .Headline_1 { @apply text-[48px] font-bold leading-[135%] tracking-[-0.001em]; }
+ .Headline_2 { @apply text-[36px] font-bold leading-[135%] tracking-[-0.001em]; }
+ .Headline_3 { @apply text-[32px] font-bold leading-[135%] tracking-[-0.001em]; }
/* Subhead */
- .Subhead_1 { @apply text-[24px] font-semibold leading-[135%] tracking-[-0.1%]; }
- .Subhead_2 { @apply text-[20px] font-semibold leading-[135%] tracking-[-0.1%]; }
- .Subhead_3_1 { @apply text-[18px] font-semibold leading-[135%] tracking-[-0.1%]; }
- .Subhead_3_2 { @apply text-[18px] font-medium leading-[135%] tracking-[-0.1%]; }
+ .Subhead_1 { @apply text-[24px] font-semibold leading-[135%] tracking-[-0.001em]; }
+ .Subhead_2 { @apply text-[20px] font-semibold leading-[135%] tracking-[-0.001em]; }
+ .Subhead_3_1 { @apply text-[18px] font-semibold leading-[135%] tracking-[-0.001em]; }
+ .Subhead_3_2 { @apply text-[18px] font-medium leading-[135%] tracking-[-0.001em]; }Alternatively, verify the intended value from your design specifications and use the correct length unit.
Also applies to: 62-67
๐ค Prompt for AI Agents
In src/app/globals.css around lines 57-59 (and also lines 62-67), the classes
use tracking-[-0.1%], but letter-spacing does not accept percentage values;
replace each tracking-[-0.1%] with a proper length unit (e.g.,
tracking-[-0.001em] or tracking-[-0.1px] depending on design) so the rule is
applied, and update all instances across the file; verify with the design spec
and adjust the chosen unit/value accordingly.
| <button | ||
| type="button" | ||
| onClick={onButtonClick} | ||
| className=" | ||
| flex w-[132px] h-[44px] | ||
| px-[16px] py-[12px] | ||
| justify-center items-center gap-[10px] | ||
| rounded-[8px] | ||
| border border-[color:var(--premary_2,#9A7A6B)] | ||
| bg-[color:var(--background,#F9F7F6)] | ||
| text-[color:var(--premary_2,#9A7A6B)] | ||
| Body_1_2 | ||
| whitespace-nowrap | ||
| " | ||
| > | ||
| ๋ณ๊ฒฝํ๊ธฐ | ||
| </button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo in CSS variable name: premary โ primary.
The button has a typo in the CSS variable name on lines 61 and 63: --premary_2 should be --primary_2. This will cause the variable lookup to fail and fall back to the hardcoded hex color, breaking design system consistency and potentially causing styling issues if the variable is later defined correctly elsewhere.
๐ Proposed fix for the CSS variable typo
className="
flex w-[132px] h-[44px]
px-[16px] py-[12px]
justify-center items-center gap-[10px]
rounded-[8px]
- border border-[color:var(--premary_2,#9A7A6B)]
+ border border-[color:var(--primary_2,#9A7A6B)]
bg-[color:var(--background,#F9F7F6)]
- text-[color:var(--premary_2,#9A7A6B)]
+ text-[color:var(--primary_2,#9A7A6B)]
Body_1_2
whitespace-nowrap
"๐ 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.
| <button | |
| type="button" | |
| onClick={onButtonClick} | |
| className=" | |
| flex w-[132px] h-[44px] | |
| px-[16px] py-[12px] | |
| justify-center items-center gap-[10px] | |
| rounded-[8px] | |
| border border-[color:var(--premary_2,#9A7A6B)] | |
| bg-[color:var(--background,#F9F7F6)] | |
| text-[color:var(--premary_2,#9A7A6B)] | |
| Body_1_2 | |
| whitespace-nowrap | |
| " | |
| > | |
| ๋ณ๊ฒฝํ๊ธฐ | |
| </button> | |
| <button | |
| type="button" | |
| onClick={onButtonClick} | |
| className=" | |
| flex w-[132px] h-[44px] | |
| px-[16px] py-[12px] | |
| justify-center items-center gap-[10px] | |
| rounded-[8px] | |
| border border-[color:var(--primary_2,#9A7A6B)] | |
| bg-[color:var(--background,#F9F7F6)] | |
| text-[color:var(--primary_2,#9A7A6B)] | |
| Body_1_2 | |
| whitespace-nowrap | |
| " | |
| > | |
| ๋ณ๊ฒฝํ๊ธฐ | |
| </button> |
๐ค Prompt for AI Agents
In src/components/base-ui/BookStory/bookstory_choosebook.tsx around lines 53 to
69, the button's CSS variable name contains a typo: replace all occurrences of
--premary_2 with --primary_2 (both in the border and text color usages) so the
component uses the correct design-system variable; update the className strings
accordingly and ensure no other instances of the misspelled variable remain in
the file.
| const handleDetailKeyDown = useCallback( | ||
| (e: React.KeyboardEvent<HTMLTextAreaElement>) => { | ||
| if (e.key !== "Tab") return; | ||
|
|
||
| e.preventDefault(); | ||
|
|
||
| const el = e.currentTarget; | ||
| const start = el.selectionStart ?? 0; | ||
| const end = el.selectionEnd ?? 0; | ||
|
|
||
| const insert = " "; | ||
| const next = detail.slice(0, start) + insert + detail.slice(end); | ||
|
|
||
| onChangeDetail(next); | ||
|
|
||
| requestAnimationFrame(() => { | ||
| el.selectionStart = el.selectionEnd = start + insert.length; | ||
| }); | ||
| }, | ||
| [detail, onChangeDetail] | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tab key handling with controlled input may be unreliable.
Using requestAnimationFrame to restore cursor position after calling onChangeDetail is fragile. When onChangeDetail updates parent state, React re-renders this component and updates the textarea value, which can reset the cursor position unpredictablyโpotentially before or after your requestAnimationFrame callback runs.
A more robust approach is to track the desired cursor position in a ref and apply it in useLayoutEffect after the detail value changes.
๐ More reliable implementation
const textareaRef = useRef<HTMLTextAreaElement | null>(null);
+ const cursorPosRef = useRef<number | null>(null);
// โ
๋ด์ฉ์ ๋ง์ถฐ textarea ๋์ด ์๋ ์กฐ์
useLayoutEffect(() => {
const el = textareaRef.current;
if (!el) return;
el.style.height = "0px";
el.style.height = `${el.scrollHeight}px`;
+
+ // Restore cursor position if pending
+ if (cursorPosRef.current !== null) {
+ el.selectionStart = el.selectionEnd = cursorPosRef.current;
+ cursorPosRef.current = null;
+ }
}, [detail]);
// textarea์์ Tab์ "๋ค์ฌ์ฐ๊ธฐ"๋ก ์ฒ๋ฆฌ
const handleDetailKeyDown = useCallback(
(e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key !== "Tab") return;
e.preventDefault();
const el = e.currentTarget;
const start = el.selectionStart ?? 0;
const end = el.selectionEnd ?? 0;
const insert = " ";
const next = detail.slice(0, start) + insert + detail.slice(end);
+ // Store desired cursor position
+ cursorPosRef.current = start + insert.length;
onChangeDetail(next);
-
- requestAnimationFrame(() => {
- el.selectionStart = el.selectionEnd = start + insert.length;
- });
},
[detail, onChangeDetail]
);Committable suggestion skipped: line range outside the PR's diff.
๐ค Prompt for AI Agents
In src/components/base-ui/BookStory/bookstory_text.tsx around lines 30-50, the
Tab key handler uses requestAnimationFrame to restore the textarea cursor which
is fragile with controlled inputs; instead, store the desired cursor position in
a ref inside the handler (set a ref to start + insert.length), call
onChangeDetail as before, remove the requestAnimationFrame, and then in a
useLayoutEffect that watches the detail value, if the ref has a stored position
set the textarea selectionStart/selectionEnd to that value and clear the ref;
ensure the textarea element is referenced via a ref accessible to
useLayoutEffect and keep dependencies minimal to avoid extra renders.
| "use client"; | ||
|
|
||
| import React from "react"; | ||
| import Image from "next/image"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
๐งฉ Analysis chain
๐ Script executed:
find . -maxdepth 2 -name "package.json" -type f | head -5Repository: checkmo2025/FE
Length of output: 72
๐ Script executed:
cat package.json | grep -A 5 '"dependencies"' | head -20Repository: checkmo2025/FE
Length of output: 176
๐ Script executed:
cat -n src/components/base-ui/Profile/mypage_profile.tsx | head -50Repository: checkmo2025/FE
Length of output: 1511
๐ Web query:
Next.js 16.0.1 release date features compatibility
๐ก Result:
-
Release date: Next.js 16.0.1 was published in late October 2025 (stable 16.0.1 listed 2025-10-28). [1][2]
-
Notable features / highlights in the Next.js 16.x line (present in 16.0.x):
- Cache Components / "use cache" + Partial Pre-Rendering improvements. [3]
- Turbopack stable and default bundler (big dev/build perf gains). [3]
- React upgrades (React 19.x integration and related new APIs). [3]
- Routing, caching API updates (new refresh/updateTag/revalidateTag semantics) and Build Adapters API (alpha). [3]
- Several breaking changes (async route params, image defaults, changes to App Router behavior). [3]
-
Compatibility / ecosystem notes:
- Many ecosystem packages needed updates for Next 16; some libraries (auth SDKs, adapters, etc.) reported peer-dependency conflicts with [email protected] โ expect to need updated versions or to use --legacy-peer-deps temporarily. [2][4]
- Several security vulnerabilities affecting early 16.x releases were disclosed in Dec 2025; upgrading to later 16.x security patches (e.g., 16.0.7+ / 16.1.x) was recommended. If you run 16.0.1, check for patched 16.x releases. [5][1]
If you want, I can: (a) fetch the exact GitHub/npm release entries for v16.0.1, (b) list breaking-change upgrade steps, or (c) check a specific thirdโparty package for Next 16 compatibility.
๐ Web query:
React 19.2.0 release date stability
๐ก Result:
React 19.2.0 (stable) was released October 1, 2025. [1]
Notes on stability:
- The React team published 19.2 as a stable release on the official React blog. [1]
- Prior to the stable release there were multiple 19.2.0-canary builds published to npm (canary = prerelease). Use the stable tag ([email protected]) from the official release rather than canary builds for production. [2][3][4]
Upgrade Next.js from 16.0.1 to 16.0.7 or later due to security vulnerabilities.
React 19.2.0 is stable and all features used ("use client" directive, Image component with fill prop, React patterns) are fully supported in these versions. However, Next.js 16.0.1 has known security vulnerabilities disclosed in December 2025. Upgrade to Next.js 16.0.7 or 16.1.x to receive security patches. Also verify that ecosystem dependencies (auth SDKs, adapters, etc.) are compatible with Next.js 16, as some packages reported peer-dependency conflicts requiring --legacy-peer-deps or updated versions.
๐ค Prompt for AI Agents
In src/components/base-ui/Profile/mypage_profile.tsx (lines 1-4): the project is
using Next.js 16.0.1 which has known security vulnerabilities; update the
Next.js dependency in package.json to 16.0.7 or a later 16.x (or 16.1.x) safe
release, run a fresh install to update the lockfile (npm/yarn/pnpm), resolve or
update any peer-dependency conflicts for auth SDKs/adapters (upgrade those
packages or use appropriate install flags only as a last resort), run the test
suite and a local build to catch runtime/API changes, and commit the updated
package.json and lockfile once compatibility is confirmed.
| <div className="flex items-start"> | ||
| <div className="py-[9px] pr-[36px] shrink-0"> | ||
| <div className="relative w-[138px] h-[138px] overflow-hidden rounded-full"> | ||
| <Image src={profileImgSrc} alt={name} fill className="object-cover" sizes="138px" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
๐งฉ Analysis chain
๐ Script executed:
#!/bin/bash
# First, check for the existence of image assets referenced in the component
echo "=== Checking for image assets in public directory ==="
for asset in profile3.svg Edit_icon.svg setting_icon.svg; do
if fd -t f "^${asset}$" public 2>/dev/null; then
echo "โ Found: $asset"
else
echo "โ Missing: $asset"
fi
done
# Also check what files exist in the public directory for reference
echo ""
echo "=== All files in public directory ==="
fd -t f . public 2>/dev/null | head -20Repository: checkmo2025/FE
Length of output: 681
๐ Script executed:
#!/bin/bash
# Inspect the file at the specified lines to see what images are referenced
echo "=== Checking lines 47, 92, 101 in mypage_profile.tsx ==="
sed -n '45,49p; 90,94p; 99,103p' src/components/base-ui/Profile/mypage_profile.tsxRepository: checkmo2025/FE
Length of output: 843
Fix filename case mismatch at line 101.
The image reference at line 101 uses /setting_icon.svg (lowercase), but the actual file in the public directory is Setting_icon.svg (capital S). On case-sensitive filesystems, this will cause the image to fail loading. Update the reference to /Setting_icon.svg to match the actual filename.
Line 92's reference to /Edit_icon.svg is correct. Line 47 uses a dynamic source variable and does not directly reference a static asset.
๐ค Prompt for AI Agents
In src/components/base-ui/Profile/mypage_profile.tsx around line 101, the image
src references "/setting_icon.svg" which mismatches the actual public file
"Setting_icon.svg" (capital S); update the import string to "/Setting_icon.svg"
so the filename case matches exactly on case-sensitive filesystems and leave the
"/Edit_icon.svg" and dynamic profile image usage unchanged.
| <div className="flex-1 min-w-0"> | ||
| <div className="flex items-start justify-between"> | ||
| <div className="min-w-0"> | ||
| <p className="text-[color:var(--Gray_7,#2C2C2C)] Subhead_1 truncate">{name}</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
๐งฉ Analysis chain
๐ Script executed:
#!/bin/bash
# First, let's look for CSS/SCSS files and check for these class definitions
echo "=== Searching for custom typography class definitions ==="
rg -t css -t scss "Subhead_1|Subhead_4_1|Subhead_4|Body_1_2" --no-heading -C 1
echo ""
echo "=== Checking for Tailwind config or alternative CSS approach ==="
fd -t f -e "\.config\." -e "globals\." -e "tailwind\." | head -20Repository: checkmo2025/FE
Length of output: 227
๐ Script executed:
#!/bin/bash
# Let's examine the target file to see the usage pattern
echo "=== Examining mypage_profile.tsx ==="
head -100 src/components/base-ui/Profile/mypage_profile.tsx | tail -50
echo ""
echo "=== Checking specific lines (54, 59, 65, 75, 93) ==="
sed -n '54p;59p;65p;75p;93p' src/components/base-ui/Profile/mypage_profile.tsxRepository: checkmo2025/FE
Length of output: 2541
๐ Script executed:
#!/bin/bash
# Search for where these classes might be defined more broadly
echo "=== Searching all files for class definitions ==="
rg "Subhead_1|Subhead_4_1|Subhead_4|Body_1_2" --no-heading -l | head -20Repository: checkmo2025/FE
Length of output: 958
๐ Script executed:
#!/bin/bash
# Check the globals.css file
echo "=== Checking src/app/globals.css ==="
cat src/app/globals.cssRepository: checkmo2025/FE
Length of output: 2654
Add missing .Subhead_4 typography class definition.
Three custom typography classes are properly defined in src/app/globals.css (Subhead_1, Subhead_4_1, Body_1_2), but .Subhead_4 is missing. This class is used at line 93 but has no corresponding definition in the utilities layer. Add the definition to globals.css or replace with an existing class like Subhead_4_1.
๐ค Prompt for AI Agents
In src/components/base-ui/Profile/mypage_profile.tsx around line 54 (and note
.Subhead_4 is used at line 93), the component references a non-existent
.Subhead_4 typography class; add a .Subhead_4 rule to src/app/globals.css in the
utilities layer (mirroring the existing Subhead_4_1 styles) or replace the usage
in mypage_profile.tsx with the existing Subhead_4_1 class to restore consistent
typography.
| <button type="button" onClick={onSettings} className="w-[24px] h-[24px] "> | ||
| <Image src="/setting_icon.svg" alt="" width={24} height={24} className="" /> | ||
| </button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add accessible label to icon-only settings button.
The settings button contains only an icon with no text label or aria-label, making it inaccessible to screen reader users. Add an aria-label attribute to describe the button's purpose.
๐ Add aria-label
- <button type="button" onClick={onSettings} className="w-[24px] h-[24px] ">
+ <button type="button" onClick={onSettings} aria-label="์ค์ ์ด๊ธฐ" className="w-[24px] h-[24px] ">
<Image src="/setting_icon.svg" alt="" width={24} height={24} className="" />
</button>๐ 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.
| <button type="button" onClick={onSettings} className="w-[24px] h-[24px] "> | |
| <Image src="/setting_icon.svg" alt="" width={24} height={24} className="" /> | |
| </button> | |
| <button type="button" onClick={onSettings} aria-label="์ค์ ์ด๊ธฐ" className="w-[24px] h-[24px] "> | |
| <Image src="/setting_icon.svg" alt="" width={24} height={24} className="" /> | |
| </button> |
๐ค Prompt for AI Agents
In src/components/base-ui/Profile/mypage_profile.tsx around lines 100 to 102,
the settings button is icon-only and lacks an accessible name; add an aria-label
(e.g., aria-label="Open settings" or a localized equivalent) to the <button> so
screen readers can describe its purpose, ensuring the attribute is concise and
matches the button's action.
| "use client"; | ||
| import Image from "next/image"; | ||
|
|
||
| type NewsListProps = { | ||
| imageUrl: string; | ||
| title: string; | ||
| content: string; | ||
| date: string; // "2025-10-09" ๊ฐ์ ๋ฌธ์์ด | ||
| className?: string; | ||
| }; | ||
|
|
||
| export default function Setting_NewsList({ | ||
| imageUrl, | ||
| title, | ||
| content, | ||
| date, | ||
| className = "", | ||
| }: NewsListProps) { | ||
| return ( | ||
| <div | ||
| className={[ | ||
| "inline-flex w-full max-w-[1000px] p-[20px] items-start", | ||
| "rounded-[8px] border border-[color:var(--Subbrown_4,#EAE5E2)] bg-white gap-6", | ||
| className, | ||
| ].join(" ")} | ||
| > | ||
| {/* left image */} | ||
| <div className="relative w-[100px] h-[145px] shrink-0 "> | ||
| <Image | ||
| src={imageUrl} | ||
| alt={title} | ||
| fill | ||
| sizes="100px" | ||
| className="object-cover" | ||
| /> | ||
| </div> | ||
|
|
||
| {/* middle + right */} | ||
| <div className="flex flex-1 min-w-0 items-start"> | ||
| {/* middle text */} | ||
| <div className="flex flex-col gap-[8px] min-w-0 flex-1"> | ||
| <p className="text-[#000] Subhead_3 truncate">{title}</p> | ||
| <p className="text-[color:var(--Gray_4,#8D8D8D)] Body_1_2 line-clamp-6"> | ||
| {content} | ||
| </p> | ||
| </div> | ||
|
|
||
| {/* ์ต์ 120px ํ๋ณด + ๋ ์ง ์ค๋ฅธ์ชฝ ๊ณ ์ */} | ||
| <div className="shrink-0 min-w-[180px] text-right"> | ||
| <p className="text-[color:var(--Gray_3,#BBB)] Body_1_2">{date}</p> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
๐ ๏ธ Refactor suggestion | ๐ Major
Extract shared component to eliminate duplication.
This component is nearly identical to src/components/base-ui/News/news_list.tsx, differing only in max-w-[1000px] vs max-w-[1040px]. Consider extracting a shared base component that accepts maxWidth as a prop, then wrap it in domain-specific exports.
๐ Proposed refactor to extract shared component
Create a new shared component:
// src/components/base-ui/shared/BaseNewsList.tsx
"use client";
import Image from "next/image";
type BaseNewsListProps = {
imageUrl: string;
title: string;
content: string;
date: string;
maxWidth?: string;
className?: string;
};
export default function BaseNewsList({
imageUrl,
title,
content,
date,
maxWidth = "1040px",
className = "",
}: BaseNewsListProps) {
return (
<div
className={[
`inline-flex w-full max-w-[${maxWidth}] p-[20px] items-start`,
"rounded-[8px] border border-[color:var(--Subbrown_4,#EAE5E2)] bg-white gap-6",
className,
].join(" ")}
>
{/* ... rest of implementation ... */}
</div>
);
}Then update this file:
-"use client";
-import Image from "next/image";
-
-type NewsListProps = {
- imageUrl: string;
- title: string;
- content: string;
- date: string;
- className?: string;
-};
-
-export default function Setting_NewsList({
- imageUrl,
- title,
- content,
- date,
- className = "",
-}: NewsListProps) {
- return (
- <div className={[/* ... */].join(" ")}>
- {/* ... */}
- </div>
- );
-}
+import BaseNewsList from "../shared/BaseNewsList";
+
+type NewsListProps = {
+ imageUrl: string;
+ title: string;
+ content: string;
+ date: string;
+ className?: string;
+};
+
+export default function Setting_NewsList(props: NewsListProps) {
+ return <BaseNewsList {...props} maxWidth="1000px" />;
+}Committable suggestion skipped: line range outside the PR's diff.
๐ค Prompt for AI Agents
In src/components/base-ui/Settings/setting_news_list.tsx lines 1-55: the
component largely duplicates src/components/base-ui/News/news_list.tsx; extract
a shared BaseNewsList component (e.g.,
src/components/base-ui/shared/BaseNewsList.tsx) that contains the full markup
and accepts props for imageUrl, title, content, date and a maxWidthClass or
className prop to control the max-w utility (avoid building Tailwind classes
with string interpolationโaccept the full class like "max-w-[1000px]" or
"max-w-[1040px]" from the caller). Replace this file with a thin wrapper that
imports BaseNewsList and renders it with maxWidthClass="max-w-[1000px]" (and
similarly update the other news_list to pass "max-w-[1040px]"), forwarding any
className and props unchanged.
| <Image | ||
| src={imageUrl} | ||
| alt={title} | ||
| fill | ||
| sizes="100px" | ||
| className="object-cover" | ||
| /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
๐งฉ Analysis chain
๐ Script executed:
# Find next.config files in the repository
fd -e js -e ts -e mjs -e cjs 'next\.config'Repository: checkmo2025/FE
Length of output: 72
๐ Script executed:
# Examine the component file to understand the context
cat -n src/components/base-ui/Settings/setting_news_list.tsx | head -60Repository: checkmo2025/FE
Length of output: 1845
๐ Script executed:
cat -n next.config.tsRepository: checkmo2025/FE
Length of output: 269
Add remotePatterns configuration for external image URLs.
The Image component loads external URLs via the imageUrl prop, but next.config.ts lacks the required remotePatterns configuration. Without this, Next.js will throw a "hostname is not allowed" error at runtime.
Add remotePatterns to next.config.ts:
const nextConfig: NextConfig = {
reactCompiler: true,
images: {
remotePatterns: [
{
protocol: 'https',
hostname: '**', // Adjust to specific domains for production
},
],
},
};Replace the wildcard with specific hostnames you expect to load (e.g., example.com, cdn.example.com).
๐ค Prompt for AI Agents
In src/components/base-ui/Settings/setting_news_list.tsx lines 29-35 the Image
component uses external imageUrl values but next.config.ts lacks
images.remotePatterns, causing "hostname is not allowed" runtime errors; update
next.config.ts to add an images.remotePatterns array that allows the external
hosts (e.g., entries with protocol: 'https' and hostname: 'example.com' or
'cdn.example.com' or a '**' wildcard for dev), replace the wildcard with the
specific domains you expect for production, and restart the Next.js server so
the new image host rules take effect.
๐ก To Reviewers
์ด PR์ feat-10 ์์ ์ ๋๋ค.
์๋ณธ ๋ ํฌ์ push ๊ถํ์ด ์์ด์ fork์์ PR ์ฌ๋ ธ์ต๋๋ค
๐ฅ ์์ ๋ด์ฉ (๊ฐ๋ฅํ ๊ตฌ์ฒด์ ์ผ๋ก ์์ฑํด ์ฃผ์ธ์)
ํ์ผ๊ตฌ์กฐ
[global css] ๊ธ์จ์ฒด, ์ ํธ์ถ๋ฐฉ๋ฒ
button_without_img
๊ฐ ํ์ด์ง ๋ณ ์์ฑํ ui
ํ์ผ๊ตฌ์กฐ
src/components/base_ui
-> ํ์
/home
/Auth
/Group-search
/Group-create
/BookStory
/News
/Search
/Profile
/Settings
/button_without_img.tsx
[global css] ๊ธ์จ์ฒด, ์ ํธ์ถ๋ฐฉ๋ฒ
ex)
Subhead_4_1 ->
/* Subhead_4.1 /
font-family: "Pretendard Variable";
font-size: 18px;
font-style: normal;
font-weight: 500;
line-height: 135%; / 24.3px /
letter-spacing: -0.018px;
๊ฐ ํธ์ถ๋จ
๊ธ์จ์ฒด ์์์ / Subhead_4.1 */ ์ด๋ ๊ฒ ํ๊ธฐ๋์ด ์์ผ๋ ํธ์ถํ์๊ณ ์๋ง ์ ๊ฒฝ์จ์ฃผ์๋ฉด ๋ฉ๋๋ค.
ํธ์ถ ๊ท์น
์ด๋ฆ: ๋์๋ฌธ์ ํฌํจ ๊ทธ๋๋ก
[.] ์ _๋ก ๋์ฒด
์ ํ ํฐ์ Gray_7 ๊ฐ์ ํ์ ( ex text-[color:var(--Gray_7)]
button_without_img
์ด๋ฏธ์ง๊ฐ ์์ ์์ ์ฌ์ฉํ ์ ์๋ ๋ฒํผ ํผ
์ฌ์ฉ ์์ (๋น์ด์์ ์ ๊ธฐ๋ณธ๊ฐ์ด ๋ค์ด๊ฐ)
์๋ฌด ๋ด์ฉ ์์ ์์ ๊ธฐ๋ณธ๊ฐ์ด ๋ค์ด๊ฐ
// ์๋ ๊ธฐ๋ณธ๊ฐ ๊ฒธ ์ฌ์ฉ๋ฐฉ๋ฒ
<ButtonWithoutImg
text="๋ฑ๋ก"
onClick={() => {} }
bgColorVar="--premary_2"
borderColorVar="--premary_2"
textColorVar="--White"
hoverBgColorVar="--premary_2"
hoverBorderColorVar="--premary_2"
hoverTextColorVar="--White"
width={132}
height={44}
/>
์ฑ ๋ชจ_ํํ๋ฉด
๋ก๊ทธ์ธ/ํ์๊ฐ์
๊ฐ๋ณ๋ก ๋ง๋๋๊ฒ ๋์๋ณด์ฌ ์๋ตํ์์ต๋๋ค.
๋ชจ์ ๊ฒ์ / ๋ชจ์ ์์ฑ
-> ์ ์ชฝ์ด๋ผ์ ์ผ๋จ ๋ณด๋ฅํ์ต๋๋ค.
์ฑ ์ด์ผ๊ธฐ
์์
๊ฒ์
๋ง์ดํ์ด์ง&๋ค๋ฅธ์ฌ๋ ํ๋กํ
notification_element
ํํ๋ฉด์ ์๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค ๊ณ ๋ก ์๋ตํฉ๋๋ค notification_element
subscribe
์ค์
setting_news_list
์์์ news_list์ maxํฌ๊ธฐ ๋นผ๊ณค ๋ค๋ฅด์ง ์์ต๋๋ค ๊ณ ๋ก ์๋ตํฉ๋๋ค.
setting_report_list
๐ค ์ถํ ์์ ์์
๋ชจ์ ๊ฒ์ / ๋ชจ์ ์์ฑ
๐ธ ์์ ๊ฒฐ๊ณผ (์คํฌ๋ฆฐ์ท)
๐ ๊ด๋ จ ์ด์
Feat-10
Summary by CodeRabbit
Release Notes
New Features
Style
โ๏ธ Tip: You can customize this high-level summary in your review settings.