Skip to content

Commit

Permalink
Merge branch 'main' into fix/react/warnings-from-SideNav-in-console
Browse files Browse the repository at this point in the history
  • Loading branch information
kuri-sun authored Nov 8, 2023
2 parents 1e56505 + 6d2b92c commit fa7826a
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 24 deletions.
1 change: 0 additions & 1 deletion e2e/components/Notifications/Notifications-test.avt.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ test.describe('Notifications @avt', () => {

await expect(actionButton).toBeVisible();

await page.keyboard.press('Tab');
await expect(actionButton).toBeFocused();

await page.keyboard.press('Tab');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,7 @@ describe('ActionableNotification', () => {
/>
);

// without focus being on/in the notification, it should not close via escape
await userEvent.keyboard('{Escape}');
expect(onCloseButtonClick).toHaveBeenCalledTimes(0);
expect(onClose).toHaveBeenCalledTimes(0);

// after focus is placed, the notification should close via escape
await userEvent.tab();
await userEvent.keyboard('{Escape}');
expect(onCloseButtonClick).toHaveBeenCalledTimes(1);
expect(onClose).toHaveBeenCalledTimes(1);
Expand Down
78 changes: 61 additions & 17 deletions packages/react/src/components/Notification/Notification.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { keys, matches } from '../../internal/keyboard';
import { usePrefix } from '../../internal/usePrefix';
import { useId } from '../../internal/useId';
import { noopFn } from '../../internal/noopFn';
import wrapFocus from '../../internal/wrapFocus';

/**
* Conditionally call a callback when the escape key is pressed
Expand Down Expand Up @@ -943,14 +944,38 @@ export function ActionableNotification({
[`${prefix}--actionable-notification--${kind}`]: kind,
[`${prefix}--actionable-notification--hide-close-button`]: hideCloseButton,
});

const innerModal = useRef<HTMLDivElement>(null);
const startTrap = useRef<HTMLElement>(null);
const endTrap = useRef<HTMLElement>(null);
const ref = useRef<HTMLDivElement>(null);

useIsomorphicEffect(() => {
if (ref.current && hasFocus) {
ref.current.focus();
if (hasFocus) {
const button = document.querySelector(
'button.cds--actionable-notification__action-button'
) as HTMLButtonElement;
button?.focus();
}
});

function handleBlur({
target: oldActiveNode,
relatedTarget: currentActiveNode,
}) {
if (isOpen && currentActiveNode && oldActiveNode) {
const { current: bodyNode } = innerModal;
const { current: startTrapNode } = startTrap;
const { current: endTrapNode } = endTrap;
wrapFocus({
bodyNode,
startTrapNode,
endTrapNode,
currentActiveNode,
oldActiveNode,
});
}
}

const handleClose = (evt: MouseEvent) => {
if (!onClose || onClose(evt) !== false) {
setIsOpen(false);
Expand All @@ -973,7 +998,16 @@ export function ActionableNotification({
ref={ref}
role={role}
className={containerClassName}
aria-labelledby={title ? id : subtitleId}>
aria-labelledby={title ? id : subtitleId}
onBlur={handleBlur}>
<span
ref={startTrap}
tabIndex={0}
role="link"
className={`${prefix}--visually-hidden`}>
Focus sentinel
</span>

<div className={`${prefix}--actionable-notification__details`}>
<NotificationIcon
notificationType={inline ? 'inline' : 'toast'}
Expand Down Expand Up @@ -1002,20 +1036,30 @@ export function ActionableNotification({
</div>
</div>
</div>
<div ref={innerModal}>
{actionButtonLabel && (
<NotificationActionButton
onClick={onActionButtonClick}
inline={inline}>
{actionButtonLabel}
</NotificationActionButton>
)}

{actionButtonLabel && (
<NotificationActionButton onClick={onActionButtonClick} inline={inline}>
{actionButtonLabel}
</NotificationActionButton>
)}

{!hideCloseButton && (
<NotificationButton
aria-label={deprecatedAriaLabel || ariaLabel}
notificationType="actionable"
onClick={handleCloseButtonClick}
/>
)}
{!hideCloseButton && (
<NotificationButton
aria-label={deprecatedAriaLabel || ariaLabel}
notificationType="actionable"
onClick={handleCloseButtonClick}
/>
)}
</div>
<span
ref={endTrap}
tabIndex={0}
role="link"
className={`${prefix}--visually-hidden`}>
Focus sentinel
</span>
</div>
);
}
Expand Down

0 comments on commit fa7826a

Please sign in to comment.