# Component/Modal/BasicModal > Props: component-modal-basicmodal.props.txt ## Examples ### Auto Focus Button 푸터 영역의 autoFocusButton 적용 기본 버튼을 변경할 수 있습니다. ```tsx { args: { title: 'Title', confirmText: 'Label', cancelText: 'Label' }, render: args => { const [show, setShow] = useState(false); const spacing_value = args.dense ? 8 : 16; const handleClose = () => setShow(false); return <> { console.log('cancel reason is', reason); handleClose(); }} onConfirm={handleClose} onExited={() => console.log('onExited')}> Heading Body ; }, args: { title: 'Title', confirmText: 'Label', cancelText: 'Label', autoFocusButton: 'confirm' }, parameters: { docs: { description: { story: '푸터 영역의 autoFocusButton 적용 기본 버튼을 변경할 수 있습니다.' } } } } ``` ### Auto Max Height 콘텐츠 영역이 길어질 경우 상하좌우 안전여백내에서 maxHeight값이 자동 적용됩니다. ```tsx { parameters: { docs: { description: { story: '콘텐츠 영역이 길어질 경우 상하좌우 안전여백내에서 maxHeight값이 자동 적용됩니다.' } } }, render: () => { const [show, setShow] = useState(false); const handleOpen = () => setShow(true); const handleClose = () => setShow(false); return <> Heading Auto Max Height Long Content... ; } } ``` ### Base ```tsx { args: { title: 'Title', confirmText: 'Label', cancelText: 'Label' }, render: args => { const [show, setShow] = useState(false); const spacing_value = args.dense ? 8 : 16; const handleClose = () => setShow(false); return <> { console.log('cancel reason is', reason); handleClose(); }} onConfirm={handleClose} onExited={() => console.log('onExited')}> Heading Body ; } } ``` ### Controlled Cancel Event 취소사유(cancelClick | escapeKeyPress | overlayClick) 별로 특정 로직을 넣을 수 있습니다. ```tsx { render: () => { const [show, setShow] = useState(false); const handleClose = () => setShow(false); return <> { console.log('reason is', reason); switch (reason) { case 'cancelClick': handleClose(); break; case 'escapeKeyPress': // custom logic... handleClose(); break; case 'overlayClick': // custom logic... handleClose(); } }} onConfirm={handleClose}> Heading Body ; }, parameters: { docs: { description: { story: '취소사유(cancelClick | escapeKeyPress | overlayClick) 별로 특정 로직을 넣을 수 있습니다.' } } } } ``` ### Custom Content 콘텐츠 영역을 커스텀할 수 있습니다. 기본 콘텐츠 영역은 간격을 가지고 있기 때문에 레이아웃 스타일을 커스텀할 경우 spaceProps를 이용, contentProps로 전달시 해당 스타일을 우선순위로 가집니다. ```tsx { render: () => { const [show, setShow] = useState(false); const handleClose = () => setShow(false); return <> Custom Modal Content - SpaceProps ; }, parameters: { docs: { description: { story: '콘텐츠 영역을 커스텀할 수 있습니다. 기본 콘텐츠 영역은 간격을 가지고 있기 때문에 레이아웃 스타일을 커스텀할 경우 spaceProps를 이용, contentProps로 전달시 해당 스타일을 우선순위로 가집니다.' } } } } ``` ### Custom Footer 푸터 영역을 커스텀할 수 있습니다. 커스텀 사용시 dense 속성은 적용되지 않습니다. ```tsx { render: () => { const [show, setShow] = useState(false); const handleClose = () => setShow(false); return <> Footer Addon 1 }> Heading Body ; }, parameters: { docs: { description: { story: '푸터 영역을 커스텀할 수 있습니다. 커스텀 사용시 dense 속성은 적용되지 않습니다.' } } } } ``` ### Custom Footer Full Screen ```tsx { render: () => { const [show, setShow] = useState(false); const handleClose = () => setShow(false); return <> Footer Addon 1 }> Heading Custom Footer + FullScreen
Long Long Content
; } } ``` ### Custom Header 헤더 영역을 커스텀할 수 있습니다. 커스텀 사용시 기본 Header(title, backButton, closeButton)는 미노출됩니다. ```tsx { render: () => { const [show, setShow] = useState(false); const handleClose = () => setShow(false); return <> Custom Header Title Status }> Heading Body ; }, parameters: { docs: { description: { story: '헤더 영역을 커스텀할 수 있습니다. 커스텀 사용시 기본 Header(title, backButton, closeButton)는 미노출됩니다.' } } } } ``` ### Custom Max Height 콘텐츠 영역 maxHeight을 커스텀할 수 있습니다. 지정하지 않을 경우 안전여백내에서 계산된 maxHeight값이 적용됩니다. ```tsx { parameters: { docs: { description: { story: '콘텐츠 영역 maxHeight을 커스텀할 수 있습니다. 지정하지 않을 경우 안전여백내에서 계산된 maxHeight값이 적용됩니다.' } } }, render: () => { const [show, setShow] = useState(false); const handleOpen = () => setShow(true); const handleClose = () => setShow(false); return <> Heading Custom Max Height - 500
Long Content...
; } } ``` ### Dense ```tsx { args: { title: 'Title', confirmText: 'Label', cancelText: 'Label' }, render: args => { const [show, setShow] = useState(false); const spacing_value = args.dense ? 8 : 16; const handleClose = () => setShow(false); return <> { console.log('cancel reason is', reason); handleClose(); }} onConfirm={handleClose} onExited={() => console.log('onExited')}> Heading Body ; }, args: { title: 'Title', confirmText: 'Label', cancelText: 'Label', dense: true, width: 340 } } ``` ### Disabled Overlay Escape 오버레이 클릭, esc 키이벤트로 인한 cancel 처리를 중지할 수 있습니다. ```tsx { args: { title: 'Title', confirmText: 'Label', cancelText: 'Label' }, render: args => { const [show, setShow] = useState(false); const spacing_value = args.dense ? 8 : 16; const handleClose = () => setShow(false); return <> { console.log('cancel reason is', reason); handleClose(); }} onConfirm={handleClose} onExited={() => console.log('onExited')}> Heading Body ; }, args: { title: 'Title', confirmText: 'Label', cancelText: 'Label', canClickOutside: false, canCloseEscapeKey: false }, parameters: { docs: { description: { story: '오버레이 클릭, esc 키이벤트로 인한 cancel 처리를 중지할 수 있습니다.' } } } } ``` ### Fill 안전여백내에서 너비 100% 적용됩니다. ```tsx { args: { title: 'Title', confirmText: 'Label', cancelText: 'Label' }, render: args => { const [show, setShow] = useState(false); const spacing_value = args.dense ? 8 : 16; const handleClose = () => setShow(false); return <> { console.log('cancel reason is', reason); handleClose(); }} onConfirm={handleClose} onExited={() => console.log('onExited')}> Heading Body ; }, args: { title: 'Title', confirmText: 'Label', cancelText: 'Label', fill: true }, parameters: { docs: { description: { story: '안전여백내에서 너비 100% 적용됩니다.' } } } } ``` ### Fill Button ```tsx { args: { title: 'Title', confirmText: 'Label', cancelText: 'Label' }, render: args => { const [show, setShow] = useState(false); const spacing_value = args.dense ? 8 : 16; const handleClose = () => setShow(false); return <> { console.log('cancel reason is', reason); handleClose(); }} onConfirm={handleClose} onExited={() => console.log('onExited')}> Heading Body ; }, args: { confirmButtonProps: { fill: true }, confirmText: 'Label', cancelText: 'Label', cancelButtonProps: { fill: true } } } ``` ### Fit Content contentProps를 display: flex로 지정하면 하위 내용 컴포넌트를 모달 높이에 맞출 수 있습니다. ```tsx { parameters: { docs: { description: { story: 'contentProps를 display: flex로 지정하면 하위 내용 컴포넌트를 모달 높이에 맞출 수 있습니다.' } } }, render: () => { const [show, setShow] = useState(false); const handleOpen = () => setShow(true); const handleClose = () => setShow(false); return <> Heading
Content
; } } ``` ### Footer Extra ```tsx { args: { title: 'Title', confirmText: 'Label', cancelText: 'Label' }, render: args => { const [show, setShow] = useState(false); const spacing_value = args.dense ? 8 : 16; const handleClose = () => setShow(false); return <> { console.log('cancel reason is', reason); handleClose(); }} onConfirm={handleClose} onExited={() => console.log('onExited')}> Heading Body ; }, args: { footerExtra: 조회 결과 내역이 모두 제외 처리됩니다. 제외하지 않을 대상은 ‘목록에서 빼기’를 이용해주세요. , width: 900, title: 'Title', confirmText: 'Label', cancelText: 'Label' } } ``` ### Footer Extra Full Screen 전체화면을 사용할 수 있습니다. 헤더/푸터 영역이 자동 고정됩니다. ```tsx { render: args => { const [show, setShow] = useState(false); const [selectValue, setSelectValue] = useState(); const options = [{ label: 'option 1', value: 'value-1' }, { label: 'option 2', value: 'value-2' }, { label: 'option 3', value: 'value-3' }, { label: 'option 4', value: 'value-4' }, { label: 'option 5', value: 'value-5' }]; return <> setShow(false)} onCancel={() => setShow(false)} autoFocusButton='confirm' {...args}> <> Text Example1 Description Text Example1 Text Example2 Description Text Example2
Long Long Content
; }, parameters: { docs: { description: { story: '전체화면을 사용할 수 있습니다. 헤더/푸터 영역이 자동 고정됩니다.' } } }, args: { footerExtra: 조회 결과 내역이 모두 제외 처리됩니다. 제외하지 않을 대상은 ‘목록에서 빼기’를 이용해주세요. } } ``` ### Full Screen 전체화면을 사용할 수 있습니다. 헤더/푸터 영역이 자동 고정됩니다. ```tsx { render: args => { const [show, setShow] = useState(false); const [selectValue, setSelectValue] = useState(); const options = [{ label: 'option 1', value: 'value-1' }, { label: 'option 2', value: 'value-2' }, { label: 'option 3', value: 'value-3' }, { label: 'option 4', value: 'value-4' }, { label: 'option 5', value: 'value-5' }]; return <> setShow(false)} onCancel={() => setShow(false)} autoFocusButton='confirm' {...args}> <> Text Example1 Description Text Example1 Text Example2 Description Text Example2
Long Long Content
; }, parameters: { docs: { description: { story: '전체화면을 사용할 수 있습니다. 헤더/푸터 영역이 자동 고정됩니다.' } } } } ``` ### Nesting Child Modal 자식 요소로써 중첩 모달을 호출 할 수 있습니다. ```tsx { render: () => { const [show, setShow] = useState(false); const [showSecond, setShowSecond] = useState(false); const handleOpenFirstModal = () => setShow(true); const handleCloseFirsModal = () => setShow(false); const handleOpenSecondModal = () => setShowSecond(true); const handleCloseSecondModal = () => setShowSecond(false); return <> Heading Body Second Modal Heading Second Modal Body ; }, parameters: { docs: { description: { story: '자식 요소로써 중첩 모달을 호출 할 수 있습니다.' } } } } ``` ### Nesting Confirm 다른 타입의 모달을 중첩으로 호출할 수 있습니다. ```tsx { render: () => { const [show, setShow] = useState(false); const handleOpen = () => setShow(true); const handleClose = () => setShow(false); const openConfirm = () => { return Confirm({ title: 'Confirm Title', confirmText: 'Confirm', cancelText: 'Cancel', onConfirm: () => { console.log('onConfirm'); handleClose(); }, onCancel: () => { console.log('onCancel'); }, onExited: () => { console.log('onExited'); } }); }; return <> Heading Body ; }, parameters: { docs: { description: { story: '다른 타입의 모달을 중첩으로 호출할 수 있습니다.' } } } } ``` ### Nesting Floating Elements 중첩된 플로팅 요소 테스트입니다. ```tsx { render: () => { const [modalShow, setModalShow] = useState(false); const [bottomSheetShow, setBottomSheetShow] = useState(false); const [nestedModalShow, setNestedModalShow] = useState(false); const [nestedChildModalShow, setNestedChildModalShow] = useState(false); const [selectValue, setSelectValue] = useState(); const [dates, setDates] = useState(); const options = [{ label: 'option 1', value: 'value-1' }, { label: 'option 2', value: 'value-2' }, { label: 'option 3', value: 'value-3' }, { label: 'option 4', value: 'value-4' }, { label: 'option 5', value: 'value-5' }]; return <> setModalShow(false)} onCancel={() => setModalShow(false)} autoFocusButton='confirm'> <> Text Example1 Description Text Example1 Text Example2 Description Text Example2 setNestedChildModalShow(false)} onCancel={() => setNestedChildModalShow(false)} autoFocusButton='confirm'> Text Example1 Description Text Example1 setDates({ from, to: end })} showTimePicker showRemoveButton />
Long Long Content
setBottomSheetShow(false)}> <> Body Content long content... { const [show, setShow] = useState(false); const order = useRef(0); const handleOpen = () => setShow(true); const handleClose = () => setShow(false); const openConfirm = (times: number = 1) => { const id = order.current++; return Confirm({ title: `Confirm Title (ID: ${id})`, text: new Array(times).fill(0).map((_, index) => index).join('\n'), confirmText: 'Confirm', cancelText: 'Cancel', onConfirm: () => { console.log('Confirm onConfirm', id); }, onCancel: () => { console.log('Confirm onCancel', id); }, onExited: () => { console.log('Confirm onExited', id); } }); }; const openAlert = (times: number = 1) => { const id = order.current++; return Alert({ title: `Alert Title (ID: ${id})`, text: new Array(times).fill(0).map((_, index) => index).join('\n'), confirmText: 'Close', onConfirm: () => { console.log('Alert onConfirm', id); }, onExited: () => { console.log('Alert onExited', id); } }); }; return <> { console.log('Modal onConfirm'); handleClose(); }} onCancel={() => { console.log('Modal onCancel'); handleClose(); }} onExited={() => { console.log('Modal onExited'); }} title='Title' confirmText='Confirm' cancelText='Cancel'> Heading Body ; }, parameters: { docs: { description: { story: '다른 타입의 모달을 중첩으로 호출할 수 있습니다.' } } } } ``` ### Nesting Modal 중첩 모달을 호출 할 수 있습니다. ```tsx { render: () => { const [show, setShow] = useState(false); const [showSecond, setShowSecond] = useState(false); const handleOpenFirstModal = () => setShow(true); const handleCloseFirsModal = () => setShow(false); const handleOpenSecondModal = () => setShowSecond(true); const handleCloseSecondModal = () => setShowSecond(false); return <> Heading Body Second Modal Heading Second Modal Body ; }, parameters: { docs: { description: { story: '중첩 모달을 호출 할 수 있습니다.' } } } } ``` ### Scrollable 콘텐츠 영역 maxHeight 지정하지 않거나 비동기적인 가변 높이를 가질 경우 contentProps scrollable 속성을 통해 overflow auto 여부를 지정할 수 있습니다. ```tsx { parameters: { docs: { description: { story: '콘텐츠 영역 maxHeight 지정하지 않거나 비동기적인 가변 높이를 가질 경우 contentProps scrollable 속성을 통해 overflow auto 여부를 지정할 수 있습니다.' } } }, render: () => { const [show, setShow] = useState(false); const handleOpen = () => setShow(true); const handleClose = () => setShow(false); return <> Heading contentProps.scrollable = true
content child 영역에 overflow auto 여부를 지정할 수 있습니다.
Long Content...
Long Content...
Long Content...
Long Content...
Long Content...
Long Content...
Long Content...
Long Content...
Long Content...
Long Content...
Long Content...
; } } ``` ### With Back Button ```tsx { args: { title: 'Title', confirmText: 'Label', cancelText: 'Label' }, render: args => { const [show, setShow] = useState(false); const spacing_value = args.dense ? 8 : 16; const handleClose = () => setShow(false); return <> { console.log('cancel reason is', reason); handleClose(); }} onConfirm={handleClose} onExited={() => console.log('onExited')}> Heading Body ; }, args: { title: 'Title', confirmText: 'Label', cancelText: 'Label', backButton: true, onClickBackButton: () => alert('onClickBackButton') } } ``` ### Without Footer confirmText, cancelText, footer를 모두 전달하지 않은 경우 콘텐츠 영역 하단 border-radius가 적용되는 케이스입니다. ```tsx { args: { title: 'Title', confirmText: '', cancelText: '', contentProps: { p: 0 } }, render: props => { const [show, setShow] = useState(false); const handleClose = () => setShow(false); return <> Heading Footer가 없는 BasicModal + Long Content 케이스
Long Content
Long Content
Long Content
Long Content
Long Content
Long Content
Long Content
Long Content
Long Content
; }, parameters: { docs: { description: { story: 'confirmText, cancelText, footer를 모두 전달하지 않은 경우 콘텐츠 영역 하단 border-radius가 적용되는 케이스입니다.' } } } } ```