Skip to content

Commit a0781d3

Browse files
brody-0125claude
andauthored
웹 접근성 강화: aria-hidden, aria-label, 포커스 표시기, 대비 개선 (#51)
- 모든 장식용 Material Symbol 아이콘에 aria-hidden="true" 추가 (StatusSummaryBar, StationCard, ExternalMapLinks, DataFreshnessBar, ThemeToggle, ContactModal, About/Archive/Route 페이지 등) - 장식용 이모지(✏️, 🔍, ⚠️)에 aria-hidden="true" 추가 - archive, route, about 페이지 nav 요소에 aria-label="상단 탐색" 추가 - SearchInput: focus:ring-0을 focus:ring-2로 변경하여 포커스 표시기 복원 - SearchInput, DevSettingsPanel: placeholder 투명도(/60) 제거로 대비 개선 - StationDetailClient: 로딩 스피너에 role="status" 및 aria-label 추가 https://claude.ai/code/session_01RjRxnGfDyE5Vs4Xmzi3Jd3 Co-authored-by: Claude <noreply@anthropic.com>
1 parent a5f5aa5 commit a0781d3

13 files changed

Lines changed: 38 additions & 38 deletions

File tree

web/src/app/about/page.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@ export default function AboutPage() {
77
return (
88
<>
99
{/* Navbar */}
10-
<nav className="bg-surface border-b border-border">
10+
<nav className="bg-surface border-b border-border" aria-label="상단 탐색">
1111
<div className="max-w-5xl mx-auto px-4 md:px-8 h-16 flex items-center justify-between">
1212
<Link href="/" className="flex items-center gap-2 text-status-operating hover:opacity-80 transition-opacity">
13-
<span className="material-symbols-outlined text-3xl">subway</span>
13+
<span className="material-symbols-outlined text-3xl" aria-hidden="true">subway</span>
1414
<span className="font-serif font-bold text-xl text-text-primary tracking-tight">나들이</span>
1515
</Link>
1616
<div className="flex items-center gap-3">
1717
<ThemeToggle />
1818
<Link href="/" className="text-sm text-text-secondary hover:text-status-operating transition-colors flex items-center gap-1">
1919
홈으로
20-
<span className="material-symbols-outlined text-base">arrow_forward</span>
20+
<span className="material-symbols-outlined text-base" aria-hidden="true">arrow_forward</span>
2121
</Link>
2222
</div>
2323
</div>
@@ -27,7 +27,7 @@ export default function AboutPage() {
2727
{/* Header */}
2828
<div className="text-center mb-12">
2929
<div className="inline-flex items-center justify-center w-16 h-16 bg-status-operating/10 rounded-full mb-6">
30-
<span className="material-symbols-outlined text-status-operating text-3xl">handshake</span>
30+
<span className="material-symbols-outlined text-status-operating text-3xl" aria-hidden="true">handshake</span>
3131
</div>
3232
<h1 className="font-serif text-3xl md:text-4xl font-bold text-text-primary mb-3">
3333
데이터 출처 및 투명성
@@ -68,15 +68,15 @@ export default function AboutPage() {
6868
<div className="grid grid-cols-3 divide-x divide-border">
6969
<div className="p-5">
7070
<div className="flex items-center gap-1.5 text-text-secondary text-xs mb-1">
71-
<span className="material-symbols-outlined text-xs">settings</span>
71+
<span className="material-symbols-outlined text-xs" aria-hidden="true">settings</span>
7272
출처
7373
</div>
7474
<p className="font-mono text-lg font-medium text-text-primary">서울 지하철</p>
7575
<span className="text-xs text-status-operating font-medium">공식 API</span>
7676
</div>
7777
<div className="p-5">
7878
<div className="flex items-center gap-1.5 text-text-secondary text-xs mb-1">
79-
<span className="material-symbols-outlined text-xs">speed</span>
79+
<span className="material-symbols-outlined text-xs" aria-hidden="true">speed</span>
8080
지연 시간
8181
</div>
8282
<p className="font-mono text-lg font-medium text-text-primary">&lt; 60s</p>
@@ -95,7 +95,7 @@ export default function AboutPage() {
9595
{/* Accuracy Note */}
9696
<div className="border-l-4 border-status-maintenance bg-status-maintenance-bg rounded-lg p-5">
9797
<div className="flex items-center gap-2 mb-2">
98-
<span className="material-symbols-outlined text-status-maintenance text-base">warning</span>
98+
<span className="material-symbols-outlined text-status-maintenance text-base" aria-hidden="true">warning</span>
9999
<span className="font-bold text-text-primary">정확성에 관한 안내</span>
100100
</div>
101101
<p className="text-sm text-text-secondary leading-relaxed">

web/src/app/archive/page.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,21 @@ import Link from 'next/link';
55
export default function ArchivePage() {
66
return (
77
<>
8-
<nav className="bg-surface-cream border-b border-border-cream">
8+
<nav className="bg-surface-cream border-b border-border-cream" aria-label="상단 탐색">
99
<div className="max-w-5xl mx-auto px-4 md:px-8 h-16 flex items-center justify-between">
1010
<Link href="/" className="flex items-center gap-2 text-primary hover:opacity-80 transition-opacity">
11-
<span className="material-symbols-outlined text-3xl">subway</span>
11+
<span className="material-symbols-outlined text-3xl" aria-hidden="true">subway</span>
1212
<span className="font-serif font-bold text-xl text-text-main tracking-tight">나들이</span>
1313
</Link>
1414
<Link href="/" className="text-sm text-text-muted hover:text-primary transition-colors flex items-center gap-1">
1515
대시보드로 돌아가기
16-
<span className="material-symbols-outlined text-base">arrow_forward</span>
16+
<span className="material-symbols-outlined text-base" aria-hidden="true">arrow_forward</span>
1717
</Link>
1818
</div>
1919
</nav>
2020
<main className="flex-1 w-full max-w-3xl mx-auto px-4 md:px-8 py-16 text-center">
2121
<div className="inline-flex items-center justify-center w-16 h-16 bg-primary/10 rounded-full mb-6">
22-
<span className="material-symbols-outlined text-primary text-3xl">inventory_2</span>
22+
<span className="material-symbols-outlined text-primary text-3xl" aria-hidden="true">inventory_2</span>
2323
</div>
2424
<h1 className="font-serif text-3xl font-bold text-text-main mb-3">데이터 아카이브</h1>
2525
<p className="font-serif text-lg text-text-muted italic mb-8">준비 중</p>

web/src/app/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ export default function HomePage() {
141141
<ThemeToggle />
142142
</nav>
143143
<div className="py-12 text-center">
144-
<p className="text-4xl mb-3">✏️</p>
144+
<p className="text-4xl mb-3" aria-hidden="true">✏️</p>
145145
<p className="mb-2 font-serif text-base font-bold text-text-primary">
146146
더 입력하면 검색 결과가 표시됩니다
147147
</p>
@@ -183,7 +183,7 @@ export default function HomePage() {
183183
))}
184184
{filteredStations.length === 0 && (
185185
<div className="py-12 text-center">
186-
<p className="text-4xl mb-3">🔍</p>
186+
<p className="text-4xl mb-3" aria-hidden="true">🔍</p>
187187
<p className="mb-2 font-serif text-base font-bold text-text-primary">
188188
&lsquo;{query.trim()}&rsquo;와 일치하는 역이 없어요
189189
</p>

web/src/app/route/page.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,21 @@ import Link from 'next/link';
55
export default function RoutePage() {
66
return (
77
<>
8-
<nav className="bg-surface-cream border-b border-border-cream">
8+
<nav className="bg-surface-cream border-b border-border-cream" aria-label="상단 탐색">
99
<div className="max-w-5xl mx-auto px-4 md:px-8 h-16 flex items-center justify-between">
1010
<Link href="/" className="flex items-center gap-2 text-primary hover:opacity-80 transition-opacity">
11-
<span className="material-symbols-outlined text-3xl">subway</span>
11+
<span className="material-symbols-outlined text-3xl" aria-hidden="true">subway</span>
1212
<span className="font-serif font-bold text-xl text-text-main tracking-tight">나들이</span>
1313
</Link>
1414
<Link href="/" className="text-sm text-text-muted hover:text-primary transition-colors flex items-center gap-1">
1515
대시보드로 돌아가기
16-
<span className="material-symbols-outlined text-base">arrow_forward</span>
16+
<span className="material-symbols-outlined text-base" aria-hidden="true">arrow_forward</span>
1717
</Link>
1818
</div>
1919
</nav>
2020
<main className="flex-1 w-full max-w-3xl mx-auto px-4 md:px-8 py-16 text-center">
2121
<div className="inline-flex items-center justify-center w-16 h-16 bg-primary/10 rounded-full mb-6">
22-
<span className="material-symbols-outlined text-primary text-3xl">map</span>
22+
<span className="material-symbols-outlined text-primary text-3xl" aria-hidden="true">map</span>
2323
</div>
2424
<h1 className="font-serif text-3xl font-bold text-text-main mb-3">경로 안내</h1>
2525
<p className="font-serif text-lg text-text-muted italic mb-8">준비 중</p>

web/src/app/station/[code]/StationDetailClient.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,8 @@ export default function StationDetailClient({ code }: { code: string }) {
153153
)}
154154

155155
{!data && !error && (
156-
<div className="flex flex-col items-center justify-center py-16 gap-3">
157-
<div className="w-8 h-8 border-2 border-status-operating/30 border-t-status-operating rounded-full animate-spin" />
156+
<div role="status" aria-label="데이터 로딩 중" className="flex flex-col items-center justify-center py-16 gap-3">
157+
<div className="w-8 h-8 border-2 border-status-operating/30 border-t-status-operating rounded-full animate-spin" aria-hidden="true" />
158158
<p className="text-text-secondary text-sm">역 정보를 가져오고 있어요...</p>
159159
</div>
160160
)}
@@ -164,7 +164,7 @@ export default function StationDetailClient({ code }: { code: string }) {
164164
{/* Fault Banner */}
165165
{hasFault && (
166166
<div className="bg-status-fault-bg border border-status-fault-border rounded-xl p-4 mt-4 flex gap-3 items-start">
167-
<span className="text-lg shrink-0 mt-0.5">⚠️</span>
167+
<span className="text-lg shrink-0 mt-0.5" aria-hidden="true">⚠️</span>
168168
<div className="text-[13px] leading-relaxed text-status-fault">
169169
<strong>
170170
{faultDetails.length === 1
@@ -211,7 +211,7 @@ export default function StationDetailClient({ code }: { code: string }) {
211211
>
212212
<div className="flex items-center justify-between mb-1">
213213
<div className="flex items-center gap-2">
214-
<span className="material-symbols-outlined text-text-secondary text-lg">
214+
<span className="material-symbols-outlined text-text-secondary text-lg" aria-hidden="true">
215215
{FACILITY_TYPE_ICONS[type]}
216216
</span>
217217
<span className="font-serif font-semibold text-[14px] text-text-primary">

web/src/components/ContactModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ export default function ContactModal({ isOpen, onClose, onSubmit }: ContactModal
322322
>
323323
{status === 'loading' ? (
324324
<>
325-
<span className="inline-block h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent" />
325+
<span className="inline-block h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent" aria-hidden="true" />
326326
<span>전송 중...</span>
327327
</>
328328
) : status === 'success' ? (

web/src/components/DataFreshnessBar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export default function DataFreshnessBar({ updatedAt, isStale }: DataFreshnessBa
3232
<div className="flex items-center gap-2">
3333
{isStale ? (
3434
<>
35-
<span className="material-symbols-outlined text-base text-status-fault">warning</span>
35+
<span className="material-symbols-outlined text-base text-status-fault" aria-hidden="true">warning</span>
3636
<p className="font-mono text-xs font-medium tracking-tight text-status-fault sm:text-sm">
3737
{relativeTime} 데이터 · 현장 확인 권장
3838
</p>

web/src/components/DevSettingsPanel.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export default function DevSettingsPanel({ onSettingsChange }: { onSettingsChang
9393
value={key}
9494
onChange={(e) => setKey(e.target.value)}
9595
placeholder="인증키 입력"
96-
className="flex-1 px-3 py-2 text-sm border border-border-cream rounded-sm bg-bg text-text-primary placeholder:text-text-secondary/60 focus:outline-2 focus:outline-status-operating focus:outline-offset-1 font-mono"
96+
className="flex-1 px-3 py-2 text-sm border border-border-cream rounded-sm bg-bg text-text-primary placeholder:text-text-secondary focus:outline-2 focus:outline-status-operating focus:outline-offset-1 font-mono"
9797
/>
9898
<button
9999
onClick={handleKeySave}

web/src/components/ExternalMapLinks.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export default function ExternalMapLinks({ station }: ExternalMapLinksProps) {
2828
aria-label={`네이버 지도에서 ${station.name}역 길찾기 열기 (외부 앱)`}
2929
>
3030
네이버 길찾기
31-
<span className="material-symbols-outlined text-sm">open_in_new</span>
31+
<span className="material-symbols-outlined text-sm" aria-hidden="true">open_in_new</span>
3232
</a>
3333
<a
3434
href={buildKakaoDirectionsUrl(params)}
@@ -38,7 +38,7 @@ export default function ExternalMapLinks({ station }: ExternalMapLinksProps) {
3838
aria-label={`카카오맵에서 ${station.name}역 길찾기 열기 (외부 앱)`}
3939
>
4040
카카오 길찾기
41-
<span className="material-symbols-outlined text-sm">open_in_new</span>
41+
<span className="material-symbols-outlined text-sm" aria-hidden="true">open_in_new</span>
4242
</a>
4343
</div>
4444
</div>

web/src/components/SearchInput.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export default function SearchInput({ value, onChange, compact }: SearchInputPro
4949
onKeyDown={handleKeyDown}
5050
placeholder="역 이름을 입력하세요 (예: 강남, 서울역)"
5151
aria-label="지하철역 검색"
52-
className="block w-full rounded-md border border-border bg-bg py-2 pl-10 pr-20 font-sans text-text-primary transition-colors placeholder:text-text-secondary focus:border-border-strong focus:outline-none focus:ring-0"
52+
className="block w-full rounded-md border border-border bg-bg py-2 pl-10 pr-20 font-sans text-text-primary transition-colors placeholder:text-text-secondary focus:border-border-strong focus:outline-none focus:ring-2 focus:ring-status-operating/30"
5353
/>
5454
<div className="absolute inset-y-0 right-0 flex items-center gap-0.5 pr-1">
5555
{localValue && (
@@ -90,7 +90,7 @@ export default function SearchInput({ value, onChange, compact }: SearchInputPro
9090
onKeyDown={handleKeyDown}
9191
placeholder="역 이름을 입력하세요 (예: 강남, 서울역)"
9292
aria-label="지하철역 검색"
93-
className="block h-[52px] w-full rounded-xl border-2 border-border bg-surface pl-12 pr-14 font-sans text-lg text-text-primary shadow-xs outline-none transition-colors placeholder:text-text-secondary/60 focus:border-status-operating focus:ring-0"
93+
className="block h-[52px] w-full rounded-xl border-2 border-border bg-surface pl-12 pr-14 font-sans text-lg text-text-primary shadow-xs outline-none transition-colors placeholder:text-text-secondary focus:border-status-operating focus:ring-2 focus:ring-status-operating/30"
9494
/>
9595
<button
9696
type="submit"

0 commit comments

Comments
 (0)