/
sdds
/
plasma
Обзор
Документация
Войти
/
sdds
/
plasma
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
dev
website/sdds-scan-docs/docs/components/Modal.mdx
311 строк
11 KB
Dima Shugaev
feat(docs): SSRProvider docs updated
24 апр 2026, 09:14
24 апр 2026, 09:14
65163f3
Код
Авторство
О чём код?
--- id: modal title: Modal --- import { PropsTable, Description } from '@site/src/components'; # Modal <Description name="Modal" /> <PropsTable name="Modal" /> ## Использование Перед использованием убедитесь, что `PopupProvider` подключен. Компонент Modal во многом схож с Popup, добавляет при этом подложку(`overlay`), а также блокирует scroll и focus. ```tsx live import React, { useState } from 'react'; import { surfaceSolidSecondary } from '@salutejs/sdds-themes/tokens'; import { Button, Modal, PopupProvider } from '@salutejs/sdds-scan'; export function App() { const [isOpenA, setIsOpenA] = useState(false); const [isOpenB, setIsOpenB] = useState(false); return ( <PopupProvider> <div style={{ height: "300px" }}> <div style={{ display: 'flex', flexDirection: 'column' }}> <Button text="Открыть A" onClick={() => setIsOpenA(true)} /> </div> <Modal id="modalA" onClose={() => setIsOpenA(false)} opened={isOpenA} placement="center" offset={[0, 0]} > <div style={{ background: `${surfaceSolidSecondary}`, padding: "1rem" }}> <Button onClick={() => setIsOpenA(false)}>Close</Button> <Button text="Открыть B" onClick={() => setIsOpenB(true)} /> Content </div> <Modal id="modalB" onClose={() => setIsOpenB(false)} opened={isOpenB} placement="right" offset={[0, 0]} > <div style={{ background: `${surfaceSolidSecondary}`, padding: "1rem" }}> <Button onClick={() => setIsOpenB(false)}>Close</Button> Content </div> </Modal> </Modal> </div> </PopupProvider> ); } ``` ## Использование стилизованной обертки Для использования стилизованного модального окна с отступами и крестиком для закрытия, добавьте свойство `hasBody`. ```tsx live import React, { useState } from 'react'; import { Button, Modal, PopupProvider } from '@salutejs/sdds-scan'; export function App() { const [isOpenA, setIsOpenA] = useState(false); const [isOpenB, setIsOpenB] = useState(false); return ( <PopupProvider> <div style={{ height: "300px" }}> <div style={{ display: 'flex', flexDirection: 'column' }}> <Button text="Открыть A" onClick={() => setIsOpenA(true)} /> </div> <Modal id="modalA" onClose={() => setIsOpenA(false)} opened={isOpenA} placement="center" offset={[0, 0]} hasBody > <Button onClick={() => setIsOpenA(false)}>Close</Button> <Button text="Открыть B" onClick={() => setIsOpenB(true)} /> Content <Modal id="modalB" onClose={() => setIsOpenB(false)} opened={isOpenB} placement="right" offset={[0, 0]} > <Button onClick={() => setIsOpenB(false)}>Close</Button> Content </Modal> </Modal> </div> </PopupProvider> ); } ``` ## Подключение анимации Подключение анимации аналогично тому, как это происходит в `Popup` - через свойство `withAnimation`(управление через `popupClasses`, `modalClasses`). Для добавления анимации в оверлей необходимо использовать класс `.modal-overlay` через переменную `modalClasses.overlay` из пакета. Пример: ```tsx import styled from 'styled-components'; import { Modal } from '@salutejs/sdds-scan'; const StyledModal = styled(Modal)` && > .${popupClasses.root}, .${modalClasses.overlay} { animation: fadeIn 1s forwards; } &&.${popupClasses.endAnimation} .${popupClasses.root} { animation: fadeOut 1s forwards; } &&.${popupClasses.endAnimation} .${modalClasses.overlay} { animation: fadeOut 1s forwards; } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } `; ``` ## FocusTrapped Свойство `isFocusTrapped` захватывает фокус внутри одного DOM элемента. Когда свойство имеет значение `true`, при нажатии `Tab` или `Shift + Tab` фокус будет перемещаться только внутри модального окна. Если поверх текущего модального окна открывается еще одно модальное окно, то фокус захватывает последнее модальное окно. После закрытия модального окна, фокус может свободно перемещаться. Если установить значение `isFocusTrapped` в false, после открытия модального фокус будет перемещен на первый элемент внутри модального окна. Но при последующей навигации с помощью `Tab` или `Shift + Tab` фокус не будет зациклен внутри модального окна и может покинуть его. ## Draggable Чтобы иметь возможность перетаскивать Modal по экрану нужно включить свойство `draggable`. Пример: ```tsx live import React from 'react'; import { Button, Modal, PopupProvider } from '@salutejs/sdds-scan'; export function App() { const [isOpen, setIsOpen] = React.useState(false); return ( <PopupProvider> <div style={{height: "200px"}}> <div style={{ display: 'flex', flexDirection: 'column' }}> <Button style={{ marginTop: "1rem", width: "15rem" }} text="Открыть" onClick={() => setIsOpen(true)} /> </div> <Modal id="modal" isOpen={isOpen} onClose={() => setIsOpen(false)} placement="center" draggable > <div style={{ background: "lightgray", padding: "1rem", height: '100%', boxSizing: 'border-box', borderRadius: '1rem' }}> <Button onClick={() => setIsOpen(false)}>Close</Button> <>Content</> </div> </Modal> </div> </PopupProvider> ); } ``` ## Resizable Чтобы иметь возможность растягивать Popup нужно настроить свойство `resizable`. Формат следующий: ```tsx /** * Настройка resizable-режима. */ resizable?: { /** * Включение/выключение ресайза. * @default false */ disabled?: boolean; /** * Направления для ресайза. */ directions?: ResizeDirections; /** * Начальный размер окна ресайза. */ defaultSize?: { width?: number; height?: number }; /** * Минимальная ширина ресайза в px. */ minWidth?: number; /** * Минимальная высота ресайза в px. */ minHeight?: number; /** * Максимальная ширина ресайза в px. */ maxWidth?: number; /** * Максимальная высота ресайза в px. */ maxHeight?: number; /** * Кастомные иконки ресайза. */ icons?: { topRight?: ReactNode; bottomRight?: ReactNode; bottomLeft?: ReactNode; topLeft?: ReactNode; }; /** * Размер иконки ресайза. * @default s */ iconSize?: 'xs' | 's' | 'm'; /** * Скрывать ли иконку для ресайза. * @default false */ hiddenIcons?: PopupPlacementMixed[]; }; ``` Пример: ```tsx live import React from 'react'; import { Button, Modal, PopupProvider } from '@salutejs/sdds-scan'; export function App() { const [isOpen, setIsOpen] = React.useState(false); return ( <PopupProvider> <div style={{height: "200px"}}> <div style={{ display: 'flex', flexDirection: 'column' }}> <Button style={{ marginTop: "1rem", width: "15rem" }} text="Открыть" onClick={() => setIsOpen(true)} /> </div> <Modal id="modal" isOpen={isOpen} onClose={() => setIsOpen(false)} placement="center" offset={[0, 0]} resizable > <div style={{ background: "lightgray", padding: "1rem", height: '100%', boxSizing: 'border-box', borderRadius: '1rem' }}> <Button onClick={() => setIsOpen(false)}>Close</Button> <>Content</> </div> </Modal> </div> </PopupProvider> ); } ```