feat(Dialog): support enter/esc keyboard event (#10261)

* feat(dialog): the enter/esc keyboard event is supported

* fix(dialog): the corresponding method is not executed when there is no button

* chore(dialog): simplify implementation

* fix: the wrong judgment
This commit is contained in:
zoy-l 2022-02-11 14:52:49 +08:00 committed by GitHub
parent fbafac333f
commit c1be4112e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 29 additions and 1 deletions

View File

@ -3,6 +3,7 @@ import {
defineComponent, defineComponent,
type PropType, type PropType,
type ExtractPropTypes, type ExtractPropTypes,
withKeys,
} from 'vue'; } from 'vue';
// Utils // Utils
@ -71,7 +72,7 @@ export default defineComponent({
props: dialogProps, props: dialogProps,
emits: ['confirm', 'cancel', 'update:show'], emits: ['confirm', 'cancel', 'update:show', 'keydown'],
setup(props, { emit, slots }) { setup(props, { emit, slots }) {
const loading = reactive({ const loading = reactive({
@ -113,6 +114,19 @@ export default defineComponent({
const onCancel = getActionHandler('cancel'); const onCancel = getActionHandler('cancel');
const onConfirm = getActionHandler('confirm'); const onConfirm = getActionHandler('confirm');
const onKeydown = withKeys(
(event: KeyboardEvent) => {
const onEventType: Record<string, () => void> = {
Enter: props.showConfirmButton ? onConfirm : () => {},
Escape: props.showCancelButton ? onCancel : () => {},
};
onEventType[event.key]();
emit('keydown', event);
},
['enter', 'esc']
);
const renderTitle = () => { const renderTitle = () => {
const title = slots.title ? slots.title() : props.title; const title = slots.title ? slots.title() : props.title;
@ -229,6 +243,8 @@ export default defineComponent({
const { width, title, theme, message, className } = props; const { width, title, theme, message, className } = props;
return ( return (
<Popup <Popup
tabindex={0}
onKeydown={onKeydown}
role="dialog" role="dialog"
class={[bem([theme]), className]} class={[bem([theme]), className]}
style={{ width: addUnit(width) }} style={{ width: addUnit(width) }}

View File

@ -96,6 +96,7 @@ exports[`should render demo and match snapshot 1`] = `
</transition-stub> </transition-stub>
<transition-stub> <transition-stub>
<div class="van-popup van-popup--center van-dialog" <div class="van-popup van-popup--center van-dialog"
tabindex="0"
role="dialog" role="dialog"
aria-labelledby="Title" aria-labelledby="Title"
style="display: none;" style="display: none;"

View File

@ -31,6 +31,7 @@ exports[`should render default slot correctly 1`] = `
exports[`should render footer slot correctly 1`] = ` exports[`should render footer slot correctly 1`] = `
<div class="van-popup van-popup--center van-dialog" <div class="van-popup van-popup--center van-dialog"
tabindex="0"
role="dialog" role="dialog"
aria-labelledby="message" aria-labelledby="message"
> >

View File

@ -3,6 +3,7 @@ import {
watch, watch,
provide, provide,
Teleport, Teleport,
nextTick,
computed, computed,
onMounted, onMounted,
Transition, Transition,
@ -68,6 +69,7 @@ export default defineComponent({
'close', 'close',
'opened', 'opened',
'closed', 'closed',
'keydown',
'update:show', 'update:show',
'click-overlay', 'click-overlay',
'click-close-icon', 'click-close-icon',
@ -172,11 +174,14 @@ export default defineComponent({
const onOpened = () => emit('opened'); const onOpened = () => emit('opened');
const onClosed = () => emit('closed'); const onClosed = () => emit('closed');
const onKeydown = (event: KeyboardEvent) => emit('keydown', event);
const renderPopup = lazyRender(() => { const renderPopup = lazyRender(() => {
const { round, position, safeAreaInsetBottom } = props; const { round, position, safeAreaInsetBottom } = props;
return ( return (
<div <div
onKeydown={onKeydown}
v-show={props.show} v-show={props.show}
ref={popupRef} ref={popupRef}
style={style.value} style={style.value}
@ -216,6 +221,11 @@ export default defineComponent({
(show) => { (show) => {
if (show && !opened) { if (show && !opened) {
open(); open();
attrs.tabindex === 0 &&
nextTick(() => {
popupRef.value?.focus();
});
} }
if (!show && opened) { if (!show && opened) {
opened = false; opened = false;