feat(components): [popconfirm] add actions slot (#17957)

* feat(components): [popconfirm] add actions slot

close #4733

* feat(components): [popconfirm] pass handlers to actions slot

* docs(components): [popconfirm] tweak example

* chore: tweak

* chore: tweak

* chore: update test

---------

Co-authored-by: btea <2356281422@qq.com>
This commit is contained in:
Typed SIGTERM 2024-08-23 08:29:34 +08:00 committed by GitHub
parent 00e1ccc2b1
commit 5f32318377
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 114 additions and 22 deletions

View File

@ -65,6 +65,7 @@ popconfirm/trigger-event
### Slots
| Name | Description |
| --------- | ------------------------------------- |
| reference | HTML element that triggers Popconfirm |
| Name | Description | Type |
| ---------------- | ------------------------------------- | -------------------------------------------------------------------------------- |
| reference | HTML element that triggers Popconfirm | — |
| actions ^(2.8.1) | content of the Popconfirm footer | ^[object]`{ confirm: (e: MouseEvent) => void, cancel: (e: MouseEvent) => void }` |

View File

@ -1,18 +1,34 @@
<template>
<el-popconfirm
width="220"
confirm-button-text="OK"
cancel-button-text="No, Thanks"
:icon="InfoFilled"
icon-color="#626AEF"
title="Are you sure to delete this?"
@cancel="onCancel"
>
<template #reference>
<el-button>Delete</el-button>
</template>
<template #actions="{ confirm, cancel }">
<el-button size="small" @click="cancel">No!</el-button>
<el-button
type="danger"
size="small"
:disabled="!clicked"
@click="confirm"
>
Yes?
</el-button>
</template>
</el-popconfirm>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { InfoFilled } from '@element-plus/icons-vue'
const clicked = ref(false)
function onCancel() {
clicked.value = true
}
</script>

View File

@ -1,11 +1,12 @@
import { nextTick } from 'vue'
import { mount } from '@vue/test-utils'
import { afterEach, describe, expect, it } from 'vitest'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { rAF } from '@element-plus/test-utils/tick'
import { usePopperContainerId } from '@element-plus/hooks'
import Popconfirm from '../src/popconfirm.vue'
const AXIOM = 'rem is the best girl'
const FUN = 'dQw4w9WgXcQ'
const selector = '.el-popper'
describe('Popconfirm.vue', () => {
@ -77,4 +78,76 @@ describe('Popconfirm.vue', () => {
expect(document.body.querySelector(selector.value)!.innerHTML).toBe('')
})
})
describe('actions slot', () => {
it('should override default buttons when given actions', async () => {
const wrapper = mount(() => (
<>
<Popconfirm
v-slots={{
reference: () => <div class="reference">{AXIOM}</div>,
actions: () => <div class="actions">{FUN}</div>,
}}
/>
</>
))
await nextTick()
await wrapper.find('.reference').trigger('click')
await nextTick()
await rAF()
const content = document.querySelector(selector)!.innerHTML
expect(content).toContain(FUN)
expect(content).not.toContain('.el-button')
})
it('should pass handlers that can emit events', async () => {
const confirm = vi.fn()
const cancel = vi.fn()
const wrapper = mount(() => (
<>
<Popconfirm
onConfirm={confirm}
onCancel={cancel}
teleported={false}
v-slots={{
reference: () => <div class="reference">{AXIOM}</div>,
actions: ({ confirm, cancel }: { confirm: any; cancel: any }) => (
<>
<button class="confirm" onClick={confirm}>
Confirm
</button>
<button class="cancel" onClick={cancel}>
Cancel
</button>
</>
),
}}
/>
</>
))
await nextTick()
await wrapper.find('.reference').trigger('click')
await nextTick()
await rAF()
expect(wrapper.emitted()).not.toHaveProperty('confirm')
await wrapper.find('.confirm').trigger('click')
await nextTick()
await rAF()
expect(confirm).toHaveBeenCalled()
await nextTick()
await wrapper.find('.reference').trigger('click')
await nextTick()
await rAF()
expect(wrapper.emitted()).not.toHaveProperty('cancel')
await wrapper.find('.cancel').trigger('click')
await nextTick()
await rAF()
expect(cancel).toHaveBeenCalled()
})
})
})

View File

@ -24,22 +24,24 @@
{{ title }}
</div>
<div :class="ns.e('action')">
<el-button
size="small"
:type="cancelButtonType === 'text' ? '' : cancelButtonType"
:text="cancelButtonType === 'text'"
@click="cancel"
>
{{ finalCancelButtonText }}
</el-button>
<el-button
size="small"
:type="confirmButtonType === 'text' ? '' : confirmButtonType"
:text="confirmButtonType === 'text'"
@click="confirm"
>
{{ finalConfirmButtonText }}
</el-button>
<slot name="actions" :confirm="confirm" :cancel="cancel">
<el-button
size="small"
:type="cancelButtonType === 'text' ? '' : cancelButtonType"
:text="cancelButtonType === 'text'"
@click="cancel"
>
{{ finalCancelButtonText }}
</el-button>
<el-button
size="small"
:type="confirmButtonType === 'text' ? '' : confirmButtonType"
:text="confirmButtonType === 'text'"
@click="confirm"
>
{{ finalConfirmButtonText }}
</el-button>
</slot>
</div>
</div>
</template>