Skip to content

Commit

Permalink
implemenying custom hook
Browse files Browse the repository at this point in the history
  • Loading branch information
snmln committed Dec 19, 2024
1 parent c4ebc92 commit b1c9d34
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@ export const createDynamicNavMenuList = (
isOpen?: boolean[],
setIsOpen?: SetState<boolean[]>
): JSX.Element[] => {
const setDropDownState = () => {
if (isOpen !== undefined && setIsOpen !== undefined) {
return setIsOpen(() => isOpen.fill(false));
}
};
return navItems.map((item, index) => {
switch (item.type) {
case NavItemType.DROPDOWN:
Expand All @@ -28,31 +23,23 @@ export const createDynamicNavMenuList = (
isOpen,
setIsOpen,
index,
linkProperties,
setDropDownState
linkProperties
}}
/>
);

case NavItemType.INTERNAL_LINK:
return (
linkProperties && (
<NavItemInternalLink
{...{ item, linkProperties, setDropDownState }}
/>
<NavItemInternalLink {...{ item, linkProperties }} />
)
);

case NavItemType.EXTERNAL_LINK:
return (
<NavItemExternalLink
item={item}
setDropDownState={setDropDownState}
/>
);
return <NavItemExternalLink item={item} />;

case NavItemType.ACTION:
return <NavItemCTA item={item} setDropDownState={setDropDownState} />;
return <NavItemCTA item={item} />;

default:
return <></>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
import React from 'react';
import React, { useCallback } from 'react';
import { USWDSNavDropDownButton } from '../../uswds/header/nav-drop-down-button';
import { USWDSMenu } from '../../uswds/header/menu';
import { DropdownNavLink } from '../types';
import { createDynamicNavMenuList } from './create-dynamic-nav-menu-list';
import { SetState } from '$types/aliases';
import { LinkProperties } from '$types/veda';
import { useClickOutside } from '$utils/use-click-outside';

interface NavDropDownButtonProps {
item: DropdownNavLink;
isOpen: boolean[];
setIsOpen: SetState<boolean[]>;
index: number;
linkProperties: LinkProperties;
setDropDownState: () => void;
}

export const NavDropDownButton = ({
item,
isOpen,
setIsOpen,
index,
linkProperties,
setDropDownState
linkProperties
}: NavDropDownButtonProps) => {
const onToggle = (index: number, setIsOpen: SetState<boolean[]>): void => {
setIsOpen((prevIsOpen) => {
Expand All @@ -34,11 +33,20 @@ export const NavDropDownButton = ({
return newIsOpen;
});
};

const handleClickOutside = useCallback(() => {
if (isOpen[index]) {
setIsOpen((prevIsOpen) => {
const newIsOpen = [...prevIsOpen];
newIsOpen[index] = false;
return newIsOpen;
});
}
}, [index, isOpen, setIsOpen]);
const dropdownRef = useClickOutside(handleClickOutside);
const submenuItems = createDynamicNavMenuList(item.children, linkProperties);

return (
<React.Fragment key={item.id}>
<div key={item.id} ref={dropdownRef}>
<USWDSNavDropDownButton
onToggle={() => onToggle(index, setIsOpen)}
menuId={item.title}
Expand All @@ -49,8 +57,7 @@ export const NavDropDownButton = ({
items={submenuItems}
isOpen={isOpen[index]}
id={`${item.id}-dropdown`}
onClick={setDropDownState()}
/>
</React.Fragment>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@ import { ActionNavItem } from '../types';

interface NavItemCTAProps {
item: ActionNavItem;
setDropDownState: () => void;
}

export const NavItemCTA: React.FC<NavItemCTAProps> = ({
item,
setDropDownState
item
}): JSX.Element => {
const { isRevealed, show, hide } = useFeedbackModal();
return (
Expand All @@ -22,9 +20,7 @@ export const NavItemCTA: React.FC<NavItemCTAProps> = ({
type='button'
tabIndex={0}
id={item.id}
onClick={() => {
setDropDownState(), show;
}}
onClick={show}
style={{ background: 'none', border: 'none', cursor: 'pointer' }}
>
{item.title}
Expand Down
10 changes: 2 additions & 8 deletions app/scripts/components/common/page-header/nav/nav-item-links.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,15 @@ import { LinkProperties } from '$types/veda';

interface NavItemExternalLinkProps {
item: ExternalNavLink;
setDropDownState: () => void;
}

interface NavItemInternalLinkProps {
item: InternalNavLink;
linkProperties: LinkProperties;
setDropDownState: () => void;
}

export const NavItemExternalLink: React.FC<NavItemExternalLinkProps> = ({
item,
setDropDownState
item
}): JSX.Element => {
return (
<a
Expand All @@ -25,7 +22,6 @@ export const NavItemExternalLink: React.FC<NavItemExternalLinkProps> = ({
href={item.href}
className='usa-nav__link'
id={item.id}
onClick={() => setDropDownState()}
>
<span>{item.title}</span>
</a>
Expand All @@ -34,8 +30,7 @@ export const NavItemExternalLink: React.FC<NavItemExternalLinkProps> = ({

export const NavItemInternalLink: React.FC<NavItemInternalLinkProps> = ({
item,
linkProperties,
setDropDownState
linkProperties
}): JSX.Element | null => {
if (linkProperties.LinkElement) {
const path = {
Expand All @@ -48,7 +43,6 @@ export const NavItemInternalLink: React.FC<NavItemInternalLinkProps> = ({
{...path}
className='usa-nav__link'
id={item.id}
onClick={() => setDropDownState()}
>
<span>{item.title}</span>
</LinkElement>
Expand Down
15 changes: 15 additions & 0 deletions app/scripts/utils/use-click-outside.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useEffect, useRef } from 'react';
export const useClickOutside = (onClose: () => void) => {
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (ref.current && !ref.current.contains(event.target as Node)) {
onClose();
}
};
document.addEventListener('click', handleClickOutside, true);
return () =>
document.removeEventListener('click', handleClickOutside, true);
}, [onClose]);
return ref;
};

0 comments on commit b1c9d34

Please sign in to comment.