diff --git a/src/components/elements/lockup/lockup.tsx b/src/components/elements/lockup/lockup.tsx index 3723b767..1a2a32e9 100644 --- a/src/components/elements/lockup/lockup.tsx +++ b/src/components/elements/lockup/lockup.tsx @@ -43,19 +43,17 @@ export const Lockup = ({ if (!suLockupEnabled) { return ( -
- -
-
- -
-
- {suSiteName || "University"} -
+ +
+
+
- -
+
+ {suSiteName || "University"} +
+
+ ) } @@ -99,12 +97,10 @@ export const Lockup = ({ case "none": default: return ( -
- - - -
+ + + ) } } diff --git a/src/components/global/page-header.tsx b/src/components/global/page-header.tsx index 41699317..490625af 100644 --- a/src/components/global/page-header.tsx +++ b/src/components/global/page-header.tsx @@ -1,4 +1,3 @@ -import SiteSearchForm from "@components/search/site-search-form"; import MainMenu from "@components/menu/main-menu"; import GlobalMessage from "@components/config-pages/global-message"; import Lockup from "@components/elements/lockup/lockup"; @@ -10,6 +9,7 @@ import { StanfordGlobalMessage } from "@lib/gql/__generated__/drupal.d"; import {isPreviewMode} from "@lib/drupal/utils"; +import Button from "@components/elements/button"; const PageHeader = async () => { const menuItems = await getMenu(MenuAvailable.Main, isPreviewMode()); @@ -30,15 +30,19 @@ const PageHeader = async () => {
{globalMessageConfig && } -
-
-
- - +
+
+
+
+ +
+ {siteSettingsConfig && siteSettingsConfig.sumSiteHeaderPrim && } + {siteSettingsConfig && siteSettingsConfig.sumSiteHeaderSec && } +
+
- - +
) diff --git a/src/components/menu/main-menu.tsx b/src/components/menu/main-menu.tsx index 62a8cdc8..019c51d2 100644 --- a/src/components/menu/main-menu.tsx +++ b/src/components/menu/main-menu.tsx @@ -4,12 +4,20 @@ import Link from "@components/elements/link"; import SiteSearchForm from "@components/search/site-search-form"; import useActiveTrail from "@lib/hooks/useActiveTrail"; import useOutsideClick from "@lib/hooks/useOutsideClick"; -import {ChevronDownIcon} from "@heroicons/react/20/solid"; -import {MenuItem as MenuItemType} from "@lib/gql/__generated__/drupal.d"; -import {clsx} from "clsx"; -import {useBoolean, useEventListener} from "usehooks-ts"; -import {useCallback, useEffect, useId, useLayoutEffect, useRef, useState} from "react"; -import {usePathname} from "next/navigation"; +import { ArrowRightIcon, ChevronDownIcon, MagnifyingGlassIcon } from "@heroicons/react/20/solid"; +import { MenuItem as MenuItemType, StanfordBasicSiteSetting } from "@lib/gql/__generated__/drupal.d"; +import { clsx } from "clsx"; +import { useBoolean, useEventListener } from "usehooks-ts"; +import { + useCallback, + useEffect, + useId, + useLayoutEffect, + useRef, + useState, +} from "react"; +import { usePathname } from "next/navigation"; +import Button from "@components/elements/button"; const menuLevelsToShow = 2; @@ -17,68 +25,132 @@ type Props = { /** * Array of nested menu items. */ - menuItems: MenuItemType[] -} + menuItems: MenuItemType[]; + sumSiteHeaderPrim?: StanfordBasicSiteSetting["sumSiteHeaderPrim"]; + sumSiteHeaderSec?: StanfordBasicSiteSetting["sumSiteHeaderSec"]; +}; -const MainMenu = ({menuItems}: Props) => { - const buttonRef = useRef(null) +const MainMenu = ({ menuItems, sumSiteHeaderPrim, sumSiteHeaderSec}: Props) => { + const buttonRef = useRef(null); const menuRef = useRef(null); const navId = useId(); - const {value: menuOpen, setFalse: closeMenu, toggle: toggleMenu} = useBoolean(false) - const browserUrl = usePathname() + const { value: menuOpen, setFalse: closeMenu, toggle: toggleMenu } = useBoolean(false); + const browserUrl = usePathname(); const activeTrail = useActiveTrail(menuItems, usePathname() || ""); useOutsideClick(menuRef, closeMenu); - const handleEscape = useCallback((event: KeyboardEvent) => { - if (event.key !== "Escape" || !menuOpen) return; + const handleEscape = useCallback( + (event: KeyboardEvent) => { + if (event.key !== "Escape" || !menuOpen) return; - closeMenu() - buttonRef.current?.focus(); - }, [menuOpen, closeMenu]); + closeMenu(); + buttonRef.current?.focus(); + }, + [menuOpen, closeMenu] + ); useEffect(() => closeMenu(), [browserUrl, closeMenu]); useEventListener("keydown", handleEscape, menuRef); return ( - - ) -} + ); +}; type MenuItemProps = MenuItemType & { - activeTrail: string[] - level: number -} + activeTrail: string[]; + level: number; +}; -const MenuItem = ({id, url, title, activeTrail, children, level}: MenuItemProps) => { +const MenuItem = ({ + id, + url, + title, + activeTrail, + children, + level, +}: MenuItemProps) => { const linkId = useId(); const menuItemRef = useRef(null); const belowListRef = useRef(null); - const [positionRight, setPositionRight] = useState(true) - const buttonRef = useRef(null) - const {value: submenuOpen, setFalse: closeSubmenu, toggle: toggleSubmenu} = useBoolean(false) - const browserUrl = usePathname() + const [positionRight, setPositionRight] = useState(true); + const buttonRef = useRef(null); + const { + value: submenuOpen, + setFalse: closeSubmenu, + toggle: toggleSubmenu, + } = useBoolean(false); + const browserUrl = usePathname(); useOutsideClick(menuItemRef, closeSubmenu); @@ -87,19 +159,25 @@ const MenuItem = ({id, url, title, activeTrail, children, level}: MenuItemProps) useLayoutEffect(() => { // If the right side of the submenu is not visible, set the position to be on the left of the menu item. - const {x, width} = belowListRef.current?.getBoundingClientRect() || {x: 0, width: 0} + const { x, width } = belowListRef.current?.getBoundingClientRect() || { + x: 0, + width: 0, + }; if (x + width > window.innerWidth) setPositionRight(false); - }, [submenuOpen]) + }, [submenuOpen]); // If the user presses escape on the keyboard, close the submenus. - const handleEscape = useCallback((event: KeyboardEvent) => { - if (event.key !== "Escape" || !submenuOpen) return; + const handleEscape = useCallback( + (event: KeyboardEvent) => { + if (event.key !== "Escape" || !submenuOpen) return; - closeSubmenu() - if (level === 0) buttonRef.current?.focus(); - }, [level, submenuOpen, closeSubmenu]); + closeSubmenu(); + if (level === 0) buttonRef.current?.focus(); + }, + [level, submenuOpen, closeSubmenu] + ); - useEventListener("keydown", handleEscape, menuItemRef) + useEventListener("keydown", handleEscape, menuItemRef); // List out the specific classes so tailwind will include them. Dynamic classes values don"t get compiled. const zIndexes = ["z-[1]", "z-[2]", "z-[3]", "z-[4]", "z-[5]"] @@ -110,42 +188,59 @@ const MenuItem = ({id, url, title, activeTrail, children, level}: MenuItemProps) const inTrail = activeTrail.includes(id) && !isCurrent; const linkStyles = clsx( - "w-full relative inline-block text-white lg:text-digital-red hocus:text-white lg:hocus:text-black no-underline hocus:underline py-5 lg:pl-0 border-l-[6px]", + "group w-full relative inline-block font-normal text-black hocus:text-black no-underline py-5 border-b-[4px] hocus:border-spirited-light", leftPadding[level], // Top menu item styles. { - "lg:border-l-0 lg:border-b-[6px] ml-5 lg:ml-0 lg:pb-2": level === 0, - "border-digital-red lg:border-black": level === 0 && isCurrent, - "border-transparent lg:border-foggy-dark": level === 0 && !isCurrent && inTrail, + "lg:border-l-0 lg:border-b-[4px] lg:mr-0 lg:pb-10": level === 0, + "border-spirited-light": level === 0 && isCurrent, + "border-transparent lg:border-spirited-light": + level === 0 && !isCurrent && inTrail, "border-transparent": level === 0 && !isCurrent && !inTrail, + "lg:pr-10" : level === 0 && children.length === 0, }, // Child menu item styles. { "ml-5 lg:ml-0 lg:pl-5": level !== 0, - "border-digital-red": level !== 0 && isCurrent, - "border-transparent": level !== 0 && !isCurrent + "border-spirited-light": level !== 0 && isCurrent, + "border-transparent": level !== 0 && !isCurrent, } - ) + ); + + const chevronBtnStyles = clsx( + "shrink-0 relative pr-10 lg:right-0 text-black bg-transparent lg:bg-transparent lg:pr-5 lg:pb-6 lg:pl-2 hocus:border-b-[4px] lg:group-hover:border-b-[4px] hocus:border-spirited-light lg:group-hover:border-spirited-light", + // Top menu item styles. + { + "border-b-[4px]": level === 0, + "border-spirited-light": level === 0 && isCurrent, + "border-transparent lg:border-spirited-light": + level === 0 && !isCurrent && inTrail, + "border-transparent": level === 0 && !isCurrent && !inTrail, + }, + ); const subMenuStyles = clsx( - "list-unstyled w-full min-w-[300px] lg:bg-white lg:shadow-2xl px-0 lg:absolute", + "list-unstyled w-full min-w-[350px] lg:bg-fog-light lg:border lg:border-white lg:shadow-2xl lg:absolute lg:rounded-[25px] lg:px-12 lg:py-4 lg:mt-3", zIndexes[level], { "lg:top-full lg:right-0": level === 0, "lg:top-0": level !== 0, "lg:left-full": level !== 0 && positionRight, "lg:right-full": level !== 0 && !positionRight, - "block": submenuOpen, - "hidden": !submenuOpen, + block: submenuOpen, + hidden: !submenuOpen, } - ) + ); return (
  • -
    +
    {title} + {level !== 0 && } - {(children.length > 0 && level < menuLevelsToShow) && - <> - {level === 0 &&
    } - - - + {children.length > 0 && level < menuLevelsToShow && + } -
    - {(children.length > 0 && level < menuLevelsToShow) && + {children.length > 0 && level < menuLevelsToShow &&
      - {children.map(item => + {children.map((item) => } - ) -} + ); +}; -export default MainMenu; \ No newline at end of file +export default MainMenu;