Changeset View
Changeset View
Standalone View
Standalone View
cashtab/src/components/Common/Modal.tsx
| // Copyright (c) 2024 The Bitcoin developers | // Copyright (c) 2024 The Bitcoin developers | ||||
| // Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
| import React from 'react'; | import React from 'react'; | ||||
| import styled from 'styled-components'; | import styled from 'styled-components'; | ||||
| import { CashtabScroll } from './Atoms'; | import { CashtabScroll } from './Atoms'; | ||||
| import { InlineLoader } from './Spinner'; | import { InlineLoader } from './Spinner'; | ||||
| import { ReactComponent as CloseIcon } from 'assets/close.svg'; | |||||
| const ModalContainer = styled.div<{ | const ModalContainer = styled.div<{ | ||||
| width: number; | width: number; | ||||
| height: number; | height: number; | ||||
| paddingPx?: number; | paddingPx?: number; | ||||
| }>` | }>` | ||||
| width: ${props => props.width}px; | width: ${props => props.width}px; | ||||
| height: ${props => props.height}px; | height: ${props => props.height}px; | ||||
| transition: height 1s ease-in-out; | transition: height 1s ease-in-out; | ||||
| position: fixed; | position: fixed; | ||||
| top: 50%; | top: 50%; | ||||
| left: 50%; | left: 50%; | ||||
| transform: translate(-50%, -50%); | transform: translate(-50%, -50%); | ||||
| max-width: 100%; | max-width: 100%; | ||||
| max-height: 100%; | max-height: 100%; | ||||
| border-radius: 9px; | width: 100%; | ||||
| background: rgba(0, 0, 0, 0.75); | max-width: 500px; | ||||
| backdrop-filter: blur(5px); | border-radius: 8px; | ||||
| background: rgba(0, 0, 0, 0.8); | |||||
| padding: ${props => | padding: ${props => | ||||
| typeof props.paddingPx === 'number' ? props.paddingPx : 12}px; | typeof props.paddingPx === 'number' ? props.paddingPx : 30}px; | ||||
| z-index: 1000; | z-index: 1000; | ||||
| box-sizing: border-box; | box-sizing: border-box; | ||||
| *, | *, | ||||
| *:before, | *:before, | ||||
| *:after { | *:after { | ||||
| box-sizing: inherit; | box-sizing: inherit; | ||||
| } | } | ||||
| `; | `; | ||||
| const ModalTitle = styled.div` | const ModalTitle = styled.div` | ||||
| font-weight: bold; | font-weight: bold; | ||||
| padding: 6px 0; | padding: 6px 0; | ||||
| font-size: var(--text-xl); | font-size: var(--text-xl); | ||||
| line-height: var(--text-xl--line-height); | line-height: var(--text-xl--line-height); | ||||
| text-align: center; | text-align: center; | ||||
| width: 100%; | width: 100%; | ||||
| color: ${props => props.theme.accent}; | color: ${props => props.theme.primaryText}; | ||||
| margin-bottom: 20px; | |||||
| `; | `; | ||||
| const MODAL_HEIGHT_DELTA = 68; | const MODAL_HEIGHT_DELTA = 68; | ||||
| const ModalBody = styled.div<{ | const ModalBody = styled.div<{ | ||||
| showButtons: boolean; | showButtons: boolean; | ||||
| height: number; | height: number; | ||||
| noScroll?: boolean; | noScroll?: boolean; | ||||
| }>` | }>` | ||||
| ▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | :hover { | ||||
| box-shadow: ${props => props.theme.buttons.primary.hoverShadow}; | box-shadow: ${props => props.theme.buttons.primary.hoverShadow}; | ||||
| } | } | ||||
| `; | `; | ||||
| const ModalConfirm = styled(ModalBaseButton)` | const ModalConfirm = styled(ModalBaseButton)` | ||||
| color: ${props => | color: ${props => | ||||
| props.disabled | props.disabled | ||||
| ? props.theme.buttons.disabled.color | ? props.theme.buttons.disabled.color | ||||
| : props.theme.buttons.primary.color}; | : props.theme.buttons.primary.color}; | ||||
| border: 1px solid ${props => (props.disabled ? 'none' : props.theme.accent)}; | |||||
| ${props => | ${props => | ||||
| props.disabled | props.disabled | ||||
| ? `background: ${props.theme.buttons.disabled.background};` | ? `border: none; background: ${props.theme.buttons.disabled.background};` | ||||
| : `background-image: ${props.theme.buttons.primary.backgroundImage}; `}; | : ` | ||||
| background-size: 200% auto; | border-top: 1px solid ${props.theme.buttons.primary.borderTop}; | ||||
| border-left: 1px solid ${props.theme.buttons.primary.borderTop}; | |||||
| border-right: 1px solid ${props.theme.buttons.primary.borderBottom}; | |||||
| border-bottom: 1px solid ${props.theme.buttons.primary.borderBottom}; | |||||
| background: ${props.theme.buttons.primary.background}; | |||||
| `}; | |||||
| `; | `; | ||||
| const ModalCancel = styled(ModalBaseButton)` | const ModalCancel = styled(ModalBaseButton)` | ||||
| color: ${props => props.theme.buttons.primary.color}; | color: ${props => props.theme.buttons.primary.color}; | ||||
| border: 1px solid ${props => props.theme.secondaryAccent}; | border: 1px solid ${props => props.theme.secondaryAccent}; | ||||
| background-image: ${props => props.theme.buttons.secondary.backgroundImage}; | background-image: ${props => props.theme.buttons.secondary.backgroundImage}; | ||||
| background-size: 200% auto; | background-size: 200% auto; | ||||
| :hover { | :hover { | ||||
| color: ${props => props.theme.buttons.primary.color}; | color: ${props => props.theme.buttons.primary.color}; | ||||
| background-color: ${props => props.theme.secondaryAccent + '60'}; | background-color: ${props => props.theme.secondaryAccent + '60'}; | ||||
| } | } | ||||
| `; | `; | ||||
| const ModalExit = styled.button` | const ModalExit = styled.button` | ||||
| position: absolute; | position: absolute; | ||||
| font-size: var(--text-lg); | |||||
| line-height: var(--text-lg--line-height); | |||||
| z-index: 1001; | z-index: 1001; | ||||
| right: 5px; | right: 14px; | ||||
| top: 5px; | top: 14px; | ||||
| background: none; | background: none; | ||||
| border: none !important; | border: none !important; | ||||
| margin: 0; | |||||
| padding: 0; | |||||
| opacity: 0.5; | |||||
| color: ${props => props.theme.primaryText}; | color: ${props => props.theme.primaryText}; | ||||
| font-weight: bold; | |||||
| cursor: pointer; | cursor: pointer; | ||||
| :hover { | :hover { | ||||
| color: ${props => props.theme.secondaryAccent}; | color: ${props => props.theme.accent}; | ||||
| opacity: 1; | |||||
| } | } | ||||
| `; | `; | ||||
| const Overlay = styled.div` | const Overlay = styled.div` | ||||
| z-index: 999; | z-index: 999; | ||||
| position: fixed; | position: fixed; | ||||
| top: 0; | top: 0; | ||||
| left: 0; | left: 0; | ||||
| width: 100%; | width: 100%; | ||||
| height: 100%; | height: 100%; | ||||
| background-color: rgba(0, 0, 0, 0.1); | |||||
| backdrop-filter: blur(10px); | |||||
| `; | `; | ||||
| interface ModalProps { | interface ModalProps { | ||||
| title?: string; | title?: string; | ||||
| description?: string; | description?: string; | ||||
| handleOk?: () => void; | handleOk?: () => void; | ||||
| handleCancel: () => void; | handleCancel: () => void; | ||||
| showCancelButton?: boolean; | showCancelButton?: boolean; | ||||
| Show All 19 Lines | export const Modal: React.FC<ModalProps> = ({ | ||||
| disabled = false, | disabled = false, | ||||
| noScroll = false, | noScroll = false, | ||||
| paddingPx, | paddingPx, | ||||
| isConfirmLoading = false, | isConfirmLoading = false, | ||||
| }) => { | }) => { | ||||
| return ( | return ( | ||||
| <> | <> | ||||
| <ModalContainer width={width} height={height} paddingPx={paddingPx}> | <ModalContainer width={width} height={height} paddingPx={paddingPx}> | ||||
| <ModalExit onClick={handleCancel}>X</ModalExit> | <ModalExit onClick={handleCancel}> | ||||
| <CloseIcon | |||||
| title="Close" | |||||
| width={15} | |||||
| height={15} | |||||
| fill="currentColor" | |||||
| /> | |||||
| </ModalExit> | |||||
| <ModalBody | <ModalBody | ||||
| height={height} | height={height} | ||||
| showButtons={showButtons} | showButtons={showButtons} | ||||
| noScroll={noScroll} | noScroll={noScroll} | ||||
| > | > | ||||
| {typeof title !== 'undefined' && ( | {typeof title !== 'undefined' && ( | ||||
| <ModalTitle>{title}</ModalTitle> | <ModalTitle>{title}</ModalTitle> | ||||
| )} | )} | ||||
| Show All 28 Lines | |||||