๐ ๏ธ Refactor: ์น ์ ๊ทผ์ฑ ๊ฐํ (ARIA ์์ฑ ๋ฐ ์๋งจํฑ ๊ตฌ์กฐ ๊ฐ์ )#99
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Walkthrough์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐ์ ARIA ์์ฑ๊ณผ ์๋งจํฑ ๋งํฌ์ ์ ์ถ๊ฐํ๊ณ ์ผ๋ถ ์ปดํฌ๋ํธ์ ํค๋ณด๋ ์ํธ์์ฉ(Enter/Space)๊ณผ ์์ด์ฝ์ ์ํธ์์ฉ ํ๋๊ทธ๋ฅผ ๋์ ํ์ต๋๋ค. ๋์ ๋ก์ง์ ์ ์ง๋ ์ฑ ์ ๊ทผ์ฑ ๋ฉํ๋ฐ์ดํฐ์ ํค๋ณด๋ ํธ๋ค๋ฌ๊ฐ ์ถ๊ฐ๋์์ต๋๋ค. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant FlipCard
participant Icon
participant Boardgame
participant Router
rect `#E6F7FF`
Note over User,FlipCard: FlipCard์ ํค๋ณด๋ ํ์ฑํ ์ถ๊ฐ
User->>FlipCard: press Enter/Space
FlipCard->>FlipCard: toggle flip state (aria-pressed ์
๋ฐ์ดํธ)
end
rect `#FFF4E6`
Note over User,Icon: Icon์ interactive ๋ชจ๋ (isInteractive)
User->>Icon: click / press Enter/Space
Icon->>Icon: handleKeyDown โ ํธ์ถ๋ onClick ์คํ (aria-pressed ๋ฐ์)
end
rect `#F0FFF4`
Note over User,Boardgame: Boardgame ๋ค๋น๊ฒ์ด์
์ค์ํ
User->>Boardgame: click or press Enter/Space on active cell
Boardgame->>Boardgame: handleCellClick(label)
Boardgame->>Router: router.push(`/main/Node?label=${label}`)
end
Estimated code review effort๐ฏ 3 (Moderate) | โฑ๏ธ ~25 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touchesโ Passed checks (5 passed)
โจ Finishing touches
๐งช Generate unit tests (beta)
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 |
|
๐ท๏ธ Labeler has automatically applied labels based on your PR title, branch name, or commit message. |
There was a problem hiding this comment.
Actionable comments posted: 12
Caution
Some comments are outside the diff and canโt be posted inline due to platform limitations.
โ ๏ธ Outside diff range comments (4)
src/pages/map/result/components/TagGroup.tsx (1)
26-37: Tag ์ปดํฌ๋ํธ๊ฐ ARIA ์์ฑ์ ์ ๋ฌํ์ง ์์ต๋๋ค.Tag ์ปดํฌ๋ํธ์ Props ์ธํฐํ์ด์ค์
aria-pressed์aria-label์ด ์ ์๋์ด ์์ง ์์ผ๋ฉฐ, ์ปดํฌ๋ํธ ๊ตฌํ๋ถ์์๋ rest props๋ฅผ ํ์ button ์๋ฆฌ๋จผํธ๋ก ์ ๋ฌํ์ง ์์ต๋๋ค. ๋ฐ๋ผ์:
- TypeScript ํ์ ์๋ฌ๊ฐ ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค
- ์ด ARIA ์์ฑ๋ค์ด ์ค์ DOM์ ์ ์ฉ๋์ง ์์ ์ ๊ทผ์ฑ ๊ฐ์ ํจ๊ณผ๊ฐ ์์ต๋๋ค
Tag ์ปดํฌ๋ํธ๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์์ ํด์ผ ํฉ๋๋ค:
src/shared/components/tag/Tag.tsx ์ธํฐํ์ด์ค ์์ :
interface Props extends React.ButtonHTMLAttributes<HTMLButtonElement> { label: string; icon?: IconName; className?: string; onClick?: () => void; variant?: VariantProps<typeof tagStyle>['variant']; }src/shared/components/tag/Tag.tsx ๊ตฌํ๋ถ ์์ :
-({ label, icon, variant, className, onClick }: Props) => { +({ label, icon, variant, className, onClick, ...rest }: Props) => { return ( <button type='button' className={cn(tagStyle({ variant }), className)} onClick={onClick} + {...rest} > {icon && <Icon name={icon} size={14} color='gray-50' />} <span>{label}</span> </button> ); }src/pages/main/HiddenReward.tsx (1)
10-24: ๊ตฌ์กฐ์ role์ interactive ์์์ ๋ถ์ ์ ํ๊ฒ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
role="main"์ ํ์ด์ง์ ์ฃผ์ ์ฝํ ์ธ ์์ญ์ ๋ํ๋ด๋ ๊ตฌ์กฐ์ (landmark) ์ญํ ์ ๋๋ค. ํด๋ฆญ ๊ฐ๋ฅํdiv์ ์ด๋ฅผ ์ ์ฉํ๋ ๊ฒ์ ARIA ๋ช ์ธ๋ฅผ ์๋ฐํฉ๋๋ค.๋ํ ์ ์ฒด ํ์ด์ง๋ฅผ ํด๋ฆญ ๊ฐ๋ฅํ๊ฒ ๋ง๋๋ ๊ฒ์ ํค๋ณด๋ ์ ๊ทผ์ฑ ์ธก๋ฉด์์๋ ๋ฌธ์ ๊ฐ ์์ต๋๋ค:
- ํค๋ณด๋ ์ฌ์ฉ์๊ฐ Enter/Space๋ก ํ์ฑํํ ์ ์์ต๋๋ค
- ํฌ์ปค์ค ํ์๊ฐ ์์ด ํ์ฌ ์์น๋ฅผ ์๊ธฐ ์ด๋ ต์ต๋๋ค
๋ค์๊ณผ ๊ฐ์ด ๋ฆฌํฉํ ๋ง์ ๊ถ์ฅํฉ๋๋ค:
- <div + <main className=' relative w-full h-[100vh] bg-gradient-to-b from-mint-500 to-white flex flex-col justify-center items-center text-center overflow-hidden - cursor-pointer ' - role="main" aria-label="ํ๋ ๋ฆฌ์๋ ํ๋ ํ์ด์ง" - onClick={() => - router.push({ - pathname: '/main/PostCard', - }) - } > <div className='absolute inset-0 z-0 pointer-events-none mt-0'> <Lottie animationData={Confetti_revised} loop autoplay className='w-full h-full object-cover' /> </div> <div className='relative z-10 flex flex-col items-center justify-center'> <h1 className='text-black mb-[4.5rem] text-headline-lg-serif'> Congrats! </h1> <p className='text-title-sm text-black mb-[6rem]'> ์ถํํฉ๋๋ค! <br /> ํ๋ ๋ฆฌ์๋๋ฅผ ํ๋ํ์ จ์ต๋๋ค. </p> <Lottie animationData={Logo_sliver} loop autoplay className='w-[18rem] h-[18rem] mb-[6rem]' /> <p className='text-label-md text-black mb-[7rem]'> ๊ฐํจ๋ฆญ๋ ์ ์ค์ ํฌ์ผ๋ชฌ <br /> '๋๋ฌด๋ฅผ ์ํธํ๋ ์ข ์ฒ ์จ'๋ฅผ <br /> ํ๋ํ์ จ์ต๋๋ค! </p> - <p className='text-label-serif text-mint-500'>click!</p> + <button + type="button" + onClick={() => + router.push({ + pathname: '/main/PostCard', + }) + } + className='text-label-serif text-mint-500 bg-transparent border-none cursor-pointer' + aria-label="์ฝ์ ํ์ด์ง๋ก ์ด๋" + > + click! + </button> </div> - </div> + </main>src/pages/main/index.tsx (1)
34-41: ํค๋ณด๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ์ถ๊ฐํ์ธ์.
role="button"๊ณผtabIndex={0}์ ์ถ๊ฐํ์ง๋ง ํค๋ณด๋ ๋ด๋น๊ฒ์ด์ ์ ์ํ ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ๋๋ฝ๋์์ต๋๋ค.onKeyDownํธ๋ค๋ฌ๋ฅผ ์ถ๊ฐํ์ฌ Enter ๋๋ Space ํค๋ก๋ ๋์ผํ ๋์์ด ์ํ๋๋๋ก ํด์ผ ํฉ๋๋ค.๋ค์ diff๋ฅผ ์ ์ฉํ์ธ์:
<section role="button" tabIndex={0} aria-label="๋ณด๋ํ์ผ๋ก ์ด๋" onClick={() => { router.push('/main/Board'); }} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + router.push('/main/Board'); + } + }} >src/shared/components/container/EventCard.tsx (1)
96-105: ์ค๊ฐ ํฌ๊ธฐ ์นด๋์๋ ์ ๊ทผ์ฑ ์์ฑ์ ์ถ๊ฐํ์ธ์.๋ํ ์นด๋์ ํํธ ์์ด์ฝ์๋
isInteractive,pressed,aria-label์์ฑ์ด ์์ง๋ง ์ค๊ฐ ํฌ๊ธฐ ์นด๋์๋ ์์ต๋๋ค. ์ผ๊ด๋ ์ ๊ทผ์ฑ์ ์ํด ์ค๊ฐ ํฌ๊ธฐ ์นด๋์๋ ๋์ผํ ์์ฑ์ ์ถ๊ฐํด์ผ ํฉ๋๋ค.๋ค์ diff๋ฅผ ์ ์ฉํ์ธ์:
<Icon name='HeartStraight' size={20} color={ liked ? 'red-400' : variant === 'mint' ? 'mint-400' : 'gray-300' } fillColor={liked ? 'red-300' : undefined} onClick={handleLikeClick} + isInteractive + pressed={liked} + aria-label={liked ? '์ข์์ ์ทจ์' : '์ข์์'} className='cursor-pointer' />
๐งน Nitpick comments (12)
src/pages/events/[id].tsx (3)
36-38: semantic HTML ์์ ์ฌ์ฉ์ ๊ณ ๋ คํ์ธ์.ํ์ฌ
aria-label="ํ์ฌ ๊ธฐ๊ฐ"์ ๊ฐ์ง wrapper๊ฐ DateTag๋ฅผ ๊ฐ์ธ๊ณ ์์ต๋๋ค. DateTag ์์ฒด๋ ์ ๊ทผ์ฑ ๋ ์ด๋ธ์ ๊ฐ์ง๊ณ ์์ด ์ผ๋ถ ์ค๋ณต์ด ์์ ์ ์์ต๋๋ค.generic
div๋์<section>์์๋ฅผ ์ฌ์ฉํ๋ฉด ๋ ๋ช ํํ ๊ตฌ์กฐ์ ์๋ฏธ๋ฅผ ์ ๊ณตํ ์ ์์ต๋๋ค:- <div aria-label="ํ์ฌ ๊ธฐ๊ฐ" className={cn('flex justify-center w-[18.4rem] mt-[1.3rem]')}> + <section aria-labelledby="event-period" className={cn('flex justify-center w-[18.4rem] mt-[1.3rem]')}> + <h2 id="event-period" className="sr-only">ํ์ฌ ๊ธฐ๊ฐ</h2> <DateTag startDate={startDate} endDate={endDate} /> - </div> + </section>
66-80: semantic HTML ์์๋ก ๊ฐ์ ํ ์ ์์ต๋๋ค.
aria-label="ํ์ฌ ์ ๋ณด"๋ฅผ ๊ฐ์ง wrapper๋ ์ฃผ์ ์ ๋ณด ์น์ ์ ๋ํ๋ด๋ฏ๋ก<section>์์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์๋ฏธ๋ก ์ ์ผ๋ก ๋ช ํํฉ๋๋ค.- <div + <section aria-label="ํ์ฌ ์ ๋ณด" className={cn( 'flex flex-col items-center w-full gap-[0.8rem]', 'mt-[0.8rem]' )} > {/* ... */} - </div> + </section>
82-107: ๊ด๋ จ ํ์ฌ ๋ชฉ๋ก์ semantic HTML ์ฌ์ฉ์ ๊ณ ๋ คํ์ธ์."๊ด๋ จ ํ์ฌ ๋ชฉ๋ก"์ navigation ๋๋ ๋ณ๋ ์น์ ์ผ๋ก ์๋ฏธ๊ฐ ๋ช ํํ๋ฏ๋ก
<section>๋๋<nav>์์ ์ฌ์ฉ์ ๊ถ์ฅํฉ๋๋ค.- <div + <section aria-label="๊ด๋ จ ํ์ฌ ๋ชฉ๋ก" className={cn( 'grid grid-cols-2 gap-[1.2rem] justify-items-center w-full max-w-[35.4rem]' )} > {/* ... */} - </div> + </section>์ฐธ๊ณ : ํ์ฌ ํ๋์ฝ๋ฉ๋ "๊ด๋ จ ํ์ฌ" ๋ฐ์ดํฐ๋ placeholder๋ก ๋ณด์ด๋ฉฐ, ํฅํ ์ค์ ๋ฐ์ดํฐ๋ก ๊ต์ฒด๊ฐ ํ์ํ ๊ฒ์ผ๋ก ์์๋ฉ๋๋ค.
src/pages/mypage/postcard/[id].tsx (1)
24-26:role="main"์<main>์์์์ ์ค๋ณต๋ฉ๋๋ค.HTML5์ ์๋งจํฑ
<main>์์๋ ์ด๋ฏธ ์๋ฌต์ ์ผ๋กmain์ญํ ์ ์ ๊ณตํฉ๋๋ค. WAI-ARIA ๋ช ์ธ์ ๋ฐ๋ฅด๋ฉด, ์๋งจํฑ HTML ์์์ ๋ช ์์ ์ผ๋ก ๋์ผํ role์ ์ถ๊ฐํ๋ ๊ฒ์ ๋ถํ์ํ๋ฉฐ ์ฝ๋ ์ค๋ณต์ ์ด๋ํฉ๋๋ค.
aria-label์ ์ ์งํ๋role์์ฑ์ ์ ๊ฑฐํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค.<main - role="main" aria-label="์ ์ฅํ ์ฝ์ ์์ธ ํ์ด์ง" className={cn(src/pages/mypage/events/[id].tsx (1)
25-27:role="main"์<main>์์์์ ์ค๋ณต๋ฉ๋๋ค.HTML5์ ์๋งจํฑ
<main>์์๋ ์ด๋ฏธ ์๋ฌต์ ์ผ๋กmain์ญํ ์ ์ ๊ณตํฉ๋๋ค. ๋ช ์์ ์ผ๋ก ๋์ผํ role์ ์ถ๊ฐํ๋ ๊ฒ์ ๋ถํ์ํฉ๋๋ค.
aria-label์ ์ ์งํ๋role์์ฑ์ ์ ๊ฑฐํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค.<main - role="main" aria-label="์ ์ฅํ ํ์ฌ ์์ธ ํ์ด์ง" className={cn(src/pages/mypage/index.tsx (1)
15-19:role="main"์<main>์์์์ ์ค๋ณต๋ฉ๋๋ค.HTML5์ ์๋งจํฑ
<main>์์๋ ์ด๋ฏธ ์๋ฌต์ ์ผ๋กmain์ญํ ์ ์ ๊ณตํฉ๋๋ค.
aria-label์ ์ ์งํ๋role์์ฑ์ ์ ๊ฑฐํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค.<main className='w-full min-h-screen bg-white flex flex-col items-center' - role="main" aria-label="๋ง์ด ํ์ด์ง" >src/pages/map/result/Map.tsx (1)
9-13: ์๋งจํฑ HTML ์ฌ์ฉ์ ์ข์ง๋งrole="main"์ ์ค๋ณต๋ฉ๋๋ค.
div๋ฅผ<main>์ผ๋ก ๋ณ๊ฒฝํ ๊ฒ์ ์๋งจํฑ HTML ์ฌ์ฉ ์ธก๋ฉด์์ ํ๋ฅญํ ๊ฐ์ ์ ๋๋ค. ๊ทธ๋ฌ๋<main>์์๋ ์ด๋ฏธ ์๋ฌต์ ์ผ๋กmain์ญํ ์ ์ ๊ณตํ๋ฏ๋ก ๋ช ์์ ์ธrole์์ฑ์ ๋ถํ์ํฉ๋๋ค.
aria-label์ ์ ์งํ๋role์์ฑ์ ์ ๊ฑฐํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค.<main className="w-full h-[100vh] bg-mint-300 overflow-hidden" - role="main" aria-label="์ฝ์ค ์ถ์ฒ ์ง๋ ํ์ด์ง" >src/pages/main/components/stampBoard/Stamp.tsx (1)
26-34: ์ผ๊ด์ฑ์ ์ํดrole="img"๋ฅผ ์ถ๊ฐํ์ธ์.ํ๋ํ ์คํฌํ์๋
role="img"๊ฐ ์์ง๋ง ๋ฏธํ๋ ์คํฌํ์๋ ์์ต๋๋ค. ์ผ๊ด๋ ์ ๊ทผ์ฑ ๊ตฌ์กฐ๋ฅผ ์ํด ๋ฏธํ๋ ์คํฌํ์ ์ปจํ ์ด๋์๋ ๋์ผํ ์ญํ ์ ์ถ๊ฐํ๋ ๊ฒ์ด ์ข์ต๋๋ค.๋ค์ diff๋ฅผ ์ ์ฉํ์ธ์:
return ( <div + role="img" className={cn( 'rounded-full bg-pink-100 w-[2.8rem] h-[2.8rem]', className, )} aria-label={`${index + 1}๋ฒ์งธ ์คํฌํ ๋ฏธํ๋`} /> );src/pages/chatbot/index.tsx (1)
53-58: aria-live ์์ฑ์ด ์ค๋ณต์ ๋๋ค.
role="log"๋ ์ด๋ฏธ ์๋ฌต์ ์ผ๋กaria-live="polite"๋ฅผ ํฌํจํ๊ณ ์์ด ๋ช ์์ ์ผ๋กaria-live="polite"๋ฅผ ์ถ๊ฐํ ํ์๊ฐ ์์ต๋๋ค.๋ค์ diff๋ฅผ ์ ์ฉํ์ฌ ์ค๋ณต ์์ฑ์ ์ ๊ฑฐํ ์ ์์ต๋๋ค:
<main role="log" aria-label="์ฑํ ๋ด์ฉ" - aria-live="polite" className={cn(mainStyle())} >src/pages/loading/index.tsx (1)
7-12: aria-live ์์ฑ์ด ์ค๋ณต์ ๋๋ค.
role="status"๋ ์ด๋ฏธ ์๋ฌต์ ์ผ๋กaria-live="polite"๋ฅผ ํฌํจํ๊ณ ์์ต๋๋ค. ๋ช ์์ ์ผ๋ก ์ถ๊ฐํ ํ์๊ฐ ์์ต๋๋ค.๋ค์ diff๋ฅผ ์ ์ฉํ์ฌ ์ค๋ณต์ ์ ๊ฑฐํ ์ ์์ต๋๋ค:
<div className='flex flex-col items-center justify-between h-[100vh] bg-white' role='status' - aria-live='polite' aria-label='ํ์ด์ง ๋ก๋ฉ ์ค์ ๋๋ค' >src/shared/icons/components/icon.tsx (1)
108-110: aria-pressed ์ฌ์ฉ์ ๋ํ ๊ฐ์ด๋๊ฐ ํ์ํฉ๋๋ค.
aria-pressed๋ ํ ๊ธ ๋ฒํผ(on/off ์ํ)์๋ง ์ฌ์ฉํด์ผ ํ๋ ์์ฑ์ ๋๋ค. ๋ชจ๋ ์ธํฐ๋ํฐ๋ธ ์์ด์ฝ์ด ํ ๊ธ์ธ ๊ฒ์ ์๋๋ฏ๋ก,pressedprop์ ์ ๋ฌํ์ง ์๋ ๊ฒฝ์ฐ์ ๊ตฌ๋ถํ ์ ์๋๋ก ํ์ ์ ์ฝ์ด๋ ์ฃผ์์ ์ถ๊ฐํ๋ ๊ฒ์ด ์ข์ต๋๋ค.๋ค์๊ณผ ๊ฐ์ด ์ธํฐํ์ด์ค์ ์ฃผ์์ ์ถ๊ฐํ์ธ์:
interface IconProps extends React.SVGProps<SVGSVGElement> { name: IconName; + /** Makes icon keyboard-accessible as a button. Use with onClick handler. */ isInteractive?: boolean; + /** For toggle buttons only. Indicates pressed state (true/false/undefined). */ pressed?: boolean; size?: number | string; // ... rest of props }src/pages/main/components/board/Boardgame.tsx (1)
24-31: alt=""์ aria-hidden="true"๊ฐ ์ค๋ณต์ ๋๋ค.์ฅ์์ฉ ์ด๋ฏธ์ง์ ๊ฒฝ์ฐ
alt=""๋ง์ผ๋ก๋ ์คํฌ๋ฆฐ ๋ฆฌ๋์์ ๋ฌด์๋ฉ๋๋ค.aria-hidden="true"๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ์ค๋ณต์ด์ง๋ง ํด๋กญ์ง๋ ์์ต๋๋ค.ํ ๊ฐ์ง๋ง ์ฌ์ฉํด๋ ์ถฉ๋ถํฉ๋๋ค:
<Image src="/assets/background_.svg" alt="" width={402} height={755} className="w-full h-full object-cover" priority - aria-hidden="true" />
๐ Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
๐ Files selected for processing (29)
src/pages/auth/index.tsx(1 hunks)src/pages/chatbot/components/ChattingBubble.tsx(1 hunks)src/pages/chatbot/components/ChattingInput.tsx(1 hunks)src/pages/chatbot/index.tsx(1 hunks)src/pages/events/[id].tsx(3 hunks)src/pages/events/components/DateTag.tsx(1 hunks)src/pages/events/index.tsx(2 hunks)src/pages/loading/index.tsx(2 hunks)src/pages/main/Board.tsx(1 hunks)src/pages/main/HiddenReward.tsx(1 hunks)src/pages/main/Node.tsx(3 hunks)src/pages/main/PostCard.tsx(2 hunks)src/pages/main/components/board/Boardgame.tsx(1 hunks)src/pages/main/components/stampBoard/Progress.tsx(1 hunks)src/pages/main/components/stampBoard/Stamp.tsx(1 hunks)src/pages/main/components/video/VideoPlayer.tsx(0 hunks)src/pages/main/index.tsx(2 hunks)src/pages/map/components/CourseSelectSection.tsx(1 hunks)src/pages/map/result/Map.tsx(1 hunks)src/pages/map/result/components/ResultMap.tsx(0 hunks)src/pages/map/result/components/TagGroup.tsx(1 hunks)src/pages/mypage/components/ProfilePhoto.tsx(1 hunks)src/pages/mypage/events/[id].tsx(1 hunks)src/pages/mypage/index.tsx(2 hunks)src/pages/mypage/postcard/[id].tsx(1 hunks)src/shared/components/container/EventCard.tsx(2 hunks)src/shared/components/flipCard/FlipCard.tsx(1 hunks)src/shared/components/tab/BottomNav.tsx(1 hunks)src/shared/icons/components/icon.tsx(3 hunks)
๐ค Files with no reviewable changes (2)
- src/pages/map/result/components/ResultMap.tsx
- src/pages/main/components/video/VideoPlayer.tsx
๐งฐ Additional context used
๐ง Learnings (1)
๐ Learning: 2025-10-31T17:34:04.352Z
Learnt from: jjangminii
Repo: geulDa/FE PR: 64
File: src/pages/map/result/components/ResultMap.tsx:3-3
Timestamp: 2025-10-31T17:34:04.352Z
Learning: The geulDa/FE project uses Next.js Pages Router (not App Router), so components should import useRouter from 'next/router' and should not use the 'use client' directive.
Applied to files:
src/pages/map/result/Map.tsx
๐งฌ Code graph analysis (8)
src/pages/main/PostCard.tsx (2)
src/shared/icons/components/icon.tsx (1)
Icon(57-117)src/shared/utils/postcardActions.ts (1)
handleShare(2-12)
src/pages/map/result/components/TagGroup.tsx (1)
src/shared/components/tag/Tag.tsx (2)
Props(27-38)Props(6-12)
src/pages/mypage/index.tsx (1)
src/pages/mypage/components/ProfilePhoto.tsx (1)
ProfilePhoto(11-35)
src/pages/map/result/Map.tsx (1)
src/pages/map/result/components/FullMap.tsx (1)
FullMap(7-19)
src/pages/chatbot/components/ChattingBubble.tsx (1)
src/shared/lib/utils.ts (1)
cn(71-73)
src/pages/chatbot/index.tsx (2)
src/shared/lib/utils.ts (1)
cn(71-73)src/pages/chatbot/components/ChattingBubble.tsx (1)
Chatting(32-43)
src/pages/events/components/DateTag.tsx (1)
src/shared/lib/utils.ts (1)
cn(71-73)
src/pages/events/[id].tsx (2)
src/shared/lib/utils.ts (1)
cn(71-73)src/pages/events/components/DateTag.tsx (1)
DateTag(24-45)
โฐ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build-and-deploy
๐ Additional comments (26)
src/shared/components/tab/BottomNav.tsx (1)
34-34: โ aria-label ์ถ๊ฐ ์น์ธ
<nav>์์์ ํ๊ตญ์ด aria-label์ ์ถ๊ฐํ์ฌ ์คํฌ๋ฆฐ ๋ฆฌ๋ ์ฌ์ฉ์์๊ฒ ๋ค๋น๊ฒ์ด์ ์์ญ์ ๋ช ํํ ์ ๋ฌํฉ๋๋ค. ๊ธฐ์กดaria-current์์ฑ(45๋ฒ ์ค)๊ณผ ํจ๊ป WAI-ARIA ํ์ค์ ๋ง๊ฒ ์ ์ ํ๊ฒ ๊ตฌํ๋์์ต๋๋ค.src/pages/main/components/stampBoard/Progress.tsx (1)
27-28: ์ ๊ทผ์ฑ ๊ฐ์ ์ด ์ฌ๋ฐ๋ฅด๊ฒ ์ ์ฉ๋์์ต๋๋ค.Radix Progress๋ role="progressbar"์ aria-valuemin, aria-valuemax, aria-valuenow๋ฅผ ์๋์ผ๋ก ์ ๊ณตํฉ๋๋ค. ์ถ๊ฐํ
aria-label๊ณผaria-valuetext๋ ๊ธฐ๋ณธ ARIA ์์ฑ๊ณผ ์ถฉ๋ํ์ง ์์ผ๋ฉฐ ์ ๊ทผ์ฑ์ ๊ฐํํฉ๋๋ค.์ ํ์ ๊ฐ์ ์ ์:
aria-label="์งํ๋ฅ "์aria-label="์คํฌํ ์งํ๋ฅ "๋ก ๋ณ๊ฒฝํ๋ฉด ์คํฌ๋ฆฐ ๋ฆฌ๋ ์ฌ์ฉ์์๊ฒ ๋ ๊ตฌ์ฒด์ ์ธ ์ปจํ ์คํธ๋ฅผ ์ ๊ณตํ ์ ์์ต๋๋ค.src/pages/map/result/components/TagGroup.tsx (1)
32-36: aria-label ํ ์คํธ๊ฐ ๋ช ํํ๊ณ ์ ์ฉํฉ๋๋ค.ํ์ฌ ์ํ์ ์ํํ ์ก์ ์ ๋ช ํํ๊ฒ ์ค๋ช ํ๋ ํ๊ตญ์ด aria-label์ด ์ ์์ฑ๋์์ต๋๋ค. ์คํฌ๋ฆฐ ๋ฆฌ๋ ์ฌ์ฉ์์๊ฒ ์ปจํ ์คํธ๋ฅผ ์ ๊ณตํ๋ ์ข์ ์ ๊ทผ ๋ฐฉ์์ ๋๋ค.
์ฐธ๊ณ : aria-label์ด ์ค์ ๋๋ฉด ์๊ฐ์ ๋ ์ด๋ธ(label prop)์ ์ค๋ฒ๋ผ์ด๋ํ๋ฏ๋ก, ์คํฌ๋ฆฐ ๋ฆฌ๋๋ ๋ ์์ธํ ์ค๋ช ์ ๋ฃ๊ฒ ๋ฉ๋๋ค. ์ด๋ ์ด๋ฒ ๊ฒฝ์ฐ์ ์๋๋ ๋์์ผ๋ก ๋ณด์ ๋๋ค.
src/pages/events/[id].tsx (1)
59-60: ์ด๋ฏธ์ง placeholder์ ๋ํ ์ฐ์ํ ์ ๊ทผ์ฑ ํจํด์ ๋๋ค.์ด๋ฏธ์ง๊ฐ ์๋ ๊ฒฝ์ฐ
role="img"์ ์ค๋ช ์ ์ธaria-label์ ์ฌ์ฉํ์ฌ ์คํฌ๋ฆฐ ๋ฆฌ๋ ์ฌ์ฉ์์๊ฒ ๋ช ํํ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ WCAG ๊ฐ์ด๋๋ผ์ธ์ ์ ๋ฐ๋ฅด๋ ํจํด์ ๋๋ค.src/pages/events/index.tsx (2)
57-80: ์ด๋ฒคํธ ๋ชฉ๋ก์ ๋ํ ์ ์ ํ ์ ๊ทผ์ฑ ๊ฐ์ ์ ๋๋ค.
<section>์aria-label="์ด๋ฒคํธ ๋ชฉ๋ก"์ ์ถ๊ฐํ์ฌ ์คํฌ๋ฆฐ ๋ฆฌ๋ ์ฌ์ฉ์๊ฐ ์ฝํ ์ธ ์์ญ์ ๋ช ํํ ์ธ์ํ ์ ์๋๋ก ๊ฐ์ ํ์ต๋๋ค. semantic HTML๊ณผ ARIA ์์ฑ์ ์กฐํฉ์ด ์ ์ ํฉ๋๋ค.
82-96: ๋์ ์ฝํ ์ธ ๋ณ๊ฒฝ์ ๋ํ ์ฐ์ํ ์ ๊ทผ์ฑ ํจํด์ ๋๋ค.empty state์
role="status"์aria-live="polite"๋ฅผ ์ถ๊ฐํ์ฌ ๋ ์ง ํํฐ๋ง ๊ฒฐ๊ณผ๊ฐ ๋ณ๊ฒฝ๋ ๋ ์คํฌ๋ฆฐ ๋ฆฌ๋ ์ฌ์ฉ์์๊ฒ ์๋์ผ๋ก ์๋ฆผ์ด ์ ๋ฌ๋๋๋ก ๊ตฌํํ์ต๋๋ค. ์ด๋ WCAG 2.1์ ๋์ ์ฝํ ์ธ ์ ๋ฐ์ดํธ ๊ฐ์ด๋๋ผ์ธ์ ์ ๋ฐ๋ฅด๋ ๋ชจ๋ฒ ์ฌ๋ก์ ๋๋ค.src/pages/mypage/components/ProfilePhoto.tsx (1)
27-27: ์ ๊ทผ์ฑ ๊ฐ์ ์ด ์ ์ ์ฉ๋์์ต๋๋ค!ํ๋กํ ์ด๋ฏธ์ง์ ๋ช ํํ ๋์ฒด ํ ์คํธ๋ฅผ ์ถ๊ฐํ์ฌ ์คํฌ๋ฆฐ ๋ฆฌ๋ ์ฌ์ฉ์๊ฐ ์ด๋ฏธ์ง์ ๋ชฉ์ ์ ์ดํดํ ์ ์๊ฒ ๋์์ต๋๋ค.
src/pages/chatbot/components/ChattingInput.tsx (2)
44-44: ์ ๋ ฅ ํ๋์ ์ ์ ํ ์ ๊ทผ์ฑ ๋ ์ด๋ธ์ด ์ถ๊ฐ๋์์ต๋๋ค!
placeholder๋ง์ผ๋ก๋ ๋ถ์ถฉ๋ถํ ์ ์์ผ๋ฏ๋กaria-label์ ์ถ๊ฐํ์ฌ ์คํฌ๋ฆฐ ๋ฆฌ๋ ์ฌ์ฉ์์๊ฒ ๋ช ํํ ์ปจํ ์คํธ๋ฅผ ์ ๊ณตํฉ๋๋ค.
52-52: ์์ด์ฝ ๋ฒํผ์ ์ ์ ํ ์ ๊ทผ์ฑ ๋ ์ด๋ธ์ด ์ถ๊ฐ๋์์ต๋๋ค!ํ ์คํธ๊ฐ ์๋ ์์ด์ฝ ๋ฒํผ์
aria-label์ ์ถ๊ฐํ์ฌ ๋ฒํผ์ ๊ธฐ๋ฅ์ ๋ช ํํ ์ ๋ฌํฉ๋๋ค.src/pages/auth/index.tsx (1)
22-23: ์ฅ์์ฉ SVG์ ๋ํ ์ ๊ทผ์ฑ ์ฒ๋ฆฌ๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์ ์ฉ๋์์ต๋๋ค!
aria-hidden="true"์focusable="false"๋ฅผ ์ฌ์ฉํ์ฌ ์ฅ์ ๋ชฉ์ ์ SVG๋ฅผ ๋ณด์กฐ ๊ธฐ์ ์์ ์ ์ ํ ์ ์ธํ์ต๋๋ค. ์ด๋ WAI-ARIA ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์ ๋ฐ๋ฅด๊ณ ์์ต๋๋ค.src/pages/mypage/index.tsx (1)
22-22: ์น์ ๋ณ ์ ๊ทผ์ฑ ๋ ์ด๋ธ์ด ์ ์ ์ฉ๋์์ต๋๋ค!๊ฐ ์น์ ์ ๋ช ํํ
aria-label์ ์ถ๊ฐํ์ฌ ์คํฌ๋ฆฐ ๋ฆฌ๋ ์ฌ์ฉ์๊ฐ ํ์ด์ง ๊ตฌ์กฐ๋ฅผ ์ฝ๊ฒ ํ์ํ ์ ์๊ฒ ๋์์ต๋๋ค.Also applies to: 28-28, 51-51
src/pages/main/index.tsx (1)
26-27: ์ ์ ํ ์ฅ์ ์ด๋ฏธ์ง ์ฒ๋ฆฌ์ ๋๋ค.๋ฐฐ๋ ์ด๋ฏธ์ง๋ฅผ
alt=""์aria-hidden="true"๋ก ๋งํฌ์ ํ ๊ฒ์ ์ฅ์ ์ด๋ฏธ์ง์ ๋ํ ์ฌ๋ฐ๋ฅธ ์ ๊ทผ ๋ฐฉ์์ ๋๋ค.src/pages/main/Board.tsx (1)
11-15: ์ ์ ํ ์ ๊ทผ์ฑ ํฅ์์ ๋๋ค.
<main>์์์role="main"๊ณผaria-label์ ์ถ๊ฐํ์ต๋๋ค. ์๋งจํฑ HTML ์์์๋ ์์์ ์ญํ ์ด ์์ผ๋ฏ๋กrole="main"์ ๊ธฐ์ ์ ์ผ๋ก ์ค๋ณต์ด์ง๋ง, ์ผ๋ถ ์ค๋๋ ์คํฌ๋ฆฐ ๋ฆฌ๋์์ ํธํ์ฑ์ ์ํด ๋ช ์์ ์ผ๋ก ์ง์ ํ๋ ๊ฒ์ ํด๋กญ์ง ์์ต๋๋ค.aria-label์ ํ์ด์ง ์ปจํ ์คํธ๋ฅผ ๋ช ํํ ์ ๋ฌํฉ๋๋ค.src/pages/main/PostCard.tsx (2)
10-11: ์ ์ ํ ๋๋๋งํฌ ์ญํ ์ง์ ์ ๋๋ค.๋ฃจํธ ์ปจํ ์ด๋์
role="main"๊ณผaria-label์ ์ถ๊ฐํ์ฌ ํ์ด์ง์ ์ฃผ์ ์ฝํ ์ธ ์์ญ์ ๋ช ํํ ํ์ํ์ต๋๋ค.
32-46: ๋ฒํผ ์ ๊ทผ์ฑ์ด ์ ๊ตฌํ๋์์ต๋๋ค.๊ฐ ๋ฒํผ์ ๋ช ํํ
aria-label์ ์ถ๊ฐํ๊ณ ์์ด์ฝ์aria-hidden="true"๋ก ํ์ํ์ฌ ์คํฌ๋ฆฐ ๋ฆฌ๋๊ฐ ์ฅ์์ ์์๋ฅผ ๋ฌด์ํ๋๋ก ํ์ต๋๋ค. ์ด๋ ์ ๊ทผ์ฑ ๋ชจ๋ฒ ์ฌ๋ก์ ๋ถํฉํฉ๋๋ค.src/shared/components/flipCard/FlipCard.tsx (1)
22-26: ํ๋ฅญํ ํค๋ณด๋ ์ ๊ทผ์ฑ ๊ตฌํ์ ๋๋ค.
role="button",tabIndex={0}, ๋์ aria-label,aria-pressed๋ฅผ ์กฐํฉํ์ฌ ์์ ํ ํค๋ณด๋ ์ ๊ทผ์ฑ์ ์ ๊ณตํฉ๋๋ค. ํ ๊ธ ๋ฒํผ์ผ๋ก์ ์ ์ ํ ์๋ฏธ๋ก ์ ๊ตฌ์กฐ์ ๋๋ค.src/pages/chatbot/components/ChattingBubble.tsx (1)
35-40: ๋ฉ์์ง ์ ๊ทผ์ฑ์ด ํฅ์๋์์ต๋๋ค.์ฑํ ๋ฒ๋ธ์
aria-label์ ์ถ๊ฐํ์ฌ ์คํฌ๋ฆฐ ๋ฆฌ๋ ์ฌ์ฉ์๊ฐ ๋ฉ์์ง์ ๋ฐ์ ์๋ฅผ ๊ตฌ๋ถํ ์ ์๋๋ก ํ์ต๋๋ค. ๊ธฐ์กด ์คํ์ผ๋ง์ ์ ์งํ๋ฉด์ ์ ๊ทผ์ฑ์ ๊ฐ์ ํ๋ ์ข์ ๋ฐฉ๋ฒ์ ๋๋ค.src/pages/main/Node.tsx (2)
20-24: ํ์ด์ง ๊ตฌ์กฐ๊ฐ ์ ๊ทผ์ฑ ๋ฉด์์ ๋ช ํํฉ๋๋ค.
<main>์์์role="main"๊ณผ ๋์ aria-label์ ์ถ๊ฐํ์ฌ ํ์ด์ง์ ์ฃผ์ ์ฝํ ์ธ ์์ญ์ ๋ช ํํ ํ์ํ์ต๋๋ค.
37-60: ์คํฌํ ๋ฒํผ์ ์ ๊ทผ์ฑ์ด ์ ๊ตฌํ๋์์ต๋๋ค.๋ฒํผ์ ์ํ์ ๋ฐ๋ผ ๋ณ๊ฒฝ๋๋
aria-label๊ณผ ์ฅ์์ ์์ด์ฝ์ ๋ํaria-hidden="true"์ค์ ์ผ๋ก ์คํฌ๋ฆฐ ๋ฆฌ๋ ์ฌ์ฉ์๊ฐ ๋ฒํผ์ ๋ชฉ์ ๊ณผ ์ํ๋ฅผ ๋ช ํํ ์ดํดํ ์ ์์ต๋๋ค.src/shared/components/container/EventCard.tsx (1)
131-147: ๋ํ ์นด๋์ ์ ๊ทผ์ฑ ๊ตฌํ์ด ์ฐ์ํฉ๋๋ค.ํํธ ์์ด์ฝ์
isInteractive,pressed,aria-label์์ฑ์ ์ ์ ํ ์ฌ์ฉํ์ฌ ํค๋ณด๋ ์ ๊ทผ์ฑ๊ณผ ์คํฌ๋ฆฐ ๋ฆฌ๋ ์ง์์ ์๋ฒฝํ๊ฒ ๊ตฌํํ์ต๋๋ค. ์ด๋ ์ ๊ทผ์ฑ ๋ชจ๋ฒ ์ฌ๋ก์ ๋๋ค.src/pages/chatbot/index.tsx (2)
62-65: LGTM!์ฅ์์ฉ ์์์
aria-hidden="true"๋ฅผ ์ ์ฉํ ๊ฒ์ ์คํฌ๋ฆฐ ๋ฆฌ๋์์ ๋ถํ์ํ ์์๋ฅผ ์จ๊ธฐ๋ ์ฌ๋ฐ๋ฅธ ์ ๊ทผ์ ๋๋ค.
86-86: LGTM!์คํฌ๋กค ์ต์ปค ์์๋ฅผ
aria-hidden="true"๋ก ํ์ํ ๊ฒ์ ์ฌ๋ฐ๋ฅธ ์ ๊ทผ์ ๋๋ค.src/pages/loading/index.tsx (1)
13-16: LGTM!์ฅ์์ฉ SVG์ Lottie ์ ๋๋ฉ์ด์ ์
aria-hidden="true"๋ฅผ ์ ์ฉํ ๊ฒ์ ์ฌ๋ฐ๋ฅธ ์ ๊ทผ์ ๋๋ค.Also applies to: 39-39
src/shared/icons/components/icon.tsx (1)
42-45: LGTM!
isInteractive์pressedprop ์ถ๊ฐ๊ฐ ์ ์ ํ๊ฒ ํ์ ์ ์๋์์ต๋๋ค.Also applies to: 57-60
src/pages/main/components/board/Boardgame.tsx (2)
9-15: LGTM!๋ค๋น๊ฒ์ด์ ๋ก์ง์
handleCellClick์ผ๋ก ์ค์ํํ ๊ฒ์ ์ข์ ๋ฆฌํฉํ ๋ง์ ๋๋ค. TODO ์ฃผ์์ด ์์ผ๋ ๋ก๊ทธ์ธ ์ฒดํฌ ๊ตฌํ์ ์์ง ๋ง์ธ์.
48-71: LGTM!๋นํ์ฑ ์ ์
aria-hidden์ผ๋ก ์จ๊ธฐ๊ณ , ํ์ฑ ์ ์role="button", ํค๋ณด๋ ํธ๋ค๋ฌ(Enter/Space), ๊ทธ๋ฆฌ๊ณ ์ค๋ช ์ ์ธaria-label์ ์ ๊ณตํ ๊ฒ์ ํ๋ฅญํ ์ ๊ทผ์ฑ ๊ตฌํ์ ๋๋ค.
src/pages/events/index.tsx
Outdated
| {/* ์คํฌ๋ฆฐ๋ฆฌ๋๊ฐ โ๋ ์ง ์ ํโ์ผ๋ก ์ฝํ๋๋ก ์ถ๊ฐ */} | ||
| <label htmlFor="event-date" className="sr-only"> | ||
| ํ์ฌ ๋ ์ง ์ ํ | ||
| </label> | ||
| <DatePicker value={date} onChange={setDate} /> |
There was a problem hiding this comment.
๐ ๏ธ Refactor suggestion | ๐ Major
๐งฉ Analysis chain
label์ htmlFor ์์ฑ์ด DatePicker์ ์ฐ๊ฒฐ๋์ง ์์ ์ ์์ต๋๋ค.
htmlFor="event-date"๋ฅผ ์ฌ์ฉํ๊ณ ์์ง๋ง, DatePicker ์ปดํฌ๋ํธ์ ํด๋น id๋ฅผ ์ ๋ฌํ์ง ์๊ณ ์์ต๋๋ค. DatePicker๊ฐ ๋ด๋ถ์ ์ผ๋ก id="event-date"๋ฅผ ๊ฐ์ง input์ ๋ ๋๋งํ์ง ์๋๋ค๋ฉด label๊ณผ input์ ์ฐ๊ฒฐ์ด ์๋ํ์ง ์์ ์ ๊ทผ์ฑ์ด ์์๋ฉ๋๋ค.
๋ค์ ์คํฌ๋ฆฝํธ๋ก DatePicker ์ปดํฌ๋ํธ์ ๊ตฌํ์ ํ์ธํ์ธ์:
ํด๊ฒฐ ๋ฐฉ๋ฒ:
Option 1: DatePicker์ id prop ์ ๋ฌ
- <label htmlFor="event-date" className="sr-only">
+ <label htmlFor="event-date-picker" className="sr-only">
ํ์ฌ ๋ ์ง ์ ํ
</label>
- <DatePicker value={date} onChange={setDate} />
+ <DatePicker id="event-date-picker" value={date} onChange={setDate} />Option 2: htmlFor ์ ๊ฑฐํ๊ณ aria-label ์ฌ์ฉ
- <label htmlFor="event-date" className="sr-only">
- ํ์ฌ ๋ ์ง ์ ํ
- </label>
- <DatePicker value={date} onChange={setDate} />
+ <div aria-label="ํ์ฌ ๋ ์ง ์ ํ">
+ <DatePicker value={date} onChange={setDate} />
+ </div>๐ Script executed:
#!/bin/bash
# Description: DatePicker ์ปดํฌ๋ํธ๊ฐ id prop์ ๋ฐ๋์ง ํ์ธ
# DatePicker ์ปดํฌ๋ํธ ๊ตฌํ ์ฐพ๊ธฐ
ast-grep --pattern $'export default function DatePicker($$$) {
$$$
}'
# ๋๋ ํ์ผ ์ฐพ๊ธฐ ๋ฐ ๋ด์ฉ ํ์ธ
fd DatePicker.tsx --exec cat {}Length of output: 2620
DatePicker๊ฐ ํ์ค input์ด ์๋๋ฏ๋ก label์ htmlFor ์์ฑ์ด ์๋ํ์ง ์์ต๋๋ค.
DatePicker๋ Button ๊ธฐ๋ฐ์ Popover ์ปดํฌ๋ํธ๋ก, id prop์ ์ง์ํ์ง ์์ต๋๋ค. ๋ฐ๋ผ์ htmlFor="event-date"๋ฅผ ์ฌ์ฉํด๋ ์ฐ๊ฒฐํ input์ด ์์ด label์ด ๋์ํ์ง ์์ต๋๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ:
DatePicker ์ปดํฌ๋ํธ๋ฅผ ์์ ํ์ฌ aria-label prop์ ์ง์ํ๋๋ก ๋ณ๊ฒฝ:
interface DatePickerProps {
value?: Date;
onChange?: (date: Date) => void;
defaultValue?: Date;
className?: string;
+ aria-label?: string;
}
export function DatePicker({
value,
onChange,
defaultValue,
className,
+ 'aria-label': ariaLabel,
...calendarProps
}: DatePickerProps) {
// ...
return (
<div className={cn('flex flex-col gap-3', className)}>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
- <Button className='w-[16rem] h-[4rem] justify-between rounded-[500px] text-label-lg text-pink-300 bg-pink-50 border border-pink-100'>
+ <Button aria-label={ariaLabel} className='w-[16rem] h-[4rem] justify-between rounded-[500px] text-label-lg text-pink-300 bg-pink-50 border border-pink-100'>๊ทธ ํ ์ฌ์ฉ ์:
- <label htmlFor="event-date" className="sr-only">
- ํ์ฌ ๋ ์ง ์ ํ
- </label>
- <DatePicker value={date} onChange={setDate} />
+ <DatePicker aria-label="ํ์ฌ ๋ ์ง ์ ํ" value={date} onChange={setDate} />Committable suggestion skipped: line range outside the PR's diff.
There was a problem hiding this comment.
Actionable comments posted: 1
๐งน Nitpick comments (3)
src/pages/map/result/components/TagGroup.tsx (1)
31-36: aria-label ๊ตฌํ์ ํ๋ฅญํ์ง๋ง, aria-pressed๋ ์ ๊ฑฐ๋ฅผ ๊ถ์ฅํฉ๋๋ค.์ด์ ๋ฆฌ๋ทฐ ์ฝ๋ฉํธ๋ฅผ ๋ฐ์ํ์ฌ
aria-pressed๋ก์ง์ ์์ ํด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ํ์ง๋ง ๋จ์ผ ๋ทฐ ์ ํ ๋ฒํผ์์aria-pressed์ฌ์ฉ์ ์ฌ์ ํ ์๋ฏธ๋ก ์ ์ผ๋ก ํผ๋์ ์ค ์ ์์ต๋๋ค:
aria-pressed๋ ์ฃผ๋ก ์ง์์ ์ธ on/off ๊ธฐ๋ฅ(์: ํ ์คํธ ์๋ํฐ์ ๊ตต๊ฒ ๋ฒํผ, ์๋ฆผ ํ ๊ธ)์ ์ ํฉํฉ๋๋ค.- ๋ทฐ ์ ํ ๋ฒํผ, ํนํ "๋ค์ ์ก์ "์ ํ์ํ๋ ๋จ์ผ ๋ฒํผ์ ๊ฒฝ์ฐ, pressed ์ํ๊ฐ "ํ์ฌ ํ์ฑ ๋ทฐ"๋ฅผ ์๋ฏธํ๋์ง "๋ฒํผ์ด ์ ์ดํ๋ ๊ธฐ๋ฅ"์ ์๋ฏธํ๋์ง ๋ชจํธํฉ๋๋ค.
ํ์ฌ
aria-label์ ์ด๋ฏธ ์๋ฒฝํ๊ฒ ๊ตฌํ๋์ด ์์ต๋๋ค:
- ํ์ฌ ์ํ("ํ์ฌ ๋ฆฌ์คํธ ๋ณด๊ธฐ์ ๋๋ค")
- ์ ํ ์ก์ ("์ง๋๋ก ์ ํํ๋ ค๋ฉด ํด๋ฆญํ์ธ์")
- ์คํฌ๋ฆฐ ๋ฆฌ๋ ์ฌ์ฉ์์๊ฒ ํ์ํ ๋ชจ๋ ์ปจํ ์คํธ ์ ๊ณต
๋ค์๊ณผ ๊ฐ์ด
aria-pressed๋ฅผ ์ ๊ฑฐํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค:<Tag label={viewMode === 'list' ? '์ง๋๋ก ๋ณด๊ธฐ' : '๋ฆฌ์คํธ๋ก ๋ณด๊ธฐ'} icon={viewMode === 'list' ? 'MapPin_' : 'ListButton'} variant="toggle" onClick={onToggleView} - aria-pressed={viewMode === 'list'} aria-label={ viewMode === 'list' ? 'ํ์ฌ ๋ฆฌ์คํธ ๋ณด๊ธฐ์ ๋๋ค. ์ง๋๋ก ์ ํํ๋ ค๋ฉด ํด๋ฆญํ์ธ์.' : 'ํ์ฌ ์ง๋ ๋ณด๊ธฐ์ ๋๋ค. ๋ฆฌ์คํธ๋ก ์ ํํ๋ ค๋ฉด ํด๋ฆญํ์ธ์.' } />์ฐธ๊ณ : WAI-ARIA Authoring Practices์์ ๋ทฐ ์ ํ์ ๊ฒฝ์ฐ ๋ช ํํ
aria-label๋ง์ผ๋ก๋ ์ถฉ๋ถํ๋ค๊ณ ์๋ดํ๊ณ ์์ต๋๋ค.src/pages/map/components/CourseSelectSection.tsx (1)
44-51: ์ด์ ๋ฆฌ๋ทฐ์์ ์ง์ ๋aria-label์ค๋ณต ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์์ต๋๋ค!
aria-label์์ฑ์ด ์ ๊ฑฐ๋์ดCommonButton์ ๋ค์ดํฐ๋ธ ํ ์คํธ๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์คํฌ๋ฆฐ ๋ฆฌ๋์ ์ ๋ฌ๋ฉ๋๋ค.aria-pressed์์ฑ๋ ์ ์ ํ ์ ์ฉ๋์ด ํ ๊ธ ๋ฒํผ ์ํ๋ฅผ ๋ช ํํ ๋ํ๋ ๋๋ค.์ ํ์ ๊ฐ์ ์ฌํญ:
์๋ฏธ๋ก ์ HTML์ ์ํดdiv[role="listitem"]๋์ ๋ค์ดํฐ๋ธ<li>์์ ์ฌ์ฉ์ ๊ณ ๋ คํด๋ณด์ธ์. ARIA ์ญํ ๋ณด๋ค ์๋งจํฑ HTML์ด ์ฐ์ ์๋๋ ๊ฒ์ด ์น ํ์ค ๊ถ์ฅ์ฌํญ์ ๋๋ค.- {Array.isArray(options) && - options.map(({ id, label }) => ( - <div role="listitem" key={id}> + {Array.isArray(options) && + options.map(({ id, label }) => ( + <li key={id}> <CommonButton label={label} aria-pressed={selected === id} variant={selected === id ? 'active' : 'default'} onClick={() => onSelect(selected === id ? null : id)} /> - </div> + </li> ))}๊ทธ๋ฆฌ๊ณ ๋ถ๋ชจ ์ปจํ ์ด๋๋ฅผ
<ul>๋ก ๋ณ๊ฒฝ:- <div - className="flex justify-center gap-[0.8rem] min-w-max" - style={{ WebkitOverflowScrolling: 'touch' }} - role="list" - > + <ul + className="flex justify-center gap-[0.8rem] min-w-max list-none" + style={{ WebkitOverflowScrolling: 'touch' }} + >src/pages/events/index.tsx (1)
49-52: ์ค๋ณต๋ ์ ๊ทผ์ฑ ๋ ์ด๋ธ์ ์ ๊ฑฐํ์ธ์.
<label htmlFor="event-date">์DatePicker์ariaLabel์์ฑ์ด ๋ชจ๋ ์กด์ฌํฉ๋๋ค.DatePicker๋ ๋ค์ดํฐ๋ธ input์ด ์๋ Button ๊ธฐ๋ฐ ์ปดํฌ๋ํธ์ด๋ฏ๋กhtmlFor๊ฐ ์๋ํ์ง ์์ต๋๋ค.ariaLabel๋ง์ผ๋ก ์ถฉ๋ถํ๋ฏ๋ก<label>์์๋ฅผ ์ ๊ฑฐํ์ธ์.- {/* ์คํฌ๋ฆฐ๋ฆฌ๋๊ฐ "๋ ์ง ์ ํ"์ผ๋ก ์ฝํ๋๋ก ์ถ๊ฐ */} - <label htmlFor="event-date" className="sr-only"> - ํ์ฌ ๋ ์ง ์ ํ - </label> <DatePicker ariaLabel="ํ์ฌ ๋ ์ง ์ ํ" value={date} onChange={setDate} />
๐ Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
๐ Files selected for processing (11)
src/pages/chatbot/index.tsx(2 hunks)src/pages/events/components/DateTag.tsx(1 hunks)src/pages/events/index.tsx(2 hunks)src/pages/loading/index.tsx(2 hunks)src/pages/main/components/board/Boardgame.tsx(1 hunks)src/pages/main/components/stampBoard/Stamp.tsx(2 hunks)src/pages/map/components/CourseSelectSection.tsx(1 hunks)src/pages/map/result/components/TagGroup.tsx(1 hunks)src/shared/components/datePicker/DatePicker.tsx(2 hunks)src/shared/components/flipCard/FlipCard.tsx(1 hunks)src/shared/icons/components/icon.tsx(5 hunks)
๐ง Files skipped from review as they are similar to previous changes (5)
- src/pages/chatbot/index.tsx
- src/pages/main/components/stampBoard/Stamp.tsx
- src/pages/events/components/DateTag.tsx
- src/shared/components/flipCard/FlipCard.tsx
- src/pages/main/components/board/Boardgame.tsx
๐งฐ Additional context used
๐งฌ Code graph analysis (1)
src/pages/events/index.tsx (1)
src/shared/components/datePicker/DatePicker.tsx (1)
DatePicker(17-92)
โฐ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build-and-deploy
๐ Additional comments (6)
src/pages/loading/index.tsx (2)
7-12: ์ด์ ๋ฆฌ๋ทฐ ์ง์ ์ฌํญ์ด ์๋ฒฝํ๊ฒ ํด๊ฒฐ๋์์ต๋๋ค!
role="status"์aria-live="polite"์ถ๊ฐ๋กaria-label์ด ์คํฌ๋ฆฐ ๋ฆฌ๋์ ์ฌ๋ฐ๋ฅด๊ฒ ์ ๋ฌ๋ฉ๋๋ค. ๋ก๋ฉ ์ํ๋ฅผ ์ ๊ทผ ๊ฐ๋ฅํ๊ฒ ๋ง๋ ํ๋ฅญํ ๊ฐ์ ์ ๋๋ค.
13-16: ์ฅ์์ฉ ์์์ ๋ํ ์ ๊ทผ์ฑ ์ฒ๋ฆฌ๊ฐ ์ฌ๋ฐ๋ฆ ๋๋ค.SVG ๋ฐฐ๊ฒฝ๊ณผ Lottie ์ ๋๋ฉ์ด์ ์
aria-hidden="true"๋ฅผ ์ถ๊ฐํ์ฌ ์คํฌ๋ฆฐ ๋ฆฌ๋๊ฐ ์ฅ์์ฉ ์์๋ฅผ ๋ฌด์ํ๋๋ก ํ์ต๋๋ค. ์๋ฏธ ์๋ ํ ์คํธ ์ ๋ณด๋aria-label์ ํตํด ์ ๋ฌ๋๋ฏ๋ก ์ ์ ํ ๊ตฌํ์ ๋๋ค.Also applies to: 36-36
src/shared/icons/components/icon.tsx (1)
45-46: ์ด์ ๋ฆฌ๋ทฐ์ ํค๋ณด๋ ์ ๊ทผ์ฑ ์ด์๊ฐ ์๋ฒฝํ๊ฒ ํด๊ฒฐ๋์์ต๋๋ค!
isInteractiveํ๋๊ทธ์ ๋ฐ๋ผ ํค๋ณด๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ๊ตฌํ๋์์ต๋๋ค:
- Enter์ Space ํค๋ก ์์ด์ฝ์ ํ์ฑํํ ์ ์์ต๋๋ค
- Space ํค์
preventDefault()๋ก ํ์ด์ง ์คํฌ๋กค์ ๋ฐฉ์งํฉ๋๋คrole="button",tabIndex={0},aria-pressed์์ฑ์ด ์กฐ๊ฑด๋ถ๋ก ์ ์ฉ๋ฉ๋๋ค- WAI-ARIA ๋ฒํผ ํจํด์ ์ฌ๋ฐ๋ฅด๊ฒ ๋ฐ๋ฅด๊ณ ์์ต๋๋ค
ํค๋ณด๋ ์ฌ์ฉ์๊ฐ ์ด์ ๋ง์ฐ์ค ์ฌ์ฉ์์ ๋์ผํ๊ฒ ์ํธ์์ฉํ ์ ์์ต๋๋ค.
Also applies to: 60-61, 79-85, 119-124
src/shared/components/datePicker/DatePicker.tsx (1)
14-14: DatePicker์ariaLabelprop ์ถ๊ฐ๋ก ์ ๊ทผ์ฑ์ด ํฅ์๋์์ต๋๋ค.๋ ์ง ์ ํ ๋ฒํผ์ ๋ํ ๋ช ์์ ์ธ ์ ๊ทผ ๊ฐ๋ฅํ ๋ ์ด๋ธ์ ์ ๊ณตํ ์ ์๊ฒ ๋์์ต๋๋ค. ๊ตฌํ์ด ๊น๋ํ๊ณ ์ ํ์ prop์ผ๋ก ๊ธฐ์กด ์ฌ์ฉ์ฒ์ ์ํฅ์ ์ฃผ์ง ์์ต๋๋ค.
Also applies to: 22-22, 66-68
src/pages/events/index.tsx (2)
57-63: ์ด๋ฒคํธ ๋ชฉ๋ก ์น์ ์aria-label์ถ๊ฐ๊ฐ ์ ์ ํฉ๋๋ค.
<section aria-label="์ด๋ฒคํธ ๋ชฉ๋ก">์ผ๋ก ์น์ ์ ๋ชฉ์ ์ด ๋ช ํํด์ ธ ์คํฌ๋ฆฐ ๋ฆฌ๋ ์ฌ์ฉ์์ ํ์์ด ๊ฐ์ ๋ฉ๋๋ค.
82-86: ๋น ์ํ์ ๋ํ ์ ๊ทผ์ฑ ์ฒ๋ฆฌ๊ฐ ์ฌ๋ฐ๋ฆ ๋๋ค.
role="status"์aria-live="polite"๋ฅผ ์ฌ์ฉํ์ฌ ํํฐ๋ง ๊ฒฐ๊ณผ๊ฐ ๋น์ด์์ ๋ ์คํฌ๋ฆฐ ๋ฆฌ๋ ์ฌ์ฉ์์๊ฒ ์ ์ ํ ์๋ฆฝ๋๋ค. ๋์ ์ฝํ ์ธ ์ ๋ฐ์ดํธ ์ ๋น์นจ์ ์ ์ธ ๋ฐฉ์์ผ๋ก ์ ๋ณด๋ฅผ ์ ๋ฌํฉ๋๋ค.
There was a problem hiding this comment.
Actionable comments posted: 0
๐งน Nitpick comments (1)
src/shared/components/datePicker/DatePicker.tsx (1)
48-54: ๊ฐ๋ ์ฑ ํฅ์์ ์ํ ๋ฆฌํฉํ ๋ง์ผํญ ์ฐ์ฐ์๋ฅผ ๋ช ์์ ์ธ if/else ๋ธ๋ก์ผ๋ก ๋ณ๊ฒฝํ์ฌ ๋ก์ง์ ์๋๊ฐ ๋ ๋ช ํํด์ก์ต๋๋ค. ๊ธฐ๋ฅ์ ์ผ๋ก๋ ๋์ผํ์ง๋ง ์ฝ๋์ ๊ฐ๋ ์ฑ์ด ๊ฐ์ ๋์์ต๋๋ค.
๐ Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
๐ Files selected for processing (2)
src/shared/components/datePicker/DatePicker.tsx(3 hunks)src/shared/icons/components/icon.tsx(4 hunks)
๐ง Files skipped from review as they are similar to previous changes (1)
- src/shared/icons/components/icon.tsx
โฐ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build-and-deploy
๐ Additional comments (1)
src/shared/components/datePicker/DatePicker.tsx (1)
14-14: ์ ๊ทผ์ฑ ๊ฐ์ ์ ์ํ ariaLabel ์์ฑ ์ถ๊ฐ ์น์ธ
ariaLabel์ต์ ์์ฑ์ ์ถ๊ฐํ๊ณ Button ์ปดํฌ๋ํธ์aria-label๋ก ์ ๋ฌํ ๊ฒ์ ์คํฌ๋ฆฐ ๋ฆฌ๋ ์ฌ์ฉ์์๊ฒ ๋ ๋ช ํํ ์ปจํ ์คํธ๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ ํ์ ์์ฑ์ด๋ฏ๋ก ๊ธฐ์กด ์ฝ๋์์ ํธํ์ฑ๋ ์ ์ง๋๋ฉฐ, React๋undefined๊ฐ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ์ฌ ์์ฑ์ ๋ ๋๋งํ์ง ์์ต๋๋ค.Also applies to: 22-22, 70-72
KongMezu
left a comment
There was a problem hiding this comment.
aria ๊ตฌ์กฐ ์ ์ ์ฉํ์ ๊ฑฐ ๊ฐ์ต๋๋ค! ๋ง์ ์์ด์์ ํ ๋ฐ.. ์ฝ๋ ํ๋ํ๋ ์๊ณ ํ์ จ์ต๋๋ค! ํฐ ๋ฆฌ๋ทฐ๋ ์์ด์ ๋ฐ๋ก approve ํ๊ฒ ์ต๋๋ค!
There was a problem hiding this comment.
์ฌ๊ธฐ ariaLabel?: string; ๋ ๋ฃ์ด์ ์์ด์ฝ ํ๋ํ๋๋ ์คํฌ๋ฆฐ๋ฆฌ๋ ์ ์ฉํ๋ฉด ์ด๋จ๊น์?
There was a problem hiding this comment.
์ด ๋ถ๋ถ์ ์ถ๊ฐ๋ก ๋ฃ์ด๋ณด๊ฒ ์ต๋๋ค:)
๐ฅ ์์ ๋ด์ฉ
aria-label,role,aria-describedby๋ฑ ์๋งจํฑ ์ ๊ทผ์ฑ ์์ฑ ์ถ๊ฐsr-onlyํด๋์ค ํ์ฉโ ๋ณ๋ ์คํ์ผ๋ง ๋ถํ์ (Tailwind ๊ธฐ๋ณธ ๋ด์ฅ ์คํ์ผ ์ฌ์ฉ)
aria-live์ถ๊ฐ๋ก ๋์ ์ฝํ ์ธ ๋์role="group",aria-labelledby๊ตฌ์กฐ๋ก ํผยท๋ฒํผ ๊ด๊ณ ๋ช ํํ๋ฆฌํฉํ ๋ง ๋ชฉ์
โ๏ธ ๊ธฐ์ ํฌ์ธํธ
๐ค ์ถํ ์์ ์ฌํญ
๐ ๊ด๋ จ ์ด์
PR Point (To Reviewer)
aria-*์์ฑ ์ ์ฉ ์, UI๋ ์ธํฐ๋์ ์ ์ํฅ์ด ์๋์ง ํ์ธ ๋ถํ๋๋ฆฝ๋๋ค.sr-only์ ์ฉ๋ ๋ถ๋ถ์ ์๋(์คํฌ๋ฆฐ๋ฆฌ๋์ฉ ์ค๋ช ) ํ์ธ ๋ถํ๋๋ฆฝ๋๋ค.role๋ถ์ฌ ๋ฒ์๊ฐ ๋ ผ๋ฆฌ์ ์ผ๋ก ์ ์ ํ์ง ๊ฒํ ๋ฐ๋๋๋ค.๐ธ ํผ๊ทธ๋ง ์คํฌ๋ฆฐ์ท or ๊ธฐ๋ฅ GIF
Summary by CodeRabbit
๋ฆด๋ฆฌ์ค ๋ ธํธ
์๋ก์ด ๊ธฐ๋ฅ
๊ฐ์ ์ฌํญ