@eisgs/modal
v2.1.0
Published
Для работы модальных окон нужно обернуть приложение в `ModalProvider` из `@eisgs/modal` и задать уникальные имена для модальных окон
Downloads
84
Readme
ModalProvider
Для работы модальных окон нужно обернуть приложение в ModalProvider
из @eisgs/modal
и задать уникальные имена для модальных окон
<ModalProvider>
<App />
</ModalProvider>
ModalConfirm
confirmText
и cancelText
задают текст в кнопках управления модалкой.
onConfirm
и onCancel
задают обработчик клика на соответсвующие кнопки
hasAlertIcon
добавляет иконку алерта
import { ModalConfirm, useModal } from '@eisgs/modal';
import { Button } from '@eisgs/button';
import { Fragment } from 'react';
const modal = useModal();
const nameList = [
{
name: 'Title',
title: 'Удалить документ ?',
confirmText: 'Удалить'
},
{
name: 'Title & text',
title: 'Удалить документ ?',
children: 'Образованные земельные участки ниже будут также удалены.',
confirmText: 'Удалить'
},
{
name: 'Alert',
title: 'Внимание',
hasAlertIcon: true,
children: 'При изменении исходных земельных участков, загруженный шаблон и образованные участки ниже будут удалены.',
},
{
name: 'Alert text',
hasAlertIcon: true,
children: 'При изменении исходных земельных участков, загруженный шаблон и образованные участки ниже будут удалены.',
},
{
name: 'Alert with primary button',
title: 'Внимание',
confirmType: 'primary',
confirmText: 'Закрыть',
hasAlertIcon: true,
children: 'При изменении исходных земельных участков, загруженный шаблон и образованные участки ниже будут удалены.',
},
];
<div style={{display: 'flex'}}>
{nameList.map(({name, children, ...rest}, index) => (
<Fragment key={name}>
<Button
onClick={() => modal.open(name)}
{...index % 2 === 0 && {type: 'secondary'}}
styles='margin-right: 40px'
>
{name}
</Button>
<ModalConfirm
{...rest}
name={name}
onConfirm={() => modal.close(name)}
onCancel={() => modal.close(name)}
>
{children}
</ModalConfirm>
</Fragment>
))}
</div>
Управление шириной Modal
По умолчанию ширина модального окна 312px
, но если заголовок модалки или ширина контента не влезают - модалка будет растянута. width
позволяет явно задать ширину модального окна и исключить растягивание
import { Modal, useModal } from '@eisgs/modal';
import { Button } from '@eisgs/button';
const modal = useModal();
const sampleText = (count) => 'Съешь же ещё этих мягких французских булок, да выпей чаю. '.repeat(count);
<>
<div className="md-flex-row md-flex-wrap w1200">
<Button type="primary" onClick={() => modal.open('modal_content_1')}>Модалка без контента</Button>
<Button type="secondary" onClick={() => modal.open('modal_content_2')}>Модалка с широким контентом</Button>
<Button type="primary" onClick={() => modal.open('modal_content_3')}>Модалка с широким контентом и явно заданной шириной</Button>
</div>
<Modal name="modal_content_1" />
<Modal name="modal_content_2">{sampleText(100)}</Modal>
<Modal name="modal_content_3" width={300}>{sampleText(100)}</Modal>
</>
Управление цветом
isGreyModal
задает серую тему для модального окна
import { Modal, ModalHeader, useModal } from '@eisgs/modal';
import { Button } from '@eisgs/button';
const modal = useModal();
const sampleText = (count) => 'Съешь же ещё этих мягких французских булок, да выпей чаю. '.repeat(count);
const whiteBlockStyle = { backgroundColor: 'white', padding: '20px', marginBottom: '10px' };
const greyBlockStyle = { backgroundColor: '#f8f8f8', padding: '20px', marginBottom: '10px' };
<>
<div className="md-flex-row md-flex-wrap w500">
<Button type="primary" onClick={() => modal.open('modal_color_1')}>Модалка обычная</Button>
<Button type="secondary" onClick={() => modal.open('modal_color_2')}>Модалка с серым фоном</Button>
</div>
<Modal name="modal_color_1" width={400}>
<ModalHeader>Заголовок модалки</ModalHeader>
<div style={greyBlockStyle}>
{sampleText(2)}
</div>
<div style={greyBlockStyle}>
{sampleText(2)}
</div>
<div style={greyBlockStyle}>
{sampleText(2)}
</div>
</Modal>
<Modal name="modal_color_2" isGreyModal width={400}>
<ModalHeader>Заголовок модалки</ModalHeader>
<div style={whiteBlockStyle}>
{sampleText(2)}
</div>
<div style={whiteBlockStyle}>
{sampleText(2)}
</div>
<div style={whiteBlockStyle}>
{sampleText(2)}
</div>
</Modal>
</>
Управление заголовком в модальном окне
Для управления заголовком следует использовать компонент <ModalHeader>
который принимает children
в качестве контента и
fontType
- тип шрифта (h1
, h2
, h3
, h4
, p1
, p2
, p3
, p2compact
, caption
, button
, plink
, link
),
fontWeight
- вес шрифта ('bold', 'bolder', 'lighter', 'normal', 500, 700),
ellipsisMaxLines
- обрезку текста в заголовке (число линий);
import { Modal, ModalHeader, useModal } from '@eisgs/modal';
import { Button } from '@eisgs/button';
import { Input } from '@eisgs/input';
const modal = useModal();
<>
<div className="md-flex-row md-flex-wrap w1200">
<Button type="primary" onClick={() => modal.open('modal_header_1')}>Модалка с заголовком h1</Button>
<Button type="secondary" onClick={() => modal.open('modal_header_2')}>Модалка с заголовком h2</Button>
<Button type="primary" onClick={() => modal.open('modal_header_3')}>Модалка с заголовком h3</Button>
<Button type="secondary" onClick={() => modal.open('modal_header_4')}>Модалка с заголовком h4</Button>
</div>
<div className="md-flex-row md-flex-wrap w1200">
<Button type="secondary" onClick={() => modal.open('modal_header_5')}>Модалка со стандартным заголовком</Button>
<Button type="primary" onClick={() => modal.open('modal_header_6')}>Модалка с кастомный весом шрифта</Button>
<Button type="secondary" onClick={() => modal.open('modal_header_7')}>Модалка с обрезкой текста 1</Button>
</div>
<div className="md-flex-row md-flex-wrap w1200">
<Button type="primary" onClick={() => modal.open('modal_header_8')}>Модалка с обрезкой текста 2</Button>
</div>
<Modal name="modal_header_1">
<ModalHeader fontType='h1'>Заголовок модалки h1</ModalHeader>
<Input label="инпут 1" value="значение 1" />
</Modal>
<Modal name="modal_header_2">
<ModalHeader fontType='h2'>Заголовок модалки h2</ModalHeader>
<Input label="инпут 1" value="значение 1" />
</Modal>
<Modal name="modal_header_3">
<ModalHeader fontType='h3'>Заголовок модалки h3</ModalHeader>
<Input label="инпут 1" value="значение 1" />
</Modal>
<Modal name="modal_header_4">
<ModalHeader fontType='h4'>Заголовок модалки h4</ModalHeader>
<Input label="инпут 1" value="значение 1" />
</Modal>
<Modal name="modal_header_5">
<ModalHeader>Стандартный заголовок модалки p1 bold</ModalHeader>
<Input label="инпут 1" value="значение 1" />
</Modal>
<Modal name="modal_header_6">
<ModalHeader fontWeight='normal'>Кастомный вес шрифта</ModalHeader>
<Input label="инпут 1" value="значение 1" />
</Modal>
<Modal width={200} name="modal_header_7">
<ModalHeader ellipsisMaxLines={1} >Очень длинный заголовок модалки и его обрезка</ModalHeader>
<Input label="инпут 1" value="значение 1" />
</Modal>
<Modal width={200} name="modal_header_8">
<ModalHeader ellipsisMaxLines={2}>Очень длинный заголовок модалки и его обрезка при превышении ширины</ModalHeader>
<Input label="инпут 1" value="значение 1" />
</Modal>
</>
Простые и вложенные модальные окна
import { Modal, ModalHeader, useModal } from '@eisgs/modal';
import { Button } from '@eisgs/button';
const modal = useModal();
<>
<div className="md-flex-row md-flex-wrap w1000">
<Button type="primary" onClick={() => modal.open('modal_options_1')}>Открыть простую модалку</Button>
<Button type="secondary" onClick={() => modal.open('modal_options_2')}>Открыть модалку, в которой есть вложенная модалка</Button>
</div>
<Modal name='modal_options_1'>
<ModalHeader>Простая модалка 1</ModalHeader>
</Modal>
<Modal name='modal_options_2'>
<>
<ModalHeader>Простая модалка 2</ModalHeader>
<Button type="primary" onClick={() => modal.open('modal_options_3')}>Открыть вложенную модалку</Button>
<Modal name='modal_options_3'>
<ModalHeader>Модалка 3</ModalHeader>
</Modal>
</>
</Modal>
</>
Кнопки в модальном окне
<ModalFooter>
позволяет сделать обертку для кнопок c flex-контейнером и отсупом 32px сверху. Для позиционирования кнопок используются justifyContent
и alignItems
со значениями как в обычном flex
import { Modal, ModalHeader, ModalFooter, useModal } from '@eisgs/modal';
import { Button } from '@eisgs/button';
const modal = useModal();
const sampleText = (count) => 'Съешь же ещё этих мягких французских булок, да выпей чаю. '.repeat(count);
<>
<div>
<Button type="secondary" onClick={() => modal.open('modal_footer_1')}>Кнопки в модалке</Button>
<Button type="primary" onClick={() => modal.open('modal_footer_2')} styles={`margin-top: 20px`}>Кнопки в модалке 2</Button>
</div>
<Modal name='modal_footer_1' width={444}>
<ModalHeader>Кнопки в модалке</ModalHeader>
<ModalFooter justifyContent='flex-start'>
<Button type="primary">Сохранить</Button>
<Button type="secondary" >Отмена</Button>
</ModalFooter>
</Modal>
<Modal name='modal_footer_2' width={444}>
<ModalHeader>Кнопки в модалке 2</ModalHeader>
<ModalFooter justifyContent='flex-end'>
<Button type="primary">Отправить</Button>
<Button type="secondary" >Отмена</Button>
</ModalFooter>
</Modal>
</>
Закрытие модального окна при нажатии на Escape
По умолчанию модальное окно закрывается при нажатии на Escape
, если данное поведение нежелательно, то можно передать closeOnEsc=false
import { Modal, ModalHeader, ModalFooter, useModal } from '@eisgs/modal';
import { Button } from '@eisgs/button';
import { Fragment } from 'react';
const modal = useModal();
const items = [
{
name: 'Поведение по умолчанию'
},
{
name: 'closeOnEsc=false',
closeOnEsc: false,
}
];
<div>
{items.map(({name, ...props}, index) => (
<Fragment key={name}>
<Button
onClick={() => modal.open(name)}
type={index === 1 ? 'secondary' : 'primary'}
{...index === 1 && { styles: `margin-top: 20px`}}
>
{name}
</Button>
<Modal name={name} {...props}>
<ModalHeader>{name}</ModalHeader>
</Modal>
</Fragment>
))}
</div>
Возможность закрытия модального окна
С помощью параметра isClosable
можно управлять возможностью закрытия модального окна.
При передаче значения false
модальное окно будет недоступно для закрытия.
import { useState } from 'react';
import { Modal, ModalHeader, ModalFooter, useModal } from '@eisgs/modal';
import { Button } from '@eisgs/button';
import { Switch } from '@eisgs/switch';
const name = 'isClosable';
const [isClosable, setIsClosable] = useState(false);
const modal = useModal();
<>
<Button onClick={() => modal.open(name)}>{`isClosable=${isClosable}`}</Button>
<Modal name={name} isClosable={isClosable} onClose={() => setIsClosable(false)}>
<ModalHeader>{name}</ModalHeader>
<Switch isChecked={isClosable} onChange={setIsClosable}>
{`isClosable: ${isClosable}`}
</Switch>
</Modal>
</>
Закрытие модального окна при клике на overlay
Параметр disableOverlayClick
позволяет блокировать закрытие модального окна при клике на overlay.
import { Modal, ModalHeader, useModal } from '@eisgs/modal';
import { Button } from '@eisgs/button';
const name = 'disableOverlayClick';
const modal = useModal();
<>
<Button onClick={() => modal.open(name)}>{name}</Button>
<Modal name={name} disableOverlayClick>
<ModalHeader>
{name}
</ModalHeader>
</Modal>
</>