Skip to content

Commit

Permalink
Fix #4051: ConfirmDialog/Popup defaultFocus prop (#5401)
Browse files Browse the repository at this point in the history
  • Loading branch information
melloware authored Nov 27, 2023
1 parent ef338f5 commit 3e278fb
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 32 deletions.
6 changes: 6 additions & 0 deletions components/doc/confirmdialog/basicdoc.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export function BasicDoc(props) {
message: 'Are you sure you want to proceed?',
header: 'Confirmation',
icon: 'pi pi-exclamation-triangle',
defaultFocus: 'accept',
accept,
reject
});
Expand All @@ -32,6 +33,7 @@ export function BasicDoc(props) {
header: 'Delete Confirmation',
icon: 'pi pi-info-circle',
acceptClassName: 'p-button-danger',
defaultFocus: 'reject',
accept,
reject
});
Expand Down Expand Up @@ -66,6 +68,7 @@ export default function BasicDemo() {
message: 'Are you sure you want to proceed?',
header: 'Confirmation',
icon: 'pi pi-exclamation-triangle',
defaultFocus: 'accept',
accept,
reject
});
Expand All @@ -76,6 +79,7 @@ export default function BasicDemo() {
message: 'Do you want to delete this record?',
header: 'Delete Confirmation',
icon: 'pi pi-info-circle',
defaultFocus: 'reject',
acceptClassName: 'p-button-danger',
accept,
reject
Expand Down Expand Up @@ -116,6 +120,7 @@ export default function BasicDemo() {
message: 'Are you sure you want to proceed?',
header: 'Confirmation',
icon: 'pi pi-exclamation-triangle',
defaultFocus: 'accept',
accept,
reject
});
Expand All @@ -126,6 +131,7 @@ export default function BasicDemo() {
message: 'Do you want to delete this record?',
header: 'Delete Confirmation',
icon: 'pi pi-info-circle',
defaultFocus: 'reject',
acceptClassName: 'p-button-danger',
accept,
reject
Expand Down
6 changes: 6 additions & 0 deletions components/doc/confirmpopup/basicdoc.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export function BasicDoc(props) {
target: event.currentTarget,
message: 'Are you sure you want to proceed?',
icon: 'pi pi-exclamation-triangle',
defaultFocus: 'accept',
accept,
reject
});
Expand All @@ -32,6 +33,7 @@ export function BasicDoc(props) {
message: 'Do you want to delete this record?',
icon: 'pi pi-info-circle',
acceptClassName: 'p-button-danger',
defaultFocus: 'reject',
accept,
reject
});
Expand Down Expand Up @@ -68,6 +70,7 @@ export default function BasicDemo() {
target: event.currentTarget,
message: 'Are you sure you want to proceed?',
icon: 'pi pi-exclamation-triangle',
defaultFocus: 'accept',
accept,
reject
});
Expand All @@ -78,6 +81,7 @@ export default function BasicDemo() {
target: event.currentTarget,
message: 'Do you want to delete this record?',
icon: 'pi pi-info-circle',
defaultFocus: 'reject',
acceptClassName: 'p-button-danger',
accept,
reject
Expand Down Expand Up @@ -118,6 +122,7 @@ export default function BasicDemo() {
target: event.currentTarget,
message: 'Are you sure you want to proceed?',
icon: 'pi pi-exclamation-triangle',
defaultFocus: 'accept',
accept,
reject
});
Expand All @@ -128,6 +133,7 @@ export default function BasicDemo() {
target: event.currentTarget,
message: 'Do you want to delete this record?',
icon: 'pi pi-info-circle',
defaultFocus: 'reject',
acceptClassName: 'p-button-danger',
accept,
reject
Expand Down
5 changes: 4 additions & 1 deletion components/lib/confirmdialog/ConfirmDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ export const ConfirmDialog = React.memo(
}));

