49 lines
1.7 KiB
JavaScript
49 lines
1.7 KiB
JavaScript
'use client';
|
|
import * as React from 'react';
|
|
import { isHTMLElement } from '@fluentui/react-utilities';
|
|
/**
|
|
* Wraps an aria live announcement function.
|
|
* Aria live announcements can be detrimental once the user is already navigating
|
|
* multiple toasts. Once the user is focused inside the toaster, the announecments should be disabled.
|
|
* @param announce
|
|
* @returns A function to announce a toast and a ref to attach to the toaster element
|
|
*/ export function useToastAnnounce(announce) {
|
|
const activeRef = React.useRef(true);
|
|
const cleanupRef = React.useRef(()=>undefined);
|
|
const announceToast = React.useCallback((message, options)=>{
|
|
if (activeRef.current) {
|
|
announce(message, options);
|
|
}
|
|
}, [
|
|
announce
|
|
]);
|
|
const toasterRef = React.useCallback((el)=>{
|
|
if (!el) {
|
|
cleanupRef.current();
|
|
return;
|
|
}
|
|
const onFocusIn = (e)=>{
|
|
if (isHTMLElement(e.currentTarget) && e.currentTarget.contains(isHTMLElement(e.relatedTarget) ? e.relatedTarget : null)) {
|
|
return;
|
|
}
|
|
activeRef.current = false;
|
|
};
|
|
const onFocusOut = (e)=>{
|
|
if (isHTMLElement(e.currentTarget) && e.currentTarget.contains(isHTMLElement(e.relatedTarget) ? e.relatedTarget : null)) {
|
|
return;
|
|
}
|
|
activeRef.current = true;
|
|
};
|
|
el.addEventListener('focusin', onFocusIn);
|
|
el.addEventListener('focusout', onFocusOut);
|
|
cleanupRef.current = ()=>{
|
|
el.removeEventListener('focusin', onFocusIn);
|
|
el.removeEventListener('focusout', onFocusOut);
|
|
};
|
|
}, []);
|
|
return {
|
|
announceToast,
|
|
toasterRef
|
|
};
|
|
}
|