-
12. Styled-components : Dialog 만들기 - 컴포넌트 스타일링 | 벨로퍼트Front-end/React.js 2020. 7. 21. 13:18반응형
이번에는 기존 화면을 가리게 되면서 정보를 보여주게 되는 Dialog 컴포넌트를 만들어보겠습니다.
이 컴포넌트를 만드는 과정에서 우리가 아까 만들었던 Button 컴포넌트를 재사용하게 됩니다.
트랜지션 효과는 나중에 구현을 해주겠습니다.
우선 components 디렉터리에 Dialog.js 파일을 생성 후 다음 코드를 입력해보세요.
/src/components/Dialog.js :
import React from 'react'; import styled from 'styled-components'; import Button from './Button'; const DarkBackground = styled.div` position: fixed; left: 0; top: 0; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; background: rgba(0, 0, 0, 0.8); `; const DialogBlock = styled.div` width: 320px; padding: 1.5rem; background: white; border-radius: 2px; h3 { margin: 0; font-size: 1.5rem; } p { font-size: 1.125rem; } `; const ButtonGroup = styled.div` margin-top: 3rem; display: flex; justify-content: flex-end; `; function Dialog({ title, children, confirmText, cancelText }) { return ( <DarkBackground> <DialogBlock> <h3>{title}</h3> <p>{children}</p> <ButtonGroup> <Button color="gray">{cancelText}</Button> <Button color="pink">{confirmText}</Button> </ButtonGroup> </DialogBlock> </DarkBackground> ); } Dialog.defaultProps = { confirmText: '확인', cancelText: '취소' }; export default Dialog;
우리가 h3, 과 p 를 스타일링 때 굳이 다음과 같이 따로 따로 컴포넌트를 만들어주지 않아도
const Title = styled.h3``; const Description = styled.p``;
styled-components 에서도 Nested CSS 문법을 사용 할 수 있기 때문에 DialogBlock 안에 있는 h3 와 p 에게 특정 스타일을 주고 싶다면 다음과 같이 작성 할 수 있답니다.
const DialogBlock = styled.div` h3 { ... } p { ... } `;
자, 이제 이 컴포넌트를 App 에 렌더링해보세요.
/src/App.js :
// ... import Dialog from './components/Dialog'; // ... function App() { return ( <ThemeProvider theme={{ palette: { blue: '#228be6', gray: '#495057', pink: '#f06595' } }} > <> <AppBlock> // ... </AppBlock> <Dialog title="정말로 삭제하시겠습니까?" confirmText="삭제" cancelText="취소" > 데이터를 정말로 삭제하시겠습니까? </Dialog> </> </ThemeProvider> ); } // ...
Dialog 컴포넌트를 예시 내용과 함께 AppBlock 하단에 넣어주었으며, ThemeProvider 내부는 하나의 리액트 엘리먼트로 감싸져있어야 하기 때문에 AppBlock 과 Dialog 를 <></> 으로 감싸주었습니다.
지금 보면 이 Dialog 에서는 취소 버튼과 삭제 버튼의 간격이 조금 넓어보이는 느낌이 있는데요, 만약에 styled-components로 컴포넌트의 스타일을 특정 상황에서 덮어쓰는 방법에 대해서 알아보겠습니다.
Dialog.js 에서 다음과 같이 ShortMarginButton 을 만들고 기존 Button 을 대체시켜보세요.
/src/components/Dialog.js :
//... const ShortMarginButton = styled(Button)` & + & { margin-left: 0.5rem; } `; function Dialog({ title, children, confirmText, cancelText }) { return ( <DarkBackground> <DialogBlock> <h3>{title}</h3> <p>{children}</p> <ButtonGroup> <ShortMarginButton color="gray">{cancelText}</ShortMarginButton> <ShortMarginButton color="pink">{confirmText}</ShortMarginButton> </ButtonGroup> </DialogBlock> </DarkBackground> ); } // ...
여백이 줄어들었나요? 이렇게 컴포넌트의 스타일을 커스터마이징 할 때에는 해당 컴포넌트에서 className props 를 내부 엘리먼트에게 전달이 되고 있는지 확인해주어야 합니다.
const MyComponent = ({ className }) => { return <div className={className}></div> }; const ExtendedComponent = styled(MyComponent)` background: black; `;
참고로 우리가 만든 Button 컴포넌트의 경우에는 ...rest 를 통하여 전달이 되고 있습니다.
컴포넌트의 모양새를 모두 갖추었으면 열고 닫을 수 있는 기능을 구현해봅시다. Dialog 에서 onConfirm 과 onCancel 을 props 로 받아오도록 하고 해당 함수들을 각 버튼들에게 onClick 으로 설정해주세요.
그리고, visible props 도 받아와서 이 값이 false 일 때 컴포넌트에서 null 을 반환하도록 설정해주세요.
/src/components/Dialog.js :
// ... function Dialog({ title, children, confirmText, cancelText, onConfirm, onCancel, visible }) { if (!visible) return null; return ( // ... ); } // ...
그 다음에는, App 컴포넌트에서 useState 를 사용하여 Dialog 를 가시성 상태를 관리해보세요.
/src/App.js :
// ... function App() { const [dialog, setDialog] = useState(false); const onClick = () => { setDialog(true); }; const onConfirm = () => { console.log('확인'); setDialog(false); }; const onCancel = () => { console.log('취소'); setDialog(false); }; return ( <ThemeProvider theme={{ palette: { blue: '#228be6', gray: '#495057', pink: '#f06595' } }} > <> <AppBlock> <Button size="large" color="pink" fullWidth onClick={onClick}> 삭제 </Button> </AppBlock> <Dialog title="정말로 삭제하시겠습니까?" confirmText="삭제" cancelText="취소" onConfirm={onConfirm} onCancel={onCancel} visible={dialog} > 데이터를 정말로 삭제하시겠습니까? </Dialog> </> </ThemeProvider> ); } // ...
맨 아래에 있는 큰 핑크색 버튼의 이름을 "삭제" 로 변경 후 해당 버튼을 누르면 우리가 만든 Dialog 가 보여지도록 설정을 했고,
Dialog 에 onConfirm, onCancel, visible 값을 전달해주었습니다.
브라우저에서 삭제 버튼을 눌러서 Dialog 가 잘 작동하는지 확인해보세요.
버튼 눌렀을 때 콘솔에 확인/취소 텍스트가 출력되는지도 확인하세요.
반응형'Front-end > React.js' 카테고리의 다른 글
1. 프로젝트 생성 UI 준비(1) - TodoList | 벨로퍼트 (0) 2020.07.22 13. Styled-components : 트랜지션 구현하기 - 컴포넌트 스타일링 | 벨로퍼트 (0) 2020.07.21 11. Styled-components : 버튼 outline, fullWidth 설정 - 컴포넌트 스타일링 | 벨로퍼트 (0) 2020.07.20 10. Styled-components : 버튼 사이즈 조정하기 - 컴포넌트 스타일링 | 벨로퍼트 (0) 2020.07.20 9. Styled-components : Polished 스타일 유틸 함수 사용 - 컴포넌트 스타일링 | 벨로퍼트 (0) 2020.07.20