Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[항공사 웹사이트의 컴포넌트 접근성 높이기 - 1단계] 비녀(강윤호) 미션 제출합니다. #52

Merged
merged 16 commits into from Oct 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 35 additions & 0 deletions package.json
@@ -0,0 +1,35 @@
{
"name": "a11y-airline",
"version": "1.0.0",
"main": "index.js",
"repository": "https://github.com/KangYunHo1221/a11y-airline",
"author": "Yunho <ansghkdbsgh@gmail.com>",
"license": "MIT",
"scripts": {
"start": "webpack serve --open",
"build": "webpack --mode=production",
"deploy": "gh-pages -d dist"
},
"devDependencies": {
"@types/node": "^18.8.2",
"@types/react": "^18.0.21",
"@types/react-dom": "^18.0.6",
"css-loader": "^6.7.1",
"html-webpack-plugin": "^5.5.0",
"mini-css-extract-plugin": "^2.6.1",
"ts-loader": "^9.4.1",
"typescript": "^4.8.4",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.11.1",
"gh-pages": "^4.0.0"
},
"dependencies": {
"@types/styled-components": "^5.1.26",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.4.1",
"styled-components": "^5.3.6"
},
"homepage": "."
}
17 changes: 17 additions & 0 deletions public/index.html
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="keyword" content="미션, 항공사, 웹사이트, 접근성" />
<meta name="description" content="미션: 항공사 웹사이트 컴포넌트의 접근성 높이기" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://capable-pixie-ad7eb2.netlify.app/" />
<meta property="og:title" content="a11y-airline" />
<meta property="og:description" content="미션: 항공사 웹사이트 컴포넌트의 접근성 높이기" />
<title>웹 접근성 미션</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
14 changes: 14 additions & 0 deletions src/App.tsx
@@ -0,0 +1,14 @@
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import FirstPage from './pages/FirstPage';

const App = () => {
return (
<BrowserRouter>
<Routes>
<Route path='/' element={<FirstPage />} />
</Routes>
</BrowserRouter>
);
};

export default App;
117 changes: 117 additions & 0 deletions src/Pages/FirstPage.tsx
@@ -0,0 +1,117 @@
import { useState } from 'react';
import styled from 'styled-components';
import Tooltip from '../components/Tooltip';

const FirstPage = () => {
const [count, setCount] = useState<number>(1);

const countUp = () => {
setCount((prev) => {
if (prev + 1 <= 3) {
return prev + 1;
}
return prev;
});
};

const countDown = () => {
setCount((prev) => {
if (prev - 1 >= 1) {
return prev - 1;
}
return prev;
});
};

const handleCountChange = (e: React.KeyboardEvent<HTMLInputElement>) => {
const input = Number(e.key);

if (input >= 1 && input <= 3) {
setCount(input);
}
};

const makeText = () => {
const text = `성인 승객이 ${count}으로 변경됐습니다`;
return text;
};
return (
<S.PageWrapper>
<h1>승객 선택</h1>
<S.SubtitleWrapper>
<h2>성인</h2>
<Tooltip />
</S.SubtitleWrapper>
<S.ControlWrapper>
<S.Button aria-label='성인 탑승자 한명 줄이기' onClick={countDown}>
-
</S.Button>
<S.Count
type='number'
min={1}
max={3}
Comment on lines +49 to +52
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 속성을 추가했을 때와 하지 않았을 때 동작이 동작이 똑같은데 추가하신 이유가 있나요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

min max를 추가해주면 스크린 리더가 읽어줄때 min max를 알려줍니다.
js로도 제한이 가능하지만 명시해주는게 더 시맨틱하다고 판단했습니다

onKeyDown={(e) => {
handleCountChange(e);
}}
value={count}
/>
<S.Button aria-label='성인 탑승자 한명 늘리기' onClick={countUp}>
+
</S.Button>
<S.HiddenText>{makeText()}</S.HiddenText>
</S.ControlWrapper>
</S.PageWrapper>
);
};

const S = {
PageWrapper: styled.div`
height: 300px;
width: 250px;
border: 2px solid gray;
display: flex;
flex-direction: column;
gap: 20px;
align-items: center;
`,
SubtitleWrapper: styled.div`
position: relative;
display: flex;
align-items: center;
gap: 4px;
`,
Button: styled.button`
width: 30px;
height: 30px;
border: 1px solid #b8b8b8;
border-radius: 50%;
font-size: 22px;
background-color: transparent;
cursor: pointer;
`,
Count: styled.input`
width: 32px;
text-align: center;
font-size: 24px;
border: none;
border-bottom: 2px solid #6d6d6d;
outline: none;

::-webkit-outer-spin-button,
::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
`,
ControlWrapper: styled.div`
display: flex;
align-items: center;
gap: 10px;
`,
HiddenText: styled.div.attrs({ role: 'status', 'aria-live': 'assertive', 'aria-relevant': 'additions' })`
position: absolute;
text-indent: -9999px;
`,
};

export default FirstPage;
42 changes: 42 additions & 0 deletions src/components/Tooltip.tsx
@@ -0,0 +1,42 @@
import styled from 'styled-components';

const Tooltip = () => {
return (
<>
<S.Question aria-label='tooltip'>?</S.Question>
<S.StyledTooltip aria-live='assertive' id='tooltip' role='tooltip'>
국민은행 61210204071715로 후원해 결식아동을 도와보세요!
Copy link

@kamwoo kamwoo Oct 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

큰일납니다. 👮‍♂️

</S.StyledTooltip>
</>
);
};

const S = {
Question: styled.button`
width: 20px;
height: 20px;
border: 1px solid #cbcbcb;
color: #cbcbcb;
border-radius: 50%;
text-align: center;
cursor: help;
background-color: white;

&:hover + [role='tooltip'],
&:focus + [role='tooltip'] {
display: block !important;
background-color: red;
}
`,
StyledTooltip: styled.div`
display: ${(props) => (props.role === 'tooltip' ? 'none' : 'block')};

position: absolute;
top: -3rem;
left: 4rem;
padding: 4px;
color: white;
`,
};

export default Tooltip;
7 changes: 7 additions & 0 deletions src/index.tsx
@@ -0,0 +1,7 @@
import { createRoot } from 'react-dom/client';
import App from './App';

const container = document.getElementById('root')!;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 뒤에 !는 처음보는데 뭐하는 건가요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

무조건 null이나 undefined 아니라는 뜻입니다.
그냥 쓰면 document.getElement return 값이 있다는 것을 명시해줍니다. 없으면 type guard 해줘야해요

image
출처:https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html

const root = createRoot(container);

root.render(<App />);
16 changes: 16 additions & 0 deletions tsconfig.json
@@ -0,0 +1,16 @@
{
"compileOnSave": true,
"compilerOptions": {
"target": "es6",
"module": "esnext",
"strict": true,
"allowJs": true,
"lib": ["dom", "dom.iterable", "esnext"],
"jsx": "react-jsx",
"skipLibCheck": true,
"incremental": true,
"moduleResolution": "node"
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
35 changes: 35 additions & 0 deletions webpack.config.js
@@ -0,0 +1,35 @@
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
entry: './src/index.tsx',
devServer: {
compress: true,
port: 3000,
},
module: {
rules: [
{
test: /\.tsx?$/,
use: [{ loader: 'ts-loader' }],
exclude: /node_modules/,
},
{
test: /\.module.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
filename: 'bundle[hash].js',
clean: true,
path: path.resolve(__dirname, 'dist'),
},
mode: 'production',
plugins: [new HtmlWebpackPlugin({ template: './public/index.html' }), new MiniCssExtractPlugin()],
performance: { hints: false },
};