fix(techdocs): ExpandableNavigation addons does not work on Firefox
Signed-off-by: Gabriel Dugny <gabriel.dugny@believe.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-techdocs-module-addons-contrib': patch
|
||||
---
|
||||
|
||||
ExpandableCollapse Techdocs Addon was breaking native sidebar collapse on Firefox
|
||||
+54
-49
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useEffect, useCallback, useState } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useLocalStorageValue } from '@react-hookz/web';
|
||||
import { Button, withStyles } from '@material-ui/core';
|
||||
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
|
||||
@@ -73,71 +73,72 @@ export const ExpandableNavigationAddon = () => {
|
||||
NESTED_LIST_TOGGLE,
|
||||
]);
|
||||
|
||||
const shouldToggle = useCallback(
|
||||
(item: HTMLInputElement) => {
|
||||
const isExpanded = item.checked;
|
||||
const shouldExpand = expanded?.expandAllNestedNavs;
|
||||
|
||||
// Is collapsed but should expand
|
||||
if (shouldExpand && !isExpanded) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Is expanded but should collapse
|
||||
if (!shouldExpand && isExpanded) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
[expanded],
|
||||
);
|
||||
const handleKeyPass = (
|
||||
// Define handleKeyPass as a named function
|
||||
function handleKeyPass(
|
||||
event: React.KeyboardEvent<HTMLElement>,
|
||||
toggleAction: () => void,
|
||||
) => {
|
||||
) {
|
||||
if (event.key === 'Enter' || event.key === ' ') {
|
||||
event.preventDefault();
|
||||
toggleAction();
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
// There is no nested navs
|
||||
if (!checkboxToggles?.length) return;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!checkboxToggles?.length) return;
|
||||
setHasNavSubLevels(true);
|
||||
checkboxToggles.forEach(item => {
|
||||
item.tabIndex = 0;
|
||||
const toggleAction = () => {
|
||||
if (shouldToggle(item)) {
|
||||
item.click();
|
||||
function createKeydownHandler(item: HTMLInputElement) {
|
||||
return function handleKeydown(event: KeyboardEvent) {
|
||||
if (event.key === 'Enter' || event.key === ' ') {
|
||||
event.preventDefault();
|
||||
item.checked = !item.checked;
|
||||
item.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
}
|
||||
};
|
||||
// Add keyboard event listener
|
||||
const keydownHandler = (event: KeyboardEvent) => {
|
||||
handleKeyPass(
|
||||
event as unknown as React.KeyboardEvent<HTMLDivElement>,
|
||||
toggleAction,
|
||||
);
|
||||
}
|
||||
function createCleanup(
|
||||
item: HTMLInputElement,
|
||||
handler: (event: KeyboardEvent) => void,
|
||||
) {
|
||||
return function cleanup() {
|
||||
item.removeEventListener('keydown', handler);
|
||||
};
|
||||
}
|
||||
const cleanupFunctions: Array<() => void> = [];
|
||||
for (const item of checkboxToggles) {
|
||||
item.tabIndex = 0;
|
||||
const keydownHandler = createKeydownHandler(item);
|
||||
item.addEventListener('keydown', keydownHandler);
|
||||
item.addEventListener('click', toggleAction);
|
||||
cleanupFunctions.push(createCleanup(item, keydownHandler));
|
||||
}
|
||||
function cleanupAll() {
|
||||
for (const cleanup of cleanupFunctions) {
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line consistent-return
|
||||
return cleanupAll;
|
||||
}, [checkboxToggles, expanded]);
|
||||
|
||||
// Clean up event listener or unmount
|
||||
return () => {
|
||||
item.removeEventListener('keydown', keydownHandler);
|
||||
item.removeEventListener('click', toggleAction);
|
||||
};
|
||||
});
|
||||
}, [checkboxToggles, shouldToggle]);
|
||||
useEffect(() => {
|
||||
if (!checkboxToggles?.length) return;
|
||||
checkboxToggles.forEach(item => {
|
||||
function shouldToggle(item: HTMLInputElement) {
|
||||
const isExpanded = item.checked;
|
||||
const shouldExpand = expanded?.expandAllNestedNavs;
|
||||
if (shouldExpand && !isExpanded) {
|
||||
return true;
|
||||
}
|
||||
if (!shouldExpand && isExpanded) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
for (const item of checkboxToggles) {
|
||||
if (shouldToggle(item)) {
|
||||
item.click();
|
||||
}
|
||||
});
|
||||
}, [expanded, checkboxToggles, shouldToggle]);
|
||||
}
|
||||
}, [expanded, checkboxToggles]);
|
||||
|
||||
const handleState = () => {
|
||||
setExpanded(prevState => ({
|
||||
@@ -145,13 +146,17 @@ export const ExpandableNavigationAddon = () => {
|
||||
}));
|
||||
};
|
||||
|
||||
function handleButtonKeyDown(event: React.KeyboardEvent<HTMLElement>) {
|
||||
handleKeyPass(event, handleState);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{hasNavSubLevels ? (
|
||||
<StyledButton
|
||||
size="small"
|
||||
onClick={handleState}
|
||||
onKeyDown={event => handleKeyPass(event, handleState)}
|
||||
onKeyDown={handleButtonKeyDown}
|
||||
tabIndex={0} // Ensuring keyboard focus
|
||||
aria-expanded={expanded?.expandAllNestedNavs} // Accessibility
|
||||
aria-label={
|
||||
|
||||
Reference in New Issue
Block a user