feat: update modal
This commit is contained in:
@@ -34,11 +34,11 @@ export default function Button({
|
||||
return (
|
||||
<button
|
||||
className={clsx(
|
||||
className,
|
||||
s.Button,
|
||||
disabled && s.Button_disabled,
|
||||
s['Button_' + variant],
|
||||
fullWidth && s.Button_fullWidth,
|
||||
className,
|
||||
)}
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
|
||||
@@ -3,3 +3,4 @@ export { Mark } from './mark';
|
||||
export { Input } from './input';
|
||||
export { TextArea } from './text-area';
|
||||
export { PhoneInput } from './phone-input';
|
||||
export { Modal, ModalContent } from './modal';
|
||||
|
||||
23
src/shared/ui/modal/close-icon.tsx
Normal file
23
src/shared/ui/modal/close-icon.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { SVGProps } from 'react';
|
||||
|
||||
const CloseIcon = ({ ...props }: SVGProps<SVGSVGElement>) => (
|
||||
<svg
|
||||
{...props}
|
||||
width='17'
|
||||
height='17'
|
||||
viewBox='0 0 17 17'
|
||||
fill='none'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
>
|
||||
<path
|
||||
d='M2.5 15L15.5 2M2.5 2L15.5 15'
|
||||
stroke='#053635'
|
||||
strokeOpacity='0.3'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export { CloseIcon };
|
||||
@@ -1 +1,2 @@
|
||||
export { Modal, ModalContent } from './modal';
|
||||
export { Modal } from './modal';
|
||||
export { ModalContent } from './modal-content';
|
||||
|
||||
79
src/shared/ui/modal/modal-content.module.scss
Normal file
79
src/shared/ui/modal/modal-content.module.scss
Normal file
@@ -0,0 +1,79 @@
|
||||
.ModalContent {
|
||||
position: absolute;
|
||||
width: rem(360px);
|
||||
padding: rem(40px) rem(20px) rem(20px);
|
||||
border-radius: rem(20px);
|
||||
background: white;
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
|
||||
overflow: auto;
|
||||
animation: fadeIn ease 0.3s;
|
||||
|
||||
@include iftablet {
|
||||
top: unset;
|
||||
width: rem(540px);
|
||||
padding: rem(40px) rem(24px) rem(24px);
|
||||
}
|
||||
|
||||
@include iflaptop {
|
||||
padding: rem(40px) rem(30px) rem(30px);
|
||||
}
|
||||
|
||||
@include ifdesktop {
|
||||
width: rem(640px);
|
||||
padding: rem(60px) rem(40px) rem(40px);
|
||||
}
|
||||
|
||||
&_open {
|
||||
animation: fadeOut ease 0.3s;
|
||||
}
|
||||
|
||||
&_isIOS {
|
||||
height: 100vh !important;
|
||||
|
||||
@include iftablet {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.Inner {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
.CloseBtn {
|
||||
position: absolute;
|
||||
top: rem(20px);
|
||||
right: rem(20px);
|
||||
width: rem(24px);
|
||||
height: rem(24px);
|
||||
cursor: pointer;
|
||||
transform: rotate(0deg);
|
||||
transition: transform 0.3s;
|
||||
|
||||
&:hover,
|
||||
&:active {
|
||||
transform: rotate(90deg);
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
49
src/shared/ui/modal/modal-content.tsx
Normal file
49
src/shared/ui/modal/modal-content.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
'use client';
|
||||
|
||||
import s from './modal-content.module.scss';
|
||||
import { MouseEvent, ReactNode, useRef } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import { useModal } from '@core/providers/modal-provider';
|
||||
import { detectIOS, useClickOutside } from '@shared/lib';
|
||||
import { CloseIcon } from '@shared/ui/modal/close-icon';
|
||||
|
||||
function ModalContent(props: {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
innerClassName?: string;
|
||||
closeByClickOutside?: boolean;
|
||||
}) {
|
||||
const {
|
||||
children,
|
||||
className,
|
||||
innerClassName,
|
||||
closeByClickOutside = false,
|
||||
} = props;
|
||||
|
||||
const modal = useModal();
|
||||
|
||||
const hideModal = () => modal.hideModal();
|
||||
|
||||
const modalRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const handleClickOutside = () => closeByClickOutside && hideModal();
|
||||
|
||||
useClickOutside(modalRef, handleClickOutside);
|
||||
|
||||
const isIOS = detectIOS();
|
||||
|
||||
const disableClick = (e: MouseEvent<HTMLDivElement>) => e.stopPropagation();
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(className, s.ModalContent, isIOS && s.ModalContent_isIOS)}
|
||||
ref={modalRef}
|
||||
onClick={disableClick}
|
||||
>
|
||||
<CloseIcon className={s.CloseBtn} onClick={hideModal} />
|
||||
<div className={clsx(s.Inner, innerClassName)}>{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export { ModalContent };
|
||||
@@ -3,7 +3,8 @@
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@@ -34,97 +35,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.ModalContent {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
background: white;
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
|
||||
//max-height: 90%;
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
//border-radius: 8px;
|
||||
animation: fadeIn ease 0.3s;
|
||||
|
||||
@include iftablet {
|
||||
position: relative;
|
||||
top: unset;
|
||||
bottom: unset;
|
||||
left: unset;
|
||||
right: unset;
|
||||
height: 100%;
|
||||
border-radius: rem(8px);
|
||||
}
|
||||
|
||||
&_open {
|
||||
animation: fadeOut ease 0.3s;
|
||||
}
|
||||
|
||||
&_isIOS {
|
||||
height: 100vh !important;
|
||||
|
||||
@include iftablet {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&__Inner {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
height: fit-content;
|
||||
}
|
||||
}
|
||||
|
||||
.Modal {
|
||||
position: relative;
|
||||
|
||||
&__Close {
|
||||
position: absolute;
|
||||
top: rem(5px);
|
||||
right: rem(5px);
|
||||
width: rem(36px);
|
||||
height: rem(36px);
|
||||
padding: rem(10px);
|
||||
cursor: pointer;
|
||||
margin-bottom: rem(4px);
|
||||
transform: rotate(0deg);
|
||||
transition: transform 0.3s;
|
||||
|
||||
@include iftablet {
|
||||
top: rem(35px);
|
||||
right: rem(35px);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@include iflaptop {
|
||||
top: rem(50px);
|
||||
right: rem(50px);
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:active {
|
||||
transform: rotate(45deg);
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: rem(17px);
|
||||
height: rem(17px);
|
||||
}
|
||||
|
||||
//svg {
|
||||
// transform: rotate(0deg);
|
||||
// transition: transform 0.3s;
|
||||
// &:hover,
|
||||
// &:active {
|
||||
// transform: rotate(45deg);
|
||||
// transition: transform 0.3s;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
'use client';
|
||||
|
||||
import s from './modal.module.scss';
|
||||
import { ReactNode, useEffect, useRef } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { ReactNode, useEffect } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import { useModal } from '@core/providers/modal-provider';
|
||||
import { detectIOS, useClickOutside } from '@shared/lib';
|
||||
import { detectIOS } from '@shared/lib';
|
||||
import { createPortal } from 'react-dom';
|
||||
|
||||
interface ModalProps {
|
||||
isOpen: boolean;
|
||||
@@ -28,7 +27,7 @@ const Modal = ({ children, isOpen, onClose }: ModalProps) => {
|
||||
|
||||
const isIOS = detectIOS();
|
||||
|
||||
return ReactDOM.createPortal(
|
||||
return createPortal(
|
||||
<div
|
||||
className={clsx(
|
||||
s.ModalBackdrop,
|
||||
@@ -42,68 +41,4 @@ const Modal = ({ children, isOpen, onClose }: ModalProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
function ModalContent(props: {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
innerClassName?: string;
|
||||
closeByClickOutside?: boolean;
|
||||
}) {
|
||||
const {
|
||||
children,
|
||||
className,
|
||||
innerClassName,
|
||||
closeByClickOutside = false,
|
||||
} = props;
|
||||
|
||||
const modal = useModal();
|
||||
|
||||
const hideModal = () => modal.hideModal();
|
||||
|
||||
const modalRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const handleClickOutside = () => {
|
||||
if (closeByClickOutside) {
|
||||
hideModal();
|
||||
}
|
||||
};
|
||||
|
||||
useClickOutside(modalRef, handleClickOutside);
|
||||
|
||||
const isIOS = detectIOS();
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(className, s.ModalContent, isIOS && s.ModalContent_isIOS)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
ref={modalRef}
|
||||
>
|
||||
<div className={clsx(s.ModalContent__Inner, innerClassName)}>
|
||||
<div className={s.Modal__Close} onClick={hideModal}>
|
||||
<CloseIcon />
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export { Modal, ModalContent };
|
||||
|
||||
const CloseIcon = () => (
|
||||
<svg
|
||||
width='17'
|
||||
height='17'
|
||||
viewBox='0 0 17 17'
|
||||
fill='none'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
>
|
||||
<path
|
||||
d='M2.5 15L15.5 2M2.5 2L15.5 15'
|
||||
stroke='#053635'
|
||||
strokeOpacity='0.3'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
export { Modal };
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
.Area {
|
||||
background: $color-white;
|
||||
border: 1px solid $color-darkgray;
|
||||
border-radius: rem(20px);
|
||||
padding: rem(10px) rem(24px);
|
||||
border-radius: rem(16px);
|
||||
padding: rem(10px) rem(10px);
|
||||
transition: border ease .5s;
|
||||
|
||||
font-family: $font-open-sans;
|
||||
font-weight: $font-regular;
|
||||
font-size: rem(18px);
|
||||
font-size: rem(16px);
|
||||
line-height: 100%;
|
||||
color: $color-text;
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
|
||||
@include iftablet {
|
||||
font-size: rem(18px);
|
||||
border-radius: rem(20px);
|
||||
padding: rem(10px) rem(24px);
|
||||
}
|
||||
|
||||
@include iflaptop {
|
||||
|
||||
Reference in New Issue
Block a user