-
Notifications
You must be signed in to change notification settings - Fork 2
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
[FE] 사이드바 및 모달 사용성 개선 #139
Changes from all commits
db6c8cc
8193841
3a3a277
c0923c1
e9719ea
d708d72
c88b09e
0ece398
0400c77
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,18 @@ | ||
import React from 'react'; | ||
import React, { PropsWithChildren, useRef } from 'react'; | ||
|
||
import { useModalClose } from '@/hooks'; | ||
|
||
import * as S from './styles'; | ||
|
||
const ModalBackground = ({ children }: React.PropsWithChildren) => { | ||
return <S.ModalBackground>{children}</S.ModalBackground>; | ||
interface ModalBackgroundProps { | ||
closeModal: () => void; | ||
} | ||
|
||
const ModalBackground: React.FC<PropsWithChildren<ModalBackgroundProps>> = ({ children, closeModal }) => { | ||
const modalBackgroundRef = useRef<HTMLDivElement>(null); | ||
useModalClose(closeModal, modalBackgroundRef); | ||
|
||
return <S.ModalBackground ref={modalBackgroundRef}>{children}</S.ModalBackground>; | ||
}; | ||
|
||
export default ModalBackground; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export { default as useSidebar } from './useSidebar'; | ||
export { default as useModalClose } from './useModalClose'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { useEffect, RefObject } from 'react'; | ||
|
||
const useModalClose = (closeModal: () => void, modalBackgroundRef: RefObject<HTMLElement>) => { | ||
const isNodeElement = (element: EventTarget | null): element is Node => { | ||
return element instanceof Node; | ||
}; | ||
|
||
const isModalBackground = (targetElement: Node | null) => { | ||
return modalBackgroundRef.current ? modalBackgroundRef.current === targetElement : false; | ||
}; | ||
|
||
const isHTMLElement = (element: Element | null): element is HTMLElement => { | ||
return element instanceof HTMLElement; | ||
}; | ||
|
||
// NOTE: esc 키를 눌렀을 때 햄버거 버튼이 포커싱되는 문제 해결을 위한 함수 | ||
const blurFocusing = () => { | ||
const activeElement = document.activeElement; | ||
|
||
if (!isHTMLElement(activeElement)) return; | ||
if (typeof activeElement.blur === 'function') activeElement.blur(); | ||
}; | ||
|
||
const handleBackgroundClick = (event: MouseEvent) => { | ||
if (isNodeElement(event.target) && isModalBackground(event.target)) { | ||
closeModal(); | ||
} | ||
}; | ||
|
||
const handleKeyDown = (event: KeyboardEvent) => { | ||
if (event.key === 'Escape') { | ||
event.preventDefault(); | ||
|
||
blurFocusing(); | ||
closeModal(); | ||
} | ||
}; | ||
|
||
useEffect(() => { | ||
const modalBackgroundElement = modalBackgroundRef.current; | ||
|
||
modalBackgroundElement?.addEventListener('click', handleBackgroundClick); | ||
document.addEventListener('keydown', handleKeyDown); | ||
|
||
return () => { | ||
modalBackgroundElement?.removeEventListener('click', handleBackgroundClick); | ||
document.removeEventListener('keydown', handleKeyDown); | ||
}; | ||
}, [closeModal, modalBackgroundRef]); | ||
}; | ||
|
||
export default useModalClose; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,19 @@ | ||
import { useState } from 'react'; | ||
|
||
const useSidebar = () => { | ||
const CLOSE_TIME = 1000; | ||
const OPEN_TIME = 0.5; | ||
const OPEN_TIME = 0.2; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 사이드 바 모달이 열릴 때, 백그라운드가 먼저 나오고 그 이후에 모달이 나오는데 그 텀이 길다 보니까 답답하다는 느낌을 받았어요. 센스있게 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. useSidebar는 제가 작업한 게 아니랍니다...ㅋㅋㅋㅋㅋ 전 추가적으로 닫는 기능을 훅으로 분리했어요~ |
||
|
||
const [isSidebarModalOpen, setIsSidebarModalOpen] = useState(false); | ||
const [isSidebarHidden, setIsSidebarHidden] = useState(true); | ||
|
||
const closeSidebar = () => { | ||
setIsSidebarModalOpen(false); | ||
setIsSidebarHidden(true); | ||
setTimeout(() => { | ||
setIsSidebarModalOpen(false); | ||
}, CLOSE_TIME); | ||
}; | ||
|
||
const openSidebar = () => { | ||
setIsSidebarModalOpen(true); | ||
|
||
setTimeout(() => { | ||
setIsSidebarHidden(false); | ||
}, OPEN_TIME); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
추후 JS element 오류 처리 함수가 완성되면 적용 가능할 것 같은데, 반복되는 optional chaining을 줄이기 위해,
modalBackgroundElement
가 없는 경우 early return을 적용해보는 것은 어떨까요? 사소한 부분입니다 :)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
요 부분은 해당 유틸 함수가 만들어지면 적용할게요 ㅎㅎ 꼼꼼하게 봐 줘서 고마워요!