diff --git a/a11y/.nvmrc b/a11y/.nvmrc new file mode 100644 index 0000000..4f2a661 --- /dev/null +++ b/a11y/.nvmrc @@ -0,0 +1 @@ +v21.1.0 \ No newline at end of file diff --git a/a11y/index.html b/a11y/index.html index 12fa3e7..fba0804 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..1ebdee0 100644 --- a/a11y/src/App.tsx +++ b/a11y/src/App.tsx @@ -6,11 +6,11 @@ import FlightBooking from "./components/FlightBooking"; function App() { return (
-
+
-
+
); } diff --git a/a11y/src/components/FlightBooking.css b/a11y/src/components/FlightBooking.css index d9d6083..fb80d3c 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; } + +.aria-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..bfb995c 100644 --- a/a11y/src/components/FlightBooking.tsx +++ b/a11y/src/components/FlightBooking.tsx @@ -1,37 +1,73 @@ -import { useState } from "react"; +import { useEffect, useRef, useState } from "react"; import "./FlightBooking.css"; const MAX_PASSENGERS = 3; +const MIN_PASSENGERS = 1; + +const getMessage = (count: number) => { + if (count === MAX_PASSENGERS) return "최대 승객 수에 도달했습니다."; + if (count === MIN_PASSENGERS) return "최소 승객 수는 1명입니다."; + return `성인 승객 ${count}명`; +}; const FlightBooking = () => { const [adultCount, setAdultCount] = useState(1); + const [message, setMessage] = useState(getMessage(1)); + const messageRef = useRef(null); - const incrementCount = () => { - setAdultCount((prev) => Math.min(MAX_PASSENGERS, prev + 1)); + const adjustCount = (change: number) => { + setAdultCount((prevCount) => { + const newCount = prevCount + change; + setMessage(getMessage(newCount)); + return newCount; + }); }; - const decrementCount = () => { - setAdultCount((prev) => Math.max(1, prev - 1)); - }; + useEffect(() => { + if (messageRef.current) { + messageRef.current.focus(); + } + }, [message]); return ( -
+

항공권 예매

성인
- - {adultCount} -
+
+ {message} +
-
+ ); }; diff --git a/a11y/tsconfig.app.json b/a11y/tsconfig.app.json index f0a2350..17d328e 100644 --- a/a11y/tsconfig.app.json +++ b/a11y/tsconfig.app.json @@ -7,8 +7,8 @@ "skipLibCheck": true, /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, + "moduleResolution": "Node", + // "allowImportingTsExtensions": true, "isolatedModules": true, "moduleDetection": "force", "noEmit": true, diff --git a/a11y/tsconfig.node.json b/a11y/tsconfig.node.json index 0d3d714..7f9c44d 100644 --- a/a11y/tsconfig.node.json +++ b/a11y/tsconfig.node.json @@ -1,13 +1,13 @@ { "compilerOptions": { "target": "ES2022", - "lib": ["ES2023"], + "lib": ["ESNext"], "module": "ESNext", "skipLibCheck": true, /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, + "moduleResolution": "Node", + // "allowImportingTsExtensions": true, "isolatedModules": true, "moduleDetection": "force", "noEmit": true, diff --git a/a11y/vite.config.ts b/a11y/vite.config.ts index 9cc50ea..d8d4e6c 100644 --- a/a11y/vite.config.ts +++ b/a11y/vite.config.ts @@ -4,4 +4,7 @@ import react from "@vitejs/plugin-react"; // https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], + server: { + host: "0.0.0.0", + }, });