diff --git a/src/components/menu/index.css b/src/components/menu/index.css index 24e2575bd..1b0c18b0f 100644 --- a/src/components/menu/index.css +++ b/src/components/menu/index.css @@ -1,320 +1,427 @@ -.menu, -.navigation, -.overflow-menu .MuiPaper-root ul { - background-color: var(--color-gunmetal-dark); -} - -.navigation { - align-items: center; - box-shadow: 0px 5px 10px 0px rgb( from var(--color-black) r g b / 0.2); - color: var(--color-gold-two); - display: flex; - font-size: 40px; - gap: 10px; -} - -.navigation a, -.navigation button, -.overflow-menu a { - border-radius: 0; - border: 0; - color: var(--color-gold-two); - text-align: left; - /* text-decoration: none; */ - white-space: nowrap; - padding: 2px 5px; -} - -.logo-padding { - margin-top: 5px; - margin-bottom: 5px; -} - -.menu { - align-items: center; - display: flex; - font-size: 34px; - gap: 10px; - justify-content: center; - line-height: 1; - margin: 10px 0; - padding: 0; - text-decoration: none; - text-transform: uppercase; - width: 100%; -} - -.menu.open { - box-shadow: 0px 5px 10px 0px rgb( from var(--color-black) r g b / 0.2); - display: block; - padding: 20px 20px 20px 20px; - position: absolute; - top: 72px; - z-index: 10; -} - -.menu ul { - list-style-type: none; -} - -.menu a, -.menu li, -.menu span { - display: block; - text-align: left; - margin: auto 0; -} - -.mobile-icon { - font-size: 0; - margin-right: 0; - margin-left: 20; -} - -.mobile-icon svg { - fill: var(--color-gold-two); - height: 54px; -} - -.App.connected .menu { - display: none; -} - -.branding { - border-radius: 0; - font-size: 0; - margin-bottom: 10px; - margin-left: 10px; - margin-right: auto; - margin-top: 10px; - - /* font-size: 40px; */ -} - -.menu button { - font-size: 20px; -} - -.menu .submenu-wrapper { - border-radius: 0; - font-size: 20px; - position: relative; -} - -.menu .submenu-wrapper ul { - background-color: var(--color-gunmetal-dark); - border-bottom-left-radius: 3px; - border-bottom-right-radius: 3px; - display: none; - left: 0; - list-style: none; - padding: 10px; - position: absolute; - z-index: 2000; - box-shadow: 0px 5px 10px 0px rgb( from var(--color-black) r g b / 0.2); - top: 24px; -} - -.submenu-wrapper li { - align-items: center; - display: flex; -} - -.submenu-wrapper input { - cursor: pointer; -} - -.menu .submenu-wrapper ul a { - border-radius: 0; -} - -.menu a:hover, -.menu button:hover, -.menu .submenu-wrapper:hover { - cursor: pointer; -} - -.menu .submenu-wrapper:hover > a { - color: var(--color-black); - color: var(--color-gold-one); - text-decoration: underline; - text-underline-offset: 5px; - text-decoration-thickness: 1px; -} - -.menu .submenu-wrapper:hover ul { - display: block; -} - -.menu li:hover button { - cursor: pointer; -} - -.external-link { - border-radius: 0; -} - -.menu .last-link { - position: relative; -} - -.menu svg { - width: 20px; - height: 20px; -} - -.menu .last-link:hover .supporters-wrapper { - display: block; -} - -.supporters-wrapper { - background-color: var(--color-black); - border-radius: 0; - color: var(--color-white); - cursor: default; - display: none; - position: absolute; - right: 0; - top: 28px; - z-index: 1; -} - -li.desktop-only-link { - display: none; - position: relative; - bottom: 2px; -} - -.menu li.only-large { - display: none; -} - -li.mobile-only-link { - display: block; -} - -@media screen and (min-width: 1280px) { - .branding { - /*margin-right: 0;*/ - } - - .mobile-icon, - .mobile-only-link { - display: none; - } - - li.desktop-only-link { - display: block; - } - - li.mobile-only-link { - display: none; - } - - .menu { - display: flex; - font-size: 20px; - /*margin: 0;*/ - /* width: auto; */ - } - - .more-dropdown-wrapper > ul { - left: -5.25rem !important; - } - - .menu > li { - border-width: 0 1px 0 0; - } -} - -@media screen and (min-width: 1920px) { - .menu li.only-large { - display: flex; - } -} - -/* new styles */ -.submenu-wrapper a { - margin: auto 0; -} - -.submenu-items { - border-left: 1px solid var(--color-gold-two); - border-right: 1px solid rgb( from var(--color-black) r g b / 0); -} - -.overflow-menu .MuiPaper-root { - background-color: var(--color-gunmetal-dark); -} - -.overflow-menu ul.MuiList-root { - padding-left: 10px; -} - -.overflow-menu li { - font-size: 20px; - text-decoration: none; - text-transform: uppercase; -} - -.overflow-menu li ul { - display: block; - list-style-type: none; - padding-left: 10px; -} - -.navigation, -ul.menu { - max-width: 100%; -} - -.visible-menu-item, .visible-overflow { - order: 0; - visibility: visible; - opacity: 1; -} - -.invisible-menu-item, .invisible-overflow { - order: 100; - visibility: hidden; - pointer-events: none; -} - -.toolbar-wrapper { - display: flex; - overflow-x: clip; - overflow-y: visible; - padding: 0 10px; - max-width: 100%; -} - -.overflow-item { - order: 99; - position: sticky; - right: 0; -} - -.overflow-show { - overflow: visible; -} - -.in-overflow-menu:hover { - background-color: transparent; -} - -/* margin unless it is the only item showing */ -nav.navigation ul.menu li.more-dropdown-wrapper:not(:nth-child(1 of li.visible-menu-all)) { - margin-left: -50px; -} - -nav.navigation ul.menu li:nth-last-child(1 of li.visible-menu-item):not(:nth-last-child(1 of li.overflow-member)) { - padding-right: 50px; -} - -.MuiPopover-root svg.icon-with-text { - color: var(--color-gold-two); -} - -.MuiPopover-root .overflow-hidden { - display: none; -} +.menu, +.navigation, +.overflow-menu .MuiPaper-root ul { + background-color: var(--color-gunmetal-dark); +} + +.navigation { + align-items: center; + border-bottom: 1px solid rgb( from var(--color-white) r g b / .2); + margin-bottom: 20px; + padding: 0 20px; + background-color: rgb( from var(--color-black) r g b / .2); + color: var(--color-gold-two); + display: flex; + font-size: 40px; +} + +.navigation a, +.navigation button, +.overflow-menu a { + border-radius: 0; + border: 0; + color: var(--color-gold-two); + text-align: left; + /* text-decoration: none; */ + white-space: nowrap; + padding: 2px 5px; +} + +.logo-padding { + margin-top: 5px; + margin-bottom: 5px; +} + +.menu { + align-items: center; + display: flex; + font-size: 34px; + line-height: 1; + margin: auto 20px auto auto; + padding: 0; + text-decoration: none; + text-transform: uppercase; + background: transparent; + width: 100%; +} + +.menu.open { + box-shadow: 0px 5px 10px 0px rgb( from var(--color-black) r g b / 0.2); + display: block; + padding: 20px 20px 20px 20px; + position: absolute; + top: 72px; + z-index: 10; +} + +.menu ul { + list-style-type: none; +} + +.menu a, +.menu li, +.menu span { + display: block; + text-align: left; + margin: auto 0; +} + +.menu li { + display: flex; + height: 60px; + align-items: center; + transition: all .3s; +} +.menu li.submenu-wrapper ul li { + height: inherit; + padding: 6px 0; +} +.menu li a, +.menu span { + padding: 0 10px; +} +.menu li.submenu-wrapper:hover { + background: var(--color-gunmetal-dark); +} + +.menu .overflow-hidden a, +.menu .overflow-hidden li, +.menu .overflow-hidden span { + height: inherit; +} + +.mobile-icon { + font-size: 0; + margin-right: 0; + margin-left: 20; +} + +.mobile-icon svg { + fill: var(--color-gold-two); + height: 54px; +} + +.App.connected .menu { + display: none; +} + +a.branding { + border-radius: 0; + font-size: 0; + padding: 10px 18px 10px 5px; + margin: 0; + border-right: 1px solid rgb( from var(--color-gold-one) r g b / .1); +} + +.menu button { + font-size: 20px; +} + +.menu .submenu-wrapper { + border-radius: 0; + font-size: 20px; + position: relative; +} + +.menu .submenu-wrapper ul { + background-color: var(--color-gunmetal-dark); + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + display: none; + left: 0; + list-style: none; + position: absolute; + padding: 0; + z-index: 2000; + box-shadow: 0px 5px 10px 0px rgb( from var(--color-black) r g b / 0.2); + border-left: 1px solid rgb( from var(--color-gold-one) r g b / .2); + border-right: 1px solid rgb( from var(--color-gold-one) r g b / .2); + border-bottom: 1px solid rgb( from var(--color-gold-one) r g b / .2); + min-width: 160px; + top: 60px; +} + .submenu-wrapper ul li { + align-items: center; + display: flex; + border-bottom: 1px solid rgb( from var(--color-gold-one) r g b / .1); + } + .submenu-wrapper ul li a { + padding: 0 10px; + margin: 0; + } + + .submenu-wrapper ul li input { + cursor: pointer; + margin-left: 10px; + } + + .menu .submenu-wrapper ul a { + border-radius: 0; + } + + +.menu a:hover, +.menu button:hover, +.menu .submenu-wrapper:hover { + cursor: pointer; +} + +.menu .submenu-wrapper:hover > a { + color: var(--color-black); + color: var(--color-gold-one); + text-decoration: underline; + text-underline-offset: 5px; + text-decoration-thickness: 1px; +} + +.menu .submenu-wrapper:hover ul { + display: block; +} + +.menu li:hover button { + cursor: pointer; +} + +.external-link { + border-radius: 0; +} + +.menu .last-link { + position: relative; +} + +.menu svg { + width: 20px; + height: 20px; +} + +.menu .last-link:hover .supporters-wrapper { + display: block; +} + +.right-items { + display: inline-flex; + align-items: center; + margin: 0 0 0 20px; +} +.right-items a { + display: inline-flex; + align-items: center; +} + +.supporters-wrapper { + background-color: var(--color-black); + border-radius: 0; + color: var(--color-white); + cursor: default; + display: none; + position: absolute; + right: 0; + top: 28px; + z-index: 1; +} + +li.desktop-only-link { + display: none; + position: relative; + bottom: 2px; +} + +.menu li.only-large { + display: none; +} + +li.mobile-only-link { + display: block; +} + + + + + + + + + + +/* new styles */ +.submenu-wrapper a { + margin: auto 0; +} + +.overflow-menu .MuiPaper-root { + background-color: var(--color-gunmetal-dark); +} + +.overflow-menu ul.MuiList-root { + padding-left: 10px; +} + +.overflow-menu li { + font-size: 20px; + text-decoration: none; + text-transform: uppercase; +} + +.overflow-menu li ul { + display: block; + list-style-type: none; + padding-left: 10px; +} + +.navigation, +ul.menu { + max-width: 100%; +} + +.visible-menu-item, .visible-overflow { + order: 0; + visibility: visible; + opacity: 1; +} + +.invisible-menu-item, .invisible-overflow { + order: 100; + visibility: hidden; + pointer-events: none; +} + +.toolbar-wrapper { + display: flex; + overflow-x: clip; + overflow-y: visible; + padding: 0 10px; + max-width: 100%; +} + +.overflow-item { + order: 99; + position: sticky; + right: 0; +} + +.overflow-show { + overflow: visible; +} + +.in-overflow-menu:hover { + background-color: transparent; +} + +/* margin unless it is the only item showing */ +nav.navigation ul.menu li.more-dropdown-wrapper:not(:nth-child(1 of li.visible-menu-all)) { + margin-left: -50px; +} + +nav.navigation ul.menu li:nth-last-child(1 of li.visible-menu-item):not(:nth-last-child(1 of li.overflow-member)) { + padding-right: 50px; +} + +.MuiPopover-root svg.icon-with-text { + color: var(--color-gold-two); +} + +.MuiPopover-root .overflow-hidden { + display: none; +} + + +.mobileMenu-toggle { + display: none; + font-size: 18px; + margin: 0 10px 0 auto; + padding: 6px 12px; + border-radius: 4px; + text-transform: uppercase; + border: 1px solid var(--color-gold-one); + color: var(--color-gold-one); +} +.mobileMenu-toggle.active { + color: var(--color-white); + background: var(--color-gold-two); +} + +@media screen and (max-width: 1280px){ + .navigation { + padding: 0 10px; + } + .menu li a { + font-size: 18px; + } + .navigation .right-items { + margin: 0; + } +} + +@media screen and (max-width: 1200px){ + .mobileMenu-toggle { + display: inline-flex; + } + + .navigation { + position: relative; + } + + .navigation .menu { + display: none; + position: absolute; + z-index: 999; + width: 100%; + top: 60px; + padding: 30px 20px; + left: 0; + height: calc(100vh - 60px); + flex-direction: column; + background: var(--color-gunmetal-dark); + } + + .navigation ul.menu li { + height: auto; + width: 100%; + margin: 0 0 20px 0; + align-items: center; + justify-content: center; + } + .navigation ul.menu li ul { + display: none !important; + pointer-events: none !important; + } + .navigation ul.menu li a { + display: block; + width: 100%; + font-size: 20px; + text-align: center; + } + + .navigation .menu.mobile-menu-open { + display: flex; + justify-content: flex-start; + align-items: center; + } + + .navigation .menu .additional .icon, + .navigation .menu .tools .title { + display: none; + } + + .navigation .menu .additional ul, + .navigation .menu .tools ul { + display: block !important; + pointer-events: all !important; + width: 100%; + position: static; + border: none; + background: none; + box-shadow: none; + } + .navigation .menu .additional ul li, + .navigation .menu .tools ul li { + border-bottom: none; + padding: 0; + } + + .navigation .menu .tools ul li:last-of-type { + margin-bottom: 0; + } + +} \ No newline at end of file diff --git a/src/components/menu/index.js b/src/components/menu/index.js index 87bd8d5ab..e4652a361 100644 --- a/src/components/menu/index.js +++ b/src/components/menu/index.js @@ -1,326 +1,323 @@ -import { useMemo, useState } from 'react'; -import useStateWithLocalStorage from '../../hooks/useStateWithLocalStorage.jsx'; -import { Link } from 'react-router-dom'; -import { useTranslation } from 'react-i18next'; -import { Icon } from '@mdi/react'; -import { - mdiCogOutline, - mdiRemote, - mdiClose, -} from '@mdi/js'; - -import { Box, Alert, IconButton, Collapse } from '@mui/material'; - -import MenuItem from './MenuItem.jsx'; -// import SubMenu from './SubMenu'; - -import { caliberArrayWithSplit } from '../../modules/format-ammo.mjs'; -import categoryPages from '../../data/category-pages.json'; -import useBossesData from '../../features/bosses/index.js'; - -import { mapIcons, useMapImagesSortedArray } from '../../features/maps/index.js'; - -import alertConfig from './alert-config.js'; - -import IntersectionObserverWrapper from './intersection-observer-wrapper.js'; - -import './index.css'; -import useTradersData from '../../features/traders/index.js'; - -// automatically selects the alert color -const alertColor = alertConfig.alertColors[alertConfig.alertLevel]; - -const ammoTypes = caliberArrayWithSplit(); - -const getAmmoMenu = (setIsOpen) => { - const ammoMenu = ammoTypes.map((ammoType) => ( - - )); - return ammoMenu; -}; - -const Menu = () => { - /*const [isOpen, setIsOpen] = useState(false); - const handleMenuClick = () => { - setIsOpen(!isOpen); - };*/ - const { t } = useTranslation(); - const [alertOpen, setAlertOpen] = useStateWithLocalStorage(alertConfig.bannerKey, true); - const [alertStateOpen, setAlertStateOpen] = useState(alertOpen || alertConfig.alwaysShow); - - const uniqueMaps = useMapImagesSortedArray(); - for (const map of uniqueMaps) { - if (mapIcons[map.normalizedName]) { - map.icon = mapIcons[map.normalizedName]; - } - else { - map.menuPadding = true; - } - } - - const { data: bosses } = useBossesData(); - const { data: allTraders } = useTradersData(); - - const traders = useMemo(() => { - return allTraders.filter(t => t.barters?.length > 0) - }, [allTraders]); - - return ( - <> - {/* ALERT BANNER SECTION */} - {alertConfig?.alertEnabled === true && ( - - - { - setAlertOpen(false); - setAlertStateOpen(false); - }} - > - - - } - > - {t(alertConfig.text, alertConfig.textVariables)} - - {alertConfig.linkEnabled === true && ( - <> - {' - '} - - {t(alertConfig.linkText)} - - - )} - - - - )} - {/* END ALERT BANNER SECTION */} - - - ); -}; - -export default Menu; +import { useMemo, useState } from 'react'; +import useStateWithLocalStorage from '../../hooks/useStateWithLocalStorage.jsx'; +import { Link } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; +import { Icon } from '@mdi/react'; +import { + mdiDotsVertical, + mdiCogOutline, + mdiRemote, + mdiClose, +} from '@mdi/js'; + +import { Box, Alert, IconButton, Collapse } from '@mui/material'; + +import MenuItem from './MenuItem.jsx'; +// import SubMenu from './SubMenu'; + +import { caliberArrayWithSplit } from '../../modules/format-ammo.mjs'; +import categoryPages from '../../data/category-pages.json'; +import useBossesData from '../../features/bosses/index.js'; + +import { mapIcons, useMapImagesSortedArray } from '../../features/maps/index.js'; + +import alertConfig from './alert-config.js'; + + +import './index.css'; +import useTradersData from '../../features/traders/index.js'; + +// automatically selects the alert color +const alertColor = alertConfig.alertColors[alertConfig.alertLevel]; + +const ammoTypes = caliberArrayWithSplit(); + +const getAmmoMenu = (setIsOpen) => { + const ammoMenu = ammoTypes.map((ammoType) => ( + + )); + return ammoMenu; +}; + +const Menu = () => { + /*const [isOpen, setIsOpen] = useState(false); + const handleMenuClick = () => { + setIsOpen(!isOpen); + };*/ + const { t } = useTranslation(); + const [alertOpen, setAlertOpen] = useStateWithLocalStorage(alertConfig.bannerKey, true); + const [alertStateOpen, setAlertStateOpen] = useState(alertOpen || alertConfig.alwaysShow); + const [mobileMenuOpen, setMobileMenuOpen] = useState(false); // State for mobile menu + + + const uniqueMaps = useMapImagesSortedArray(); + for (const map of uniqueMaps) { + if (mapIcons[map.normalizedName]) { + map.icon = mapIcons[map.normalizedName]; + } + else { + map.menuPadding = true; + } + } + + const { data: bosses } = useBossesData(); + const { data: allTraders } = useTradersData(); + + const traders = useMemo(() => { + return allTraders.filter(t => t.barters?.length > 0) + }, [allTraders]); + + // Toggle handler for mobile menu + const mobileMenuToggle = () => { + setMobileMenuOpen(!mobileMenuOpen); + }; + + return ( + <> + {/* ALERT BANNER SECTION */} + {alertConfig?.alertEnabled === true && ( + + + { + setAlertOpen(false); + setAlertStateOpen(false); + }} + > + + + } + > + {t(alertConfig.text, alertConfig.textVariables)} + + {alertConfig.linkEnabled === true && ( + <> + {' - '} + + {t(alertConfig.linkText)} + + + )} + + + + )} + {/* END ALERT BANNER SECTION */} + + + ); +}; + +export default Menu; diff --git a/src/components/menu/intersection-observer-wrapper.js b/src/components/menu/intersection-observer-wrapper.js deleted file mode 100644 index 2de0278b8..000000000 --- a/src/components/menu/intersection-observer-wrapper.js +++ /dev/null @@ -1,62 +0,0 @@ -import React, { useRef, useEffect, useState } from 'react'; -import classnames from 'classnames'; - -import OverflowMenu from './overflow-menu.js'; - -export default function IntersectionObserverWrapper({ children }) { - const navRef = useRef(null); - const [visibilityMap, setVisibilityMap] = useState({}); - const handleIntersection = (entries) => { - const updatedEntries = {}; - entries.forEach((entry) => { - const targetid = entry.target.dataset.targetid; - if (entry.isIntersecting) { - updatedEntries[targetid] = true; - } else { - updatedEntries[targetid] = false; - } - }); - - setVisibilityMap((prev) => ({ - ...prev, - ...updatedEntries, - })); - }; - useEffect(() => { - const observer = new IntersectionObserver(handleIntersection, { - root: navRef.current, - threshold: 1, - }); - // We are addting observers to child elements of the container div - // with ref as navRef. Notice that we are adding observers - // only if we have the data attribute targetid on the child element - Array.from(navRef.current.children).forEach((item) => { - if (item.dataset.targetid) { - observer.observe(item); - } - }); - return () => { - observer.disconnect(); - }; - }, []); - return ( -
- {React.Children.map(children, (child) => { - return React.cloneElement(child, { - className: classnames(child.props.className, { - 'visible-menu-item visible-menu-all': - !!visibilityMap[child.props['data-targetid']], - 'invisible-menu-item': !visibilityMap[child.props['data-targetid']], - //[classes.showOverflow]: visible && showOverflow - }), - }); - })} - - {children} - -
- ); -}