React를 사용한 채팅 애플리케이션에서 메시지 입력과 이미지 업로드를 처리하는 컴포넌트의 코드입니다.
export function SendMessage() {
....
const handleKeyDown = (e: KeyboardEvent<HTMLLabelElement>) => {
if (e.key === 'Enter') {
const fileInput = document.getElementById('file') as HTMLInputElement;
fileInput.click();
}
};
return (
<form className={classes.input} onSubmit={handleSendMessage}>
<div className={classes.sendInput}>
<label htmlFor="message" className="a11yHidden">
메세지 입력
</label>
<input
type="text"
name="text"
id="message"
value={input}
aria-label="메시지 입력"
placeholder="메시지를 입력하세요."
onChange={(e) => setInput(e.target.value)}
required
/>
</div>
<div className={classes.sendBtn}>
<input
type="file"
id="file"
name="file"
accept="image/*"
onChange={(e) => setImg(e.target.files[0])}
aria-label="이미지 업로드 버튼"
tabIndex={-1}
/>
<label
htmlFor="file"
tabIndex={0}
onKeyDown={handleKeyDown}
role="button"
aria-label="이미지 업로드 버튼"
>
<img src={Img} alt="이미지 업로드 버튼" />
</label>
<button type="submit" aria-label="메세지 보내기 버튼">
⌲
</button>
</div>
</form>
);
}
이미지 업로드 버튼은 라벨과 이미지 아이콘으로 구성되어 있습니다. 라벨은 실제 파일 업로드 버튼(input 엘리먼트)을 레이블링하며, tabIndex 속성을 -1로 설정하여 키보드 포커스 이동을 막습니다. 대신 라벨에 tabIndex 속성을 지정하여 키보드로 이미지 업로드 버튼을 누를 수 있도록 합니다. 라벨에는 handleKeyDown 함수가 onKeyDown 이벤트에 바인딩되어 있어, 엔터키가 눌리면 실제 파일 업로드 버튼을 클릭하도록 처리합니다.
마지막으로, 모든 엘리먼트에는 aria-label 속성이 지정되어 스크린 리더 사용자가 쉽게 이해할 수 있는 라벨링이 제공됩니다. a11yHidden 클래스를 사용하여 시각적으로는 보이지 않지만, 스크린 리더에서는 읽히는 라벨링도 제공됩니다.
.input {
background: var(--gray-100);
width: 100%;
height: 50px;
padding: 10px;
display: flex;
align-items: center;
justify-content: space-between;
border-radius: 8px;
border: 2px solid var(--gray-500);
.sendInput {
width: 100%;
}
input {
width: 100%;
padding: 0.8rem;
margin-left: -10px;
color: var(--black);
font-size: 18px;
&:focus {
border-radius: 12px;
border: 2px solid var(--accent);
}
&::placeholder {
color: var(--gray-600);
}
}
.sendBtn {
display: flex;
align-items: flex-start;
gap: 10px;
input[type='file'] {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
label {
display: inline-block;
width: 36px;
height: 36px;
cursor: pointer;
}
img {
height: 36px;
}
button[type='submit'] {
width: 36px;
height: 36px;
padding: 0 10px;
color: white;
background-color: var(--primary);
cursor: pointer;
border-radius: 50%;
font-size: 30px;
&:focus {
border: 2px solid var(--accent);
}
img {
width: 24px;
height: 24px;
}
}
}
}
🧐 결과
'Project' 카테고리의 다른 글
로그인한 사용자별 다른 프로필 보이게 하기 (0) | 2023.04.06 |
---|---|
React에서 페이지 변경 시 카드 딜레이 구현하기 (0) | 2023.04.02 |
채팅 기능 메세지와 이미지 업로드 구현 (0) | 2023.03.24 |
Router 연결 관련 문제 (0) | 2023.03.22 |
네비게이션 메뉴 카테고리에서 하위메뉴 띄우기 (0) | 2023.02.01 |