diff --git a/.gitignore b/.gitignore index 7ab1f8dd..6b45aa06 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,4 @@ tsconfig.tsbuildinfo # Storybook build files storybook-static/ +!/.junie/guidelines.md diff --git a/app/layout.tsx b/app/layout.tsx index 21f75e65..3ab06b31 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,5 +1,6 @@ import '../source/00-config/index.css'; +import DropdownMenu from '@/source/03-components/Menu/DropdownMenu/DropdownMenu'; import { JSX, PropsWithChildren } from 'react'; import sourceSansPro from '../source/01-global/fonts/source-sans'; import '../source/01-global/index.css'; @@ -8,7 +9,6 @@ import Header from '../source/02-layouts/Header/Header'; import SiteContainer from '../source/02-layouts/SiteContainer/SiteContainer'; import BackToTop from '../source/03-components/BackToTop/BackToTop'; import Menu from '../source/03-components/Menu/Menu'; -import ResponsiveMenu from '../source/03-components/Menu/ResponsiveMenu/ResponsiveMenu'; import footerStyles from '../source/03-components/Menu/menu-footer.module.css'; import SiteName from '../source/03-components/SiteName/SiteName'; import Skiplink from '../source/03-components/Skiplink/Skiplink'; @@ -22,13 +22,15 @@ function RootLayout({ children }: PropsWithChildren): JSX.Element {
- diff --git a/public/images/mobile-arrow-up.svg b/public/images/mobile-arrow-up.svg new file mode 100644 index 00000000..eadd6d97 --- /dev/null +++ b/public/images/mobile-arrow-up.svg @@ -0,0 +1 @@ + diff --git a/source/00-config/vars/colors.css b/source/00-config/vars/colors.css index 53f13c8b..28df5b8c 100644 --- a/source/00-config/vars/colors.css +++ b/source/00-config/vars/colors.css @@ -39,11 +39,14 @@ --ui-accent-light: var(--brand-blue-light); --ui-background: var(--grayscale-gray-3); --ui-background-dark: var(--grayscale-gray-6); + --ui-background-darker: var(--grayscale-gray-7); --ui-background-light: var(--grayscale-gray-1); --ui-border: var(--grayscale-gray-3); --ui-border-dark: var(--grayscale-gray-6); --ui-border-light: var(--grayscale-gray-1); --ui-focus: var(--brand-blue-light); --ui-text-dark: var(--grayscale-gray-5); + --ui-text-darker: var(--grayscale-gray-7); --ui-text-light: var(--grayscale-gray-3); + --ui-text-lighter: var(--grayscale-gray-1); } diff --git a/source/03-components/Menu/DropdownMenu/DropdownContext.tsx b/source/03-components/Menu/DropdownMenu/DropdownContext.tsx new file mode 100644 index 00000000..179243dd --- /dev/null +++ b/source/03-components/Menu/DropdownMenu/DropdownContext.tsx @@ -0,0 +1,6 @@ +import { Context, createContext } from 'react'; + +const DropdownContext: Context> = + createContext({}); + +export default DropdownContext; diff --git a/source/03-components/Menu/DropdownMenu/DropdownItem.tsx b/source/03-components/Menu/DropdownMenu/DropdownItem.tsx new file mode 100644 index 00000000..9530c2c2 --- /dev/null +++ b/source/03-components/Menu/DropdownMenu/DropdownItem.tsx @@ -0,0 +1,354 @@ +import DropdownContext from '@/source/03-components/Menu/DropdownMenu/DropdownContext'; +import { MenuItem } from '@/source/03-components/Menu/Menu'; +import clsx from 'clsx'; +import { GessoComponent } from 'gesso'; +import { + FocusEventHandler, + JSX, + KeyboardEventHandler, + PropsWithChildren, + MouseEvent as ReactMouseEvent, + useContext, +} from 'react'; +import styles from './dropdown-menu.module.css'; + +interface DropdownItemProps extends GessoComponent { + item: MenuItem; + isChild?: boolean; + isExpanded: boolean; + useArrowKeys?: boolean; + onItemClick: (itemId: string | number, event: ReactMouseEvent) => void; + onKeyDown?: KeyboardEventHandler; + onBlur: FocusEventHandler; +} + +interface DropdownItemWrapperProps + extends Pick { + hasChildren?: boolean; + isInActiveTrail?: boolean; +} + +function DropdownItemWrapper({ + modifierClasses, + hasChildren, + isExpanded, + isInActiveTrail, + children, +}: PropsWithChildren): JSX.Element { + return ( +
  • + {children} +
  • + ); +} + +type DropdownLinkProps = Pick< + DropdownItemProps, + 'useArrowKeys' | 'onKeyDown' | 'onBlur' +> & + Pick; + +interface DropdownMenubarLinkProps + extends DropdownItemWrapperProps, + DropdownLinkProps {} + +function DropdownMenubarLink({ + modifierClasses, + useArrowKeys, + onKeyDown, + onBlur, + url, + id, + title, + isExpanded, +}: DropdownMenubarLinkProps): JSX.Element { + return ( + + + {title} + + + ); +} + +type DropdownMenubarButtonProps = DropdownItemWrapperProps & + Pick & + Pick< + DropdownItemProps, + 'useArrowKeys' | 'onKeyDown' | 'onBlur' | 'onItemClick' + >; + +function DropdownMenuBarButton({ + modifierClasses, + isExpanded, + id, + useArrowKeys, + onKeyDown, + onBlur, + title, + isInActiveTrail, + onItemClick, + below, +}: DropdownMenubarButtonProps): JSX.Element { + const expandedItems = useContext(DropdownContext); + + return ( + + + {isExpanded && below?.length && ( +
      + {below.map(child => ( + // eslint-disable-next-line @typescript-eslint/no-use-before-define + + ))} +
    + )} +
    + ); +} + +type PopupMenuLinkProps = DropdownLinkProps & DropdownItemWrapperProps; + +function PopupMenuLink({ + url, + hasChildren, + id, + useArrowKeys, + onKeyDown, + onBlur, + title, +}: PopupMenuLinkProps): JSX.Element { + return ( + + {title} + + ); +} + +type PopupMenuWithSubmenuProps = DropdownItemWrapperProps & + PopupMenuLinkProps & + DropdownMenubarButtonProps; + +function PopupMenuWithSubmenu({ + id, + modifierClasses, + isExpanded, + url, + onBlur, + onKeyDown, + useArrowKeys, + title, + onItemClick, + below, + isInActiveTrail, +}: PopupMenuWithSubmenuProps): JSX.Element { + const expandedItems = useContext(DropdownContext); + + return ( + + +
    {children}