mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-01 02:12:36 +02:00
fix(v2): navbar dropdown opened with tab, not closing on click outside (#3240)
* package use-onclickoutside added * fix:dropdown toggle updated and tab behavior fixed * fix:variable name and type checker on drop down updated * fix: optional chaining added to dropdown toggle function * fix: package.json problem fixed and type of element updated * fix:type problem fixed
This commit is contained in:
parent
ee4a3ece57
commit
ee6dee72b7
3 changed files with 56 additions and 11 deletions
|
@ -27,6 +27,7 @@
|
|||
"prop-types": "^15.7.2",
|
||||
"react-router-dom": "^5.1.2",
|
||||
"react-toggle": "^4.1.1",
|
||||
"use-onclickoutside": "^0.3.1",
|
||||
"@docusaurus/utils-validation": "^2.0.0-alpha.61"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -5,10 +5,11 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React, {ComponentProps, ComponentType} from 'react';
|
||||
import React, {ComponentProps, ComponentType, useState} from 'react';
|
||||
import clsx from 'clsx';
|
||||
import Link from '@docusaurus/Link';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import useOnClickOutside from 'use-onclickoutside';
|
||||
|
||||
function NavLink({
|
||||
activeBasePath,
|
||||
|
@ -33,6 +34,7 @@ function NavLink({
|
|||
const toUrl = useBaseUrl(to);
|
||||
const activeBaseUrl = useBaseUrl(activeBasePath);
|
||||
const normalizedHref = useBaseUrl(href, {forcePrependBaseUrl: true});
|
||||
|
||||
return (
|
||||
<Link
|
||||
{...(href
|
||||
|
@ -61,6 +63,21 @@ function NavLink({
|
|||
}
|
||||
|
||||
function NavItemDesktop({items, position, className, ...props}) {
|
||||
const dropDownRef = React.useRef<HTMLDivElement>(null);
|
||||
const dropDownMenuRef = React.useRef<HTMLUListElement>(null);
|
||||
const [showDropDown, setShowDropDown] = useState(false);
|
||||
useOnClickOutside(dropDownRef, () => toggle(false));
|
||||
function toggle(state: boolean) {
|
||||
if (state) {
|
||||
const firstNavLinkOfULElement =
|
||||
dropDownMenuRef?.current?.firstChild?.firstChild;
|
||||
|
||||
if (firstNavLinkOfULElement) {
|
||||
(firstNavLinkOfULElement as HTMLElement).focus();
|
||||
}
|
||||
}
|
||||
setShowDropDown(state);
|
||||
}
|
||||
const navLinkClassNames = (extraClassName, isDropdownItem = false) =>
|
||||
clsx(
|
||||
{
|
||||
|
@ -76,32 +93,34 @@ function NavItemDesktop({items, position, className, ...props}) {
|
|||
|
||||
return (
|
||||
<div
|
||||
ref={dropDownRef}
|
||||
className={clsx('navbar__item', 'dropdown', 'dropdown--hoverable', {
|
||||
'dropdown--left': position === 'left',
|
||||
'dropdown--right': position === 'right',
|
||||
'dropdown--show': showDropDown,
|
||||
})}>
|
||||
<NavLink
|
||||
className={navLinkClassNames(className)}
|
||||
{...props}
|
||||
onClick={props.to ? undefined : (e) => e.preventDefault()}
|
||||
onKeyDown={(e) => {
|
||||
function toggle() {
|
||||
((e.target as HTMLElement)
|
||||
.parentNode as HTMLElement).classList.toggle('dropdown--show');
|
||||
}
|
||||
if (e.key === 'Enter' && !props.to) {
|
||||
toggle();
|
||||
}
|
||||
if (e.key === 'Tab') {
|
||||
toggle();
|
||||
if ((e.key === 'Enter' && !props.to) || e.key === 'Tab') {
|
||||
e.preventDefault();
|
||||
toggle(true);
|
||||
}
|
||||
}}>
|
||||
{props.label}
|
||||
</NavLink>
|
||||
<ul className="dropdown__menu">
|
||||
<ul ref={dropDownMenuRef} className="dropdown__menu">
|
||||
{items.map(({className: childItemClassName, ...childItemProps}, i) => (
|
||||
<li key={i}>
|
||||
<NavLink
|
||||
onKeyDown={(e) => {
|
||||
if (i === items.length - 1 && e.key === 'Tab') {
|
||||
e.preventDefault();
|
||||
toggle(false);
|
||||
}
|
||||
}}
|
||||
activeClassName="dropdown__link--active"
|
||||
className={navLinkClassNames(childItemClassName, true)}
|
||||
{...childItemProps}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue