Skip to content

[refactor] 동아리 목록, 상세 및 채팅 페이지 리디자인 반영#189

Merged
ff1451 merged 3 commits intodevelopfrom
188-refactor-동아리-목록-상세-및-채팅-페이지-리디자인-반영
Mar 19, 2026

Hidden character warning

The head ref may contain hidden characters: "188-refactor-\ub3d9\uc544\ub9ac-\ubaa9\ub85d-\uc0c1\uc138-\ubc0f-\ucc44\ud305-\ud398\uc774\uc9c0-\ub9ac\ub514\uc790\uc778-\ubc18\uc601"
Merged

[refactor] 동아리 목록, 상세 및 채팅 페이지 리디자인 반영#189
ff1451 merged 3 commits intodevelopfrom
188-refactor-동아리-목록-상세-및-채팅-페이지-리디자인-반영

Conversation

@ff1451
Copy link
Collaborator

@ff1451 ff1451 commented Mar 18, 2026

✨ 요약

- 동아리 목록/검색/상세 화면을 리디자인 시안에 맞게 정리했습니다.
- 동아리 상세 라우트를 별도 Layout으로 이동하고 헤더 동작을 조정했습니다.
- 채팅 목록/채팅방 화면과 채팅 전용 헤더를  UI에 맞게 개편했습니다.
- 변경사항은 동아리 영역과 채팅 영역으로 나눠 2개의 커밋으로 정리했습니다.



😎 해결한 이슈



Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 채팅 입력창 자동 높이 조절 및 전송 버튼 비활성화 반영
    • 채팅 메시지 행 컴포넌트 도입으로 메시지 표시·그룹화 개선
    • 채팅 목록 항목 구성 및 미리보기 개선
  • 스타일

    • 버튼 색상 통일(bg-primary-500) 및 카드·검색바 레이아웃 조정
    • 동아리 카드, 리스트 헤더 및 간격·타이포그래피 개선
  • 변경

    • 회원 직책 라벨 "관리자" → "임원진"으로 표시
    • 특정 헤더 타이틀 매핑 제거 및 탭/멤버 수 표시 로직 개선

@coderabbitai
Copy link

coderabbitai bot commented Mar 18, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7f9a36a6-6b12-4f0e-8b98-93ea51c01572

📥 Commits

Reviewing files that changed from the base of the PR and between a41f5b5 and a022d88.

📒 Files selected for processing (1)
  • src/components/layout/Header/components/ChatHeader.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/layout/Header/components/ChatHeader.tsx

Walkthrough

라우팅 선언을 일부 재구성해 /clubs/:clubId 경로를 레이아웃 그룹의 형제 라우트로 이동했고, 헤더 구성에 /clubs/\d+ 매칭 기본 타입을 추가했습니다. 채팅 헤더 DOM이 절대 위치에서 플렉스 기반으로 재배치되었고, 채팅방에서는 개별 메시지 렌더링을 ChatMessageRow로 분리하고 textarea 자동 리사이징과 전송 버튼 비활성화 로직(isSubmitDisabled)을 도입했습니다. 다수의 UI 스타일(예: bg-primary → bg-primary-500, 카드/목록/탭 스타일)과 ClubMemberTab 시그니처에 멤버 수 prop 추가가 포함됩니다.

Possibly related PRs

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 동아리 목록/상세/채팅 페이지 리디자인 반영이라는 주요 변경사항을 명확하게 요약합니다.
Linked Issues check ✅ Passed 링크된 이슈 #188은 구체적 요구사항이 없으나, PR이 제목과 설명에 명시된 동아리/채팅 페이지 리디자인 및 라우트·헤더 조정 목표를 모두 충족합니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 동아리 목록/상세/채팅 페이지 리디자인과 관련 라우트·헤더 조정 범위 내에 있습니다.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 188-refactor-동아리-목록-상세-및-채팅-페이지-리디자인-반영
📝 Coding Plan
  • Generate coding plan for human review comments

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.

❤️ Share

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/pages/Club/ClubList/components/SearchBar.tsx (1)

7-12: ⚠️ Potential issue | 🟠 Major

Props 타입을 판별 유니온으로 분리하고, input에 접근성 속성을 추가해주세요.

현재 타입이면 isButton과 입력 props를 함께 넘겨도 허용되어 <Link> 안에 <input>이 들어가는 조합을 타입이 막아주지 못합니다. 또한 input 요소에 aria-label이 없어 접근성을 만족하지 않습니다.

-interface SearchBarProps {
-  isButton?: boolean;
-  value?: string;
-  onChange?: (value: string) => void;
-  onSubmit?: (e: FormEvent<HTMLFormElement>) => void;
-  autoFocus?: boolean;
-}
+type SearchBarProps =
+  | {
+      isButton: true;
+      value?: never;
+      onChange?: never;
+      onSubmit?: never;
+      autoFocus?: never;
+    }
+  | {
+      isButton?: false;
+      value?: string;
+      onChange?: (value: string) => void;
+      onSubmit?: (e: FormEvent<HTMLFormElement>) => void;
+      autoFocus?: boolean;
+    };

input 요소에도 aria-label="동아리 이름으로 검색" 추가하세요.

Also applies to: 22-23, 25-31, 36-46

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

In `@src/pages/Club/ClubList/components/SearchBar.tsx` around lines 7 - 12, The
SearchBarProps currently allows invalid combinations (e.g., isButton with input
callbacks) and missing accessibility on the input; change SearchBarProps into a
discriminated union (e.g., { isButton: true; onSubmit: ... } | { isButton?:
false; value?: string; onChange?: (v:string)=>void; autoFocus?: boolean }) so
TypeScript prevents passing input props when isButton is true, update the
SearchBar component to use this union (references: SearchBarProps, isButton,
onChange, onSubmit) and add aria-label="동아리 이름으로 검색" to the input element; apply
the same discriminated-union + aria-label fix to the other similar
components/instances noted (lines 22-23, 25-31, 36-46).
src/pages/Club/ClubDetail/index.tsx (1)

84-104: ⚠️ Potential issue | 🟠 Major

현재 탭만 조건부 렌더링하도록 리팩토링이 필요합니다.

모든 탭이 조건 검증 후 <Activity> 내에서 렌더링되고 있습니다. mode="hidden"이더라도 자식 컴포넌트가 마운트되면서 useGetClubRecruitment (ClubRecruitment.tsx L18), useGetClubMembers (ClubMember.tsx L60) 등 데이터 훅이 즉시 실행됩니다. 결과적으로 사용자가 보는 탭과 관계없이 모든 활성 탭의 요청이 함께 발생합니다. 상태 보존이 필수가 아니라면 현재 탭만 렌더링하는 방식으로 초기 로드 성능을 개선할 수 있습니다.

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

In `@src/pages/Club/ClubDetail/index.tsx` around lines 84 - 104, The current code
mounts all tab child components inside <Activity> even when mode="hidden",
causing hooks like useGetClubRecruitment and useGetClubMembers to run; change
rendering so only the active tab's <Activity> and its child are mounted.
Concretely, for each tab (symbols: Activity, ClubRecruit, ClubIntro,
ClubMemberTab, ClubAccount) move the currentTab checks outward so you render the
Activity+child only when currentTab matches (e.g., only render ClubRecruit when
currentTab === 'recruitment' and clubDetail.recruitment.status !== 'CLOSED';
only render ClubMemberTab when currentTab === 'members' and clubDetail.isMember;
only render ClubAccount when currentTab === 'account' and (clubDetail.isMember
|| clubDetail.isApplied'); keep ClubIntro rendered only when currentTab ===
'intro'). This prevents mounting children and stops their hooks
(useGetClubRecruitment, useGetClubMembers) from executing for inactive tabs.
🧹 Nitpick comments (2)
src/pages/Chat/index.tsx (1)

58-84: 목록 아이템 텍스트는 typography token으로 맞춰 주세요.

이 구간에 text-[16px], text-[12px], leading-[1.6]가 반복돼서 채팅 목록만 theme scale에서 벗어납니다. text-sub*/text-body*/text-cap* 조합으로 맞추는 편이 유지보수에 좋습니다.

As per coding guidelines, "Use typography tokens (text-h1 through text-h5, text-sub1 through text-sub4, text-body1 through text-body3, text-cap1 through text-cap2) from src/styles/theme.css".

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

In `@src/pages/Chat/index.tsx` around lines 58 - 84, The chat list uses hardcoded
utility font classes (e.g., text-[16px], text-[12px], leading-[1.6]) on elements
rendering room.roomName, formatTime(room.lastSentAt), previewMessage and the
unread badge which breaks the theme scale; replace those with the appropriate
typography tokens from src/styles/theme.css (for example
text-sub*/text-body*/text-cap* combinations) on the span containing
room.roomName, the timestamp span that calls formatTime, the previewMessage <p>,
and any small badge text so all items use the theme tokens instead of explicit
sizes while preserving existing class names like BellOffIcon and
hasUnreadMessage logic.
src/pages/Club/ClubDetail/components/ClubMember.tsx (1)

1-1: 배지 스타일은 cn()과 테마 토큰으로 맞춰주세요.

지금은 clsx 직접 사용과 hex 색상 클래스가 같이 들어와 있어서, 테마 변경 시 이 컴포넌트만 따로 수정하게 됩니다. POSITION_BADGE_STYLEStheme.css 기반 토큰으로 바꾸고 클래스 병합도 cn()으로 통일하는 편이 좋겠습니다.

As per coding guidelines Use cn() utility from src/utils/ts/cn.ts to merge Tailwind CSS classes and Prioritize color tokens from src/styles/theme.css.

Also applies to: 13-17, 41-45

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

In `@src/pages/Club/ClubDetail/components/ClubMember.tsx` at line 1, The component
is using clsx and hardcoded hex color classes; replace the clsx import with the
cn() utility and refactor POSITION_BADGE_STYLES to use theme CSS tokens (from
theme.css) instead of hex classes, then update all places where clsx is used
(including the badge render paths referenced by POSITION_BADGE_STYLES and the
occurrences around lines 13-17 and 41-45) to call cn(...) with the new
token-based class names; ensure you import cn() from src/utils/ts/cn.ts and keep
the same class-merge semantics so the badge styles follow theme tokens and use
cn() consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/App.tsx`:
- Around line 103-105: Update the routing so the clubs/:clubId route uses a
dedicated Layout instance with the page-specific props instead of the shared
Layout: change the Route for path "clubs/:clubId" to render <Layout
contentClassName="bg-indigo-5" showBottomNav={false}> wrapping <ClubDetail />
(or otherwise pass those props into Layout when rendering ClubDetail), leaving
"clubs/:clubId/applications" to use the standard Layout with its existing props;
ensure you reference the Layout component and the ClubDetail element so the
top/overscroll background and header padding come from the Layout's main area
and match the redesign.

In `@src/components/layout/Header/components/ChatHeader.tsx`:
- Around line 33-37: 현재 ChatHeader 컴포넌트에서 사이드바 여는 버튼을 isGroup으로 감싸면 1:1 다이렉트
채팅에서 사이드바(알림 토글)에 접근할 수 없어 집니다; 수정하려면 ChatHeader 내에서 onClick 핸들러 openSidebar와 버튼
렌더링(HamburgerIcon 포함)은 항상 렌더되도록 변경하고, 그룹 전용으로 보여야 할 참가자 목록/섹션(참고: 기존 diff의 사이드바
첫 섹션, lines 54-70에 해당하는 UI)은 계속해서 isGroup 조건으로만 감싸 유지하세요; 즉, 제거 대상은 버튼을 감싸는
isGroup 조건이고, 유지할 조건은 참가자 목록 렌더링 부분입니다.

In `@src/pages/Chat/ChatRoom.tsx`:
- Around line 156-159: The message list container (the div with ref
scrollContainerRef in ChatRoom.tsx) needs to be exposed as a live region so
assistive tech announces new messages; update that div to include role="log" and
provide an accessible name (using aria-label or aria-labelledby, e.g.,
aria-label="Chat messages") and consider adding aria-atomic/aria-live attributes
as needed to ensure new message announcements; ensure the change is applied to
the same element that receives appended messages so screen readers detect
additions.

In `@src/pages/Club/ClubList/components/SearchBar.tsx`:
- Around line 25-31: The search input in SearchBar.tsx lacks an accessible name;
update the <input> in the SearchBar component to include an accessible name
(preferably add an aria-label attribute or wire a visible <label> to it).
Specifically, either add aria-label={ariaLabel ?? SEARCH_PLACEHOLDER} and accept
an optional ariaLabel prop on the SearchBar, or add a <label
htmlFor="club-search"> tied to input id="club-search"; ensure the new prop or
id/label change is used where value and onChange are passed so screen readers
can announce the field.

---

Outside diff comments:
In `@src/pages/Club/ClubDetail/index.tsx`:
- Around line 84-104: The current code mounts all tab child components inside
<Activity> even when mode="hidden", causing hooks like useGetClubRecruitment and
useGetClubMembers to run; change rendering so only the active tab's <Activity>
and its child are mounted. Concretely, for each tab (symbols: Activity,
ClubRecruit, ClubIntro, ClubMemberTab, ClubAccount) move the currentTab checks
outward so you render the Activity+child only when currentTab matches (e.g.,
only render ClubRecruit when currentTab === 'recruitment' and
clubDetail.recruitment.status !== 'CLOSED'; only render ClubMemberTab when
currentTab === 'members' and clubDetail.isMember; only render ClubAccount when
currentTab === 'account' and (clubDetail.isMember || clubDetail.isApplied');
keep ClubIntro rendered only when currentTab === 'intro'). This prevents
mounting children and stops their hooks (useGetClubRecruitment,
useGetClubMembers) from executing for inactive tabs.

In `@src/pages/Club/ClubList/components/SearchBar.tsx`:
- Around line 7-12: The SearchBarProps currently allows invalid combinations
(e.g., isButton with input callbacks) and missing accessibility on the input;
change SearchBarProps into a discriminated union (e.g., { isButton: true;
onSubmit: ... } | { isButton?: false; value?: string; onChange?:
(v:string)=>void; autoFocus?: boolean }) so TypeScript prevents passing input
props when isButton is true, update the SearchBar component to use this union
(references: SearchBarProps, isButton, onChange, onSubmit) and add
aria-label="동아리 이름으로 검색" to the input element; apply the same
discriminated-union + aria-label fix to the other similar components/instances
noted (lines 22-23, 25-31, 36-46).

---

Nitpick comments:
In `@src/pages/Chat/index.tsx`:
- Around line 58-84: The chat list uses hardcoded utility font classes (e.g.,
text-[16px], text-[12px], leading-[1.6]) on elements rendering room.roomName,
formatTime(room.lastSentAt), previewMessage and the unread badge which breaks
the theme scale; replace those with the appropriate typography tokens from
src/styles/theme.css (for example text-sub*/text-body*/text-cap* combinations)
on the span containing room.roomName, the timestamp span that calls formatTime,
the previewMessage <p>, and any small badge text so all items use the theme
tokens instead of explicit sizes while preserving existing class names like
BellOffIcon and hasUnreadMessage logic.

In `@src/pages/Club/ClubDetail/components/ClubMember.tsx`:
- Line 1: The component is using clsx and hardcoded hex color classes; replace
the clsx import with the cn() utility and refactor POSITION_BADGE_STYLES to use
theme CSS tokens (from theme.css) instead of hex classes, then update all places
where clsx is used (including the badge render paths referenced by
POSITION_BADGE_STYLES and the occurrences around lines 13-17 and 41-45) to call
cn(...) with the new token-based class names; ensure you import cn() from
src/utils/ts/cn.ts and keep the same class-merge semantics so the badge styles
follow theme tokens and use cn() consistently.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 228a5e57-85d0-43d0-8fd5-009ac7f8a92e

📥 Commits

Reviewing files that changed from the base of the PR and between 03b664e and a41f5b5.

⛔ Files ignored due to path filters (1)
  • src/assets/svg/chat-send-arrow.svg is excluded by !**/*.svg, !src/assets/** and included by **
📒 Files selected for processing (15)
  • src/App.tsx
  • src/components/layout/Header/components/ChatHeader.tsx
  • src/components/layout/Header/headerConfig.ts
  • src/components/layout/Header/routeTitles.ts
  • src/pages/Chat/ChatRoom.tsx
  • src/pages/Chat/index.tsx
  • src/pages/Club/Application/components/AccountInfo.tsx
  • src/pages/Club/ClubDetail/components/ClubIntro.tsx
  • src/pages/Club/ClubDetail/components/ClubMember.tsx
  • src/pages/Club/ClubDetail/components/ClubRecruitment.tsx
  • src/pages/Club/ClubDetail/index.tsx
  • src/pages/Club/ClubList/components/ClubCard.tsx
  • src/pages/Club/ClubList/components/SearchBar.tsx
  • src/pages/Club/ClubList/index.tsx
  • src/pages/Club/ClubSearch/index.tsx
💤 Files with no reviewable changes (1)
  • src/components/layout/Header/routeTitles.ts

Comment on lines 103 to 105
<Route element={<Layout />}>
<Route path="clubs/:clubId" element={<ClubDetail />} />
<Route path="clubs/:clubId/applications" element={<ApplicationPage />} />
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

ClubDetail는 전용 Layout 배경을 분리해주세요.

ClubDetailsrc/pages/Club/ClubDetail/index.tsx에서 루트 배경을 bg-indigo-5로 두고 있지만, 실제 페이지 배경과 헤더 padding 영역은 Layout<main>이 담당합니다. 지금처럼 공용 <Layout /> 아래에 두면 상세 상단/overscroll 구간은 기본 배경색이 남아서 리디자인과 다른 띠가 보일 수 있습니다. clubs/:clubIdcontentClassName="bg-indigo-5"를 주는 Layout으로 분리하는 편이 안전합니다.

💡 제안
-            <Route element={<Layout />}>
-              <Route path="clubs/:clubId" element={<ClubDetail />} />
+            <Route element={<Layout contentClassName="bg-indigo-5" />}>
+              <Route path="clubs/:clubId" element={<ClubDetail />} />
+            </Route>
+            <Route element={<Layout />}>
               <Route path="clubs/:clubId/applications" element={<ApplicationPage />} />

As per coding guidelines src/pages/**/*.tsx: Pass showBottomNav (bottom tab display) and contentClassName (background color, etc.) props to Layout component.

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

In `@src/App.tsx` around lines 103 - 105, Update the routing so the clubs/:clubId
route uses a dedicated Layout instance with the page-specific props instead of
the shared Layout: change the Route for path "clubs/:clubId" to render <Layout
contentClassName="bg-indigo-5" showBottomNav={false}> wrapping <ClubDetail />
(or otherwise pass those props into Layout when rendering ClubDetail), leaving
"clubs/:clubId/applications" to use the standard Layout with its existing props;
ensure you reference the Layout component and the ClubDetail element so the
top/overscroll background and header padding come from the Layout's main area
and match the redesign.

Comment on lines 156 to 159
<div
ref={scrollContainerRef}
className="bg-indigo-0 min-h-0 flex-1 overflow-x-hidden overflow-y-auto overscroll-contain pb-4"
className="min-h-0 flex-1 overflow-x-hidden overflow-y-auto overscroll-contain py-3"
>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

메시지 목록을 live region으로 노출해주세요.

현재 컨테이너는 동적으로 추가되는 메시지를 보조기기가 채팅 로그로 인식할 근거가 없습니다. 채팅처럼 순차적으로 항목이 추가되는 영역은 role="log"와 접근 가능한 이름을 두는 패턴이어서, 지금처럼 포커스가 입력창에 머무는 화면에서는 새 메시지 안내가 누락될 수 있습니다. (developer.mozilla.org)

💡 제안
       <div
         ref={scrollContainerRef}
+        role="log"
+        aria-label="채팅 메시지"
         className="min-h-0 flex-1 overflow-x-hidden overflow-y-auto overscroll-contain py-3"
       >
📝 Committable suggestion

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

Suggested change
<div
ref={scrollContainerRef}
className="bg-indigo-0 min-h-0 flex-1 overflow-x-hidden overflow-y-auto overscroll-contain pb-4"
className="min-h-0 flex-1 overflow-x-hidden overflow-y-auto overscroll-contain py-3"
>
<div
ref={scrollContainerRef}
role="log"
aria-label="채팅 메시지"
className="min-h-0 flex-1 overflow-x-hidden overflow-y-auto overscroll-contain py-3"
>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/Chat/ChatRoom.tsx` around lines 156 - 159, The message list
container (the div with ref scrollContainerRef in ChatRoom.tsx) needs to be
exposed as a live region so assistive tech announces new messages; update that
div to include role="log" and provide an accessible name (using aria-label or
aria-labelledby, e.g., aria-label="Chat messages") and consider adding
aria-atomic/aria-live attributes as needed to ensure new message announcements;
ensure the change is applied to the same element that receives appended messages
so screen readers detect additions.

Comment on lines +25 to +31
<input
className="flex-1 bg-transparent text-base font-medium text-indigo-300 outline-none placeholder:text-indigo-300"
placeholder={SEARCH_PLACEHOLDER}
value={value}
onChange={onChange ? (e) => onChange(e.target.value) : undefined}
autoFocus={autoFocus}
/>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

검색 input에 접근 가능한 이름을 추가해 주세요.

placeholder만으로는 스크린리더 이름이 잡히지 않습니다. aria-label이나 연결된 <label>이 필요합니다.

예시 수정
         <input
+          type="search"
+          aria-label={SEARCH_PLACEHOLDER}
           className="flex-1 bg-transparent text-base font-medium text-indigo-300 outline-none placeholder:text-indigo-300"
           placeholder={SEARCH_PLACEHOLDER}
           value={value}

As per coding guidelines, "src/pages/**/components/**/*.tsx: ... 접근성(aria-*, role, 키보드 탐색)을 우선 확인하는지".

📝 Committable suggestion

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

Suggested change
<input
className="flex-1 bg-transparent text-base font-medium text-indigo-300 outline-none placeholder:text-indigo-300"
placeholder={SEARCH_PLACEHOLDER}
value={value}
onChange={onChange ? (e) => onChange(e.target.value) : undefined}
autoFocus={autoFocus}
/>
<input
type="search"
aria-label={SEARCH_PLACEHOLDER}
className="flex-1 bg-transparent text-base font-medium text-indigo-300 outline-none placeholder:text-indigo-300"
placeholder={SEARCH_PLACEHOLDER}
value={value}
onChange={onChange ? (e) => onChange(e.target.value) : undefined}
autoFocus={autoFocus}
/>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/Club/ClubList/components/SearchBar.tsx` around lines 25 - 31, The
search input in SearchBar.tsx lacks an accessible name; update the <input> in
the SearchBar component to include an accessible name (preferably add an
aria-label attribute or wire a visible <label> to it). Specifically, either add
aria-label={ariaLabel ?? SEARCH_PLACEHOLDER} and accept an optional ariaLabel
prop on the SearchBar, or add a <label htmlFor="club-search"> tied to input
id="club-search"; ensure the new prop or id/label change is used where value and
onChange are passed so screen readers can announce the field.

@ff1451 ff1451 merged commit ff0f3a1 into develop Mar 19, 2026
1 check passed
@ff1451 ff1451 self-assigned this Mar 20, 2026
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.

[refactor] 동아리 목록, 상세 및 채팅 페이지 리디자인 반영

1 participant