Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,27 @@
# self-paced-enhance-usability
# self-paced-enhance-usability

- [ ] 스크린 리더로 성인 승객 수를 늘리거나 줄일 수 있어야 한다.
- [ ] 인원 수는 최소 1명, 최대 3명까지만 가능하게 구현한다.
- [ ] 승객 수를 늘리는 경우 실제 스크린 리더는 아래와 같이 읽을 수 있어야 한다.

## Step 1: 언어 설정하기

- [x] `index.html` 파일에 html 태그 lang 속성에 `lang='ko'` 로 변경

## Step 2: 시맨틱 태그 사용하기

- [x] `App.tsx` 파일에 시멘틱 태그 적용

## Step 3: 버튼 접근성 향상시키기

- [x] `FlightBooking` 컴포넌트에 `button` 요소 `aria-label` 속성 추가

## Step 4: 변경 사항에 대한 실시간 알림 추가하기

- [x] `FlightBooking` 컴포넌트에 `span` 요소 `aria-live` 속성 추가
- `polite`: 현재 스크린 리더가 다른 작업을 수행하고 있다면, 해당 작업이 완료된 후 콘텐츠 변경 사항을 알림
- `assertive`: 콘텐츠 변경이 발생하면 현재 스크린 리더의 작업 여부와 상관없이 즉시 사용자에게 알림

## Step 5: 최소/최대 값 도달 시 상태 메시지 알림 추가하기

- [x] `alertMessage` 상태에 최소/최대 메시지를 저장시키고 조건부 렌더링으로 보이지 않는 요소를 렌더링, 스크린 리더기에는 읽히도록 구현
26 changes: 12 additions & 14 deletions a11y/index.html
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
<!doctype html>
<html lang="en">

<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Accessibility</title>
</head>

<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Accessibility</title>
</head>

<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
14 changes: 7 additions & 7 deletions a11y/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import "./Typography.css";
import "./App.css";
import './Typography.css';
import './App.css';

import FlightBooking from "./components/FlightBooking";
import FlightBooking from './components/FlightBooking';

function App() {
return (
<div className="app">
<div className="app-main">
<div className="flight-booking-container">
<main className="app-main">
<section className="flight-booking-container">
<FlightBooking />
</div>
</div>
</section>
</main>
</div>
);
}
Expand Down
14 changes: 13 additions & 1 deletion a11y/src/components/FlightBooking.css
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
width: 30px;
height: 30px;
border-radius: 16px;
border: 1px solid #C0C0C0;
border: 1px solid #c0c0c0;
background-color: #fff;
cursor: pointer;
display: flex;
Expand All @@ -61,3 +61,15 @@
border-radius: 4px;
cursor: pointer;
}

.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
35 changes: 30 additions & 5 deletions a11y/src/components/FlightBooking.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
import { useState } from "react";
import { useState } from 'react';

import "./FlightBooking.css";
import './FlightBooking.css';

const MAX_PASSENGERS = 3;
const MIN_PASSENGERS = 1;

const FlightBooking = () => {
const [adultCount, setAdultCount] = useState(1);
const [alertMessage, setAlertMessage] = useState('');

const incrementCount = () => {
if (adultCount >= MAX_PASSENGERS) {
setAlertMessage('최대 승객 수에 도달했습니다.');
return;
}

setAdultCount((prev) => Math.min(MAX_PASSENGERS, prev + 1));
};

const decrementCount = () => {
if (adultCount === MIN_PASSENGERS) {
setAlertMessage('최소 승객 수에 도달했습니다.');
return;
}

setAdultCount((prev) => Math.max(1, prev - 1));
};

Expand All @@ -21,15 +33,28 @@ const FlightBooking = () => {
<div className="passenger-count">
<span className="body-text">성인</span>
<div className="counter">
<button className="button-text" onClick={decrementCount}>
<button
className="button-text"
onClick={decrementCount}
aria-label="성인 승객 감소"
>
-
</button>
<span>{adultCount}</span>
<button className="button-text" onClick={incrementCount}>
<span aria-live="polite">{adultCount}</span>
<button
className="button-text"
onClick={incrementCount}
aria-label="성인 승객 증가"
>
+
</button>
</div>
</div>
{alertMessage && (
<div className="visually-hidden" role="alert">
{alertMessage}
</div>
)}
<button className="search-button">항공편 검색</button>
</div>
);
Expand Down