const createFooter = () => {
const defaultFocus = getPropValue('defaultFocus');
const acceptClassName = classNames('p-confirm-dialog-accept', getPropValue('acceptClassName'));
const rejectClassName = classNames(
'p-confirm-dialog-reject',
Expand All @@ -137,6 +138,7 @@ export const ConfirmDialog = React.memo(

const rejectButtonProps = {
label: rejectLabel,
autoFocus: defaultFocus === 'reject',
icon: getPropValue('rejectIcon'),
className: classNames(getPropValue('rejectClassName'), cx('rejectButton', { getPropValue })),
onClick: reject,
Expand All @@ -150,6 +152,7 @@ export const ConfirmDialog = React.memo(
const acceptButtonProps = mergeProps(
{
label: acceptLabel,
autoFocus: defaultFocus === undefined || defaultFocus === 'accept',
icon: getPropValue('acceptIcon'),
className: classNames(getPropValue('acceptClassName'), cx('acceptButton')),
onClick: accept,
Expand All @@ -164,7 +167,7 @@ export const ConfirmDialog = React.memo(
const content = (
<>
<Button {...rejectButtonProps} />
<Button {...acceptButtonProps} autoFocus />
<Button {...acceptButtonProps} />
</>
);

Expand Down
25 changes: 13 additions & 12 deletions components/lib/confirmdialog/ConfirmDialogBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,24 @@ const classes = {
export const ConfirmDialogBase = ComponentBase.extend({
defaultProps: {
__TYPE: 'ConfirmDialog',
tagKey: undefined,
visible: undefined,
message: null,
rejectLabel: null,
acceptLabel: null,
icon: null,
rejectIcon: null,
acceptIcon: null,
rejectClassName: null,
accept: null,
acceptClassName: null,
className: null,
acceptIcon: null,
acceptLabel: null,
appendTo: null,
footer: null,
breakpoints: null,
className: null,
defaultFocus: 'accept',
footer: null,
icon: null,
message: null,
onHide: null,
accept: null,
reject: null,
rejectClassName: null,
rejectIcon: null,
rejectLabel: null,
tagKey: undefined,
visible: undefined,
children: undefined
},
css: {
Expand Down
10 changes: 10 additions & 0 deletions components/lib/confirmdialog/confirmdialog.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ interface ConfirmDialogOptions {
* @defaultValue No
*/
rejectLabel: string;
/**
* Element to receive the focus when the dialog gets visible, valid values are "accept" and "reject".
* @defaultValue accept
*/
defaultFocus: string;
/**
* Default element created by the component.
*/
Expand Down Expand Up @@ -194,6 +199,11 @@ export interface ConfirmDialogProps extends Omit<DialogProps, 'onHide' | 'footer
* Style class of the accept button.
*/
acceptClassName?: string | undefined;
/**
* Element to receive the focus when the dialog gets visible, valid values are "accept" and "reject".
* @defaultValue accept
*/
defaultFocus?: string | undefined;
/**
* DOM element instance where the overlay panel should be mounted. Valid values are any DOM Element and "self". The "self" value is used to render a component where it is located.
* @defaultValue document.body
Expand Down
14 changes: 11 additions & 3 deletions components/lib/confirmpopup/ConfirmPopup.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as React from 'react';
import { useOnEscapeKey } from '../../lib/hooks/Hooks';
import PrimeReact, { PrimeReactContext, localeOption } from '../api/Api';
import { Button } from '../button/Button';
import { useHandleStyle } from '../componentbase/ComponentBase';
Expand All @@ -8,7 +9,6 @@ import { OverlayService } from '../overlayservice/OverlayService';
import { Portal } from '../portal/Portal';
import { DomHandler, IconUtils, ObjectUtils, ZIndexUtils, classNames, mergeProps } from '../utils/Utils';
import { ConfirmPopupBase } from './ConfirmPopupBase';
import { useOnEscapeKey } from '../../lib/hooks/Hooks';

export const confirmPopup = (props = {}) => {
props = { ...props, ...{ visible: props.visible === undefined ? true : props.visible } };
Expand Down Expand Up @@ -45,6 +45,7 @@ export const ConfirmPopup = React.memo(

const overlayRef = React.useRef(null);
const acceptBtnRef = React.useRef(null);
const rejectBtnRef = React.useRef(null);
const isPanelClicked = React.useRef(false);
const overlayEventListener = React.useRef(null);
const confirmProps = React.useRef(null);
Expand Down Expand Up @@ -137,8 +138,14 @@ export const ConfirmPopup = React.memo(
const onEntered = () => {
bindOverlayListener();

if (acceptBtnRef.current) {
acceptBtnRef.current.focus();
const defaultFocus = getPropValue('defaultFocus');

if (defaultFocus === undefined || defaultFocus === 'accept') {
acceptBtnRef.current && acceptBtnRef.current.focus();
}

if (defaultFocus === 'reject') {
rejectBtnRef.current && rejectBtnRef.current.focus();
}

callbackFromProp('onShow');
Expand Down Expand Up @@ -280,6 +287,7 @@ export const ConfirmPopup = React.memo(
);

const rejectButtonProps = mergeProps({
ref: rejectBtnRef,
label: rejectLabel,
icon: getPropValue('rejectIcon'),
className: cx('rejectButton', { getPropValue }),
Expand Down
33 changes: 17 additions & 16 deletions components/lib/confirmpopup/ConfirmPopupBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,29 +74,30 @@ const classes = {
export const ConfirmPopupBase = ComponentBase.extend({
defaultProps: {
__TYPE: 'ConfirmPopup',
tagKey: undefined,
target: null,
visible: false,
message: null,
rejectLabel: null,
acceptLabel: null,
icon: null,
rejectIcon: null,
acceptIcon: null,
rejectClassName: null,
accept: null,
acceptClassName: null,
className: null,
style: null,
acceptIcon: null,
acceptLabel: null,
appendTo: null,
children: undefined,
className: null,
closeOnEscape: true,
defaultFocus: 'accept',
dismissable: true,
footer: null,
onShow: null,
icon: null,
message: null,
onHide: null,
accept: null,
onShow: null,
reject: null,
rejectClassName: null,
rejectIcon: null,
rejectLabel: null,
style: null,
tagKey: undefined,
target: null,
transitionOptions: null,
children: undefined,
closeOnEscape: true
visible: false
},
css: {
classes,
Expand Down
10 changes: 10 additions & 0 deletions components/lib/confirmpopup/confirmpopup.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ interface ConfirmPopupOptions {
* @defaultValue No
*/
rejectLabel: string;
/**
* Element to receive the focus when the dialog gets visible, valid values are "accept" and "reject".
* @defaultValue accept
*/
defaultFocus: string;
/**
* Default element created by the component.
*/
Expand Down Expand Up @@ -155,6 +160,11 @@ export interface ConfirmPopupProps {
* @defaultValue false
*/
visible?: boolean | undefined;
/**
* Element to receive the focus when the dialog gets visible, valid values are "accept" and "reject".
* @defaultValue accept
*/
defaultFocus?: string | undefined;
/**
* Message of the confirmation.
*/
Expand Down

0 comments on commit 3e278fb

Please sign in to comment.