Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dialog): 增加关闭按钮 #1872

Merged
merged 13 commits into from
Jan 19, 2024
38 changes: 38 additions & 0 deletions src/packages/dialog/__test__/dialog.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,41 @@ test('dialog cancelText confirmText', async () => {
expect(footerOkEle).toHaveTextContent('确定文案自定义')
expect(footerCancelEle).toHaveTextContent('取消文案自定义')
})

test('dialog closeIcon equals true', async () => {
const { container } = render(
<Dialog
visible
cancelText="取消文案自定义"
confirmText="确定文案自定义"
closeIcon
/>
)

const closeBtn = container.querySelector('.nut-dialog-close')
expect(closeBtn).toBeInTheDocument()
})

test('dialog close icon position adjustment', async () => {
const onClose = jest.fn()
const onCancel = jest.fn()
const { container } = render(
<Dialog
visible
cancelText="取消文案自定义"
confirmText="确定文案自定义"
closeIcon
closeIconPosition="top-left"
onClose={onClose}
onCancel={onCancel}
/>
)

const closeBtn = container.querySelector(
'.nut-dialog-close-top-left'
) as HTMLElement
expect(closeBtn).toBeInTheDocument()
fireEvent.click(closeBtn)
expect(onClose).toBeCalled()
expect(onCancel).toBeCalled()
})
2 changes: 2 additions & 0 deletions src/packages/dialog/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export interface BasicDialogProps extends BasicComponent {
closeOnOverlayClick?: boolean
footerDirection?: string
lockScroll?: boolean
closeIconPosition?: string
closeIcon?: boolean | ReactNode
beforeClose?: () => boolean
beforeCancel?: () => boolean
onClose?: () => void
Expand Down
15 changes: 13 additions & 2 deletions src/packages/dialog/content.taro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ interface ContentProps extends BasicComponent {
title: ReactNode
header: ReactNode
footer: ReactNode
close: ReactNode
footerDirection: string
onClick: (event: ITouchEvent) => void
}
Expand All @@ -16,10 +17,19 @@ export const Content: FunctionComponent<
Partial<ContentProps> &
Omit<HTMLAttributes<HTMLDivElement>, 'onClick' | 'title'>
> = (props) => {
const { visible, title, header, footer, footerDirection, onClick, children } =
props
const {
visible,
title,
header,
footer,
close,
footerDirection,
onClick,
children,
} = props

const classPrefix = 'nut-dialog'

const renderHeader = () => {
return title ? <div className={`${classPrefix}-header`}>{title}</div> : null
}
Expand All @@ -46,6 +56,7 @@ export const Content: FunctionComponent<
style={props.style}
onClick={(e) => handleClick(e)}
>
{close}
{header}
<div
className={classPrefix}
Expand Down
14 changes: 12 additions & 2 deletions src/packages/dialog/content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,23 @@ interface ContentProps {
title: ReactNode
header: ReactNode
footer: ReactNode
close: ReactNode
footerDirection: string
}

export const Content: FunctionComponent<
Partial<ContentProps> & HTMLAttributes<HTMLDivElement>
> = (props) => {
const { visible, title, header, footer, footerDirection, onClick, children } =
props
const {
visible,
title,
header,
footer,
close,
footerDirection,
onClick,
children,
} = props

const classPrefix = 'nut-dialog'

Expand Down Expand Up @@ -43,6 +52,7 @@ export const Content: FunctionComponent<
style={props.style}
onClick={(e) => handleClick(e)}
>
{close}
{header}
<div
className={classPrefix}
Expand Down
48 changes: 48 additions & 0 deletions src/packages/dialog/demo.taro.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState } from 'react'
import Taro from '@tarojs/taro'
import { ArrowCornerLeft } from '@nutui/icons-react-taro'
import { Dialog, Cell, Image } from '@/packages/nutui.react.taro'
import { useTranslate } from '@/sites/assets/locale/taro'
import Header from '@/sites/components/header'
Expand All @@ -20,6 +21,8 @@ interface T {
confirmText: string
cancelText: string
header: string
closeIcon: string
customClose: string
}

const DialogDemo = () => {
Expand All @@ -40,6 +43,8 @@ const DialogDemo = () => {
confirmText: '确定',
cancelText: '取消',
header: '顶部带插图',
closeIcon: '顶部带关闭按钮',
customClose: '自定义顶部关闭按钮',
},
'en-US': {
basic: 'Basic Usage',
Expand All @@ -58,6 +63,8 @@ const DialogDemo = () => {
confirmText: 'confirm',
cancelText: 'cancel',
header: 'Top with illustration',
closeIcon: 'Top with close button',
customClose: 'Customize the top close button',
},
})

Expand All @@ -69,6 +76,9 @@ const DialogDemo = () => {
const [visible6, setVisible6] = useState(false)
const [visible7, setVisible7] = useState(false)
const [visible8, setVisible8] = useState(false)
const [visible9, setVisible9] = useState(false)
const [visible10, setVisible10] = useState(false)

return (
<>
<Header />
Expand Down Expand Up @@ -191,6 +201,44 @@ const DialogDemo = () => {
>
{translated.content}
</Dialog>
<Cell
title={translated.closeIcon}
onClick={() => {
setVisible9(true)
}}
/>
<Dialog
className="test-dialog"
title={translated.closeIcon}
visible={visible9}
closeIcon
onConfirm={() => setVisible9(false)}
onCancel={() => setVisible9(false)}
>
{translated.content}
</Dialog>
<Cell
title={translated.customClose}
onClick={() => {
setVisible10(true)
}}
/>
<Dialog
className="test-dialog"
title={translated.customClose}
visible={visible10}
closeIcon={<ArrowCornerLeft width="16px" height="16px" />}
closeIconPosition="top-left"
onConfirm={() => setVisible10(false)}
onCancel={() => setVisible10(false)}
style={{
'--nutui-dialog-close-top': '10px',
'--nutui-dialog-close-left': '10px',
'--nutui-dialog-close-color': 'red',
}}
>
{translated.content}
</Dialog>
</div>
</>
)
Expand Down
47 changes: 47 additions & 0 deletions src/packages/dialog/demo.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState } from 'react'
import { ArrowCornerLeft } from '@nutui/icons-react'
import { Dialog } from './dialog'
import Cell from '../cell'
import { useTranslate } from '@/sites/assets/locale'
Expand All @@ -21,6 +22,8 @@ interface T {
confirmText: string
cancelText: string
header: string
closeIcon: string
customClose: string
}

const DialogDemo = () => {
Expand All @@ -42,6 +45,8 @@ const DialogDemo = () => {
confirmText: '确定',
cancelText: '取消',
header: '顶部带插图',
closeIcon: '顶部带关闭按钮',
customClose: '自定义顶部关闭按钮',
},
'en-US': {
funUse: 'Function use',
Expand All @@ -61,6 +66,8 @@ const DialogDemo = () => {
confirmText: 'confirm',
cancelText: 'cancel',
header: 'Top with illustration',
closeIcon: 'Top with close button',
customClose: 'Customize the top close button',
},
})

Expand All @@ -71,6 +78,8 @@ const DialogDemo = () => {
const [visible5, setVisible5] = useState(false)
const [visible6, setVisible6] = useState(false)
const [visible7, setVisible7] = useState(false)
const [visible8, setVisible8] = useState(false)
const [visible9, setVisible9] = useState(false)

return (
<>
Expand Down Expand Up @@ -264,6 +273,44 @@ const DialogDemo = () => {
>
{translated.content}
</Dialog>
<Cell
title={translated.closeIcon}
onClick={() => {
setVisible8(true)
}}
/>
<Dialog
className="test-dialog"
title={translated.closeIcon}
visible={visible8}
closeIcon
onConfirm={() => setVisible8(false)}
onCancel={() => setVisible8(false)}
>
{translated.content}
</Dialog>
<Cell
title={translated.customClose}
onClick={() => {
setVisible9(true)
}}
/>
<Dialog
className="test-dialog"
title={translated.customClose}
visible={visible9}
closeIcon={<ArrowCornerLeft width="16px" height="16px" />}
closeIconPosition="top-left"
onConfirm={() => setVisible9(false)}
onCancel={() => setVisible9(false)}
style={{
'--nutui-dialog-close-top': '10px',
'--nutui-dialog-close-left': '10px',
'--nutui-dialog-close-color': 'red',
}}
>
{translated.content}
</Dialog>
</div>
</>
)
Expand Down
25 changes: 25 additions & 0 deletions src/packages/dialog/dialog.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,31 @@
animation-duration: 0.3s;
}

&-close {
position: absolute !important;
z-index: 1;
cursor: pointer;
width: $dialog-close-width;
height: $dialog-close-height;
display: flex;
justify-content: center;
align-items: center;
top: $dialog-close-top;
color: $dialog-close-color;

&-top-right {
right: $dialog-close-right;
}

&-top-left {
left: $dialog-close-left;
}

&:active {
opacity: 0.7;
}
}

&-header {
display: block;
text-align: center;
Expand Down
27 changes: 27 additions & 0 deletions src/packages/dialog/dialog.taro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { MouseEvent } from 'react'
import classNames from 'classnames'
import { CSSTransition } from 'react-transition-group'
import { View } from '@tarojs/components'
import { Close } from '@nutui/icons-react-taro'
import Button from '@/packages/button/index.taro'
import { BasicDialogProps } from './config'
import { Content } from './content.taro'
Expand Down Expand Up @@ -32,6 +33,8 @@ const defaultProps = {
disableConfirmButton: false,
footerDirection: 'horizontal',
lockScroll: true,
closeIconPosition: 'top-right',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里也更新下类型

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里也更新下类型
已修改

closeIcon: false,
beforeCancel: () => true,
beforeClose: () => true,
onOverlayClick: () => true,
Expand Down Expand Up @@ -65,6 +68,8 @@ export const BaseDialog: FunctionComponent<Partial<DialogProps>> & {
confirmText,
cancelText,
overlay,
closeIconPosition,
closeIcon,
onClose,
onCancel,
onConfirm,
Expand Down Expand Up @@ -101,6 +106,7 @@ export const BaseDialog: FunctionComponent<Partial<DialogProps>> & {
onClose?.()
onConfirm?.(e)
}

return (
footer || (
<>
Expand Down Expand Up @@ -129,6 +135,26 @@ export const BaseDialog: FunctionComponent<Partial<DialogProps>> & {
)
)
}

const renderCloseIcon = () => {
if (!closeIcon) return null
const handleCancel = () => {
if (!beforeCancel?.()) return
if (!beforeClose?.()) return
onClose?.()
onCancel?.()
}
const closeClasses = classNames({
[`${classPrefix}-close`]: true,
[`${classPrefix}-close-${closeIconPosition}`]: true,
})
return (
<View className={closeClasses} onClick={handleCancel}>
{React.isValidElement(closeIcon) ? closeIcon : <Close />}
</View>
)
}

const onHandleClickOverlay = (e: any) => {
if (closeOnOverlayClick && visible && e.target === e.currentTarget) {
const closed = onOverlayClick && onOverlayClick()
Expand Down Expand Up @@ -166,6 +192,7 @@ export const BaseDialog: FunctionComponent<Partial<DialogProps>> & {
style={style}
title={title}
header={header}
close={renderCloseIcon()}
footer={renderFooter()}
footerDirection={footerDirection}
visible={visible}
Expand Down
Loading
Loading