2.1.0 • Published 2 months ago

@eisgs/modal v2.1.0

Weekly downloads
-
License
MIT
Repository
-
Last release
2 months ago

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>
</>
2.1.0

2 months ago

2.0.0

1 year ago

1.3.3

1 year ago

1.3.2

1 year ago

1.3.1

2 years ago

1.3.0

2 years ago

1.2.4

2 years ago

1.2.3

2 years ago

1.2.1

2 years ago

1.2.0

2 years ago

1.1.0

2 years ago

1.1.3

2 years ago

1.1.2

2 years ago

1.0.9

3 years ago

1.0.8

3 years ago

1.0.7

3 years ago

1.0.6

3 years ago

1.0.5

3 years ago

1.0.4

3 years ago

1.0.3

3 years ago

1.0.2

3 years ago

1.0.1

3 years ago