diff --git a/README.md b/README.md index 002f489..3bfbcb6 100644 --- a/README.md +++ b/README.md @@ -1 +1,27 @@ -# self-paced-enhance-usability \ No newline at end of file +# 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` 상태에 최소/최대 메시지를 저장시키고 조건부 렌더링으로 보이지 않는 요소를 렌더링, 스크린 리더기에는 읽히도록 구현 diff --git a/a11y/index.html b/a11y/index.html index 12fa3e7..e525729 100644 --- a/a11y/index.html +++ b/a11y/index.html @@ -1,16 +1,14 @@ - - - - - - - - Accessibility - - - -
- - + + + + + + + Accessibility + + +
+ + diff --git a/a11y/src/App.tsx b/a11y/src/App.tsx index a8159f9..8c8ebb8 100644 --- a/a11y/src/App.tsx +++ b/a11y/src/App.tsx @@ -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 (
-
-
+
+
-
-
+ +
); } diff --git a/a11y/src/components/FlightBooking.css b/a11y/src/components/FlightBooking.css index d9d6083..5235c41 100644 --- a/a11y/src/components/FlightBooking.css +++ b/a11y/src/components/FlightBooking.css @@ -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; @@ -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; +} diff --git a/a11y/src/components/FlightBooking.tsx b/a11y/src/components/FlightBooking.tsx index 313cab3..e3f98a5 100644 --- a/a11y/src/components/FlightBooking.tsx +++ b/a11y/src/components/FlightBooking.tsx @@ -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)); }; @@ -21,15 +33,28 @@ const FlightBooking = () => {
성인
- - {adultCount} -
+ {alertMessage && ( +
+ {alertMessage} +
+ )} );