diff --git a/package.json b/package.json index eba33f3d5b1..b4c4b28ef55 100644 --- a/package.json +++ b/package.json @@ -84,6 +84,7 @@ "remark-gfm": "^3.0.1", "swiper": "^11.1.10", "tailwind-merge": "^2.3.0", + "tailwind-variants": "^0.2.1", "tailwindcss-animate": "^1.0.7", "usehooks-ts": "^3.1.0", "yaml-loader": "^0.8.0" diff --git a/src/components/Nav/Desktop/index.tsx b/src/components/Nav/Desktop/index.tsx index 92214ca540c..7e8e313bf54 100644 --- a/src/components/Nav/Desktop/index.tsx +++ b/src/components/Nav/Desktop/index.tsx @@ -3,14 +3,16 @@ import { useRouter } from "next/router" import { useTranslation } from "next-i18next" import { BsTranslate } from "react-icons/bs" import { MdBrightness2, MdWbSunny } from "react-icons/md" -import { HStack, useColorModeValue, useEventListener } from "@chakra-ui/react" -import { IconButton } from "@/components/Buttons" import LanguagePicker from "@/components/LanguagePicker" import { Button } from "@/components/ui/buttons/Button" +import { HStack } from "@/components/ui/flex" import { DESKTOP_LANGUAGE_BUTTON_NAME } from "@/lib/constants" +import useColorModeValue from "@/hooks/useColorModeValue" +import { useEventListener } from "@/hooks/useEventListener" + type DesktopNavMenuProps = { toggleColorMode: () => void } @@ -20,20 +22,12 @@ const DesktopNavMenu = ({ toggleColorMode }: DesktopNavMenuProps) => { const { locale } = useRouter() const languagePickerRef = useRef(null) - const ThemeIcon = useColorModeValue(, ) + const ThemeIcon = useColorModeValue(MdBrightness2, MdWbSunny) const themeIconAriaLabel = useColorModeValue( "Switch to Dark Theme", "Switch to Light Theme" ) - const desktopHoverFocusStyles = { - "& > svg": { - transform: "rotate(10deg)", - color: "primary.hover", - transition: "transform 0.5s, color 0.2s", - }, - } - /** * Adds a keydown event listener to toggle color mode (ctrl|cmd + \) * or open the language picker (\). @@ -52,22 +46,16 @@ const DesktopNavMenu = ({ toggleColorMode }: DesktopNavMenuProps) => { }) return ( - - + {/* Locale-picker menu */} diff --git a/src/components/Nav/Menu/MenuContent.tsx b/src/components/Nav/Menu/MenuContent.tsx index 2c075949c23..fb84a89501d 100644 --- a/src/components/Nav/Menu/MenuContent.tsx +++ b/src/components/Nav/Menu/MenuContent.tsx @@ -1,12 +1,47 @@ import { motion } from "framer-motion" -import { Box } from "@chakra-ui/react" +import { tv } from "tailwind-variants" import { Content } from "@radix-ui/react-navigation-menu" +import { cn } from "@/lib/utils/cn" + import { NavItem, NavSections } from "../types" import SubMenu from "./SubMenu" import { useNavMenu } from "./useNavMenu" +export const navMenuVariants = tv({ + slots: { + base: "text-body", + item: "has-[button[data-state=open]]:rounded-s-md has-[button[data-state=open]]:rounded-e-none has-[button[data-state=open]]:-me-2 has-[button[data-state=open]]:pe-2", + link: "w-full relative py-4 hover:text-menu-active [&:hover_p]:text-menu-active focus-visible:text-menu-active [&:focus-visible_p]:text-menu-active hover:outline-0 rounded-md hover:shadow-none focus-visible:outline-0 focus-visible:rounded-md focus-visible:shadow-none", + submenu: "grid h-full w-full grid-cols-1", + }, + variants: { + level: { + 1: { + submenu: "grid-cols-3 bg-menu-1-background", + item: "has-[button[data-state=open]]:bg-menu-1-active-background", + link: "data-[active=true]:bg-menu-1-active-background hover:bg-menu-1-active-background focus-visible:bg-menu-1-active-background", + }, + 2: { + submenu: "grid-cols-2 bg-menu-2-background", + item: "has-[button[data-state=open]]:bg-menu-2-active-background", + link: "hover:bg-menu-2-active-background focus-visible:bg-menu-2-active-background data-[active=true]:bg-menu-2-active-background", + }, + 3: { + submenu: "grid-cols-1 bg-menu-3-background", + item: "has-[button[data-state=open]]:bg-menu-3-active-background", + link: "data-[active=true]:bg-menu-3-active-background hover:bg-menu-3-active-background", + }, + 4: { + submenu: "grid-cols-1 bg-menu-4-background", + item: "has-[button[data-state=open]]:bg-menu-4-active-background", + link: "data-[active=true]:bg-menu-4-active-background hover:bg-menu-4-active-background", + }, + }, + }, +}) + type MenuContentProps = { items: NavItem[] isOpen: boolean @@ -15,23 +50,19 @@ type MenuContentProps = { // Desktop Menu content const MenuContent = ({ items, isOpen, sections }: MenuContentProps) => { - const { activeSection, containerVariants, menuColors, onClose } = - useNavMenu(sections) + const { activeSection, containerVariants, onClose } = useNavMenu(sections) + const { base } = navMenuVariants() return ( - { activeSection={activeSection} onClose={onClose} /> - + ) } diff --git a/src/components/Nav/Menu/SubMenu.tsx b/src/components/Nav/Menu/SubMenu.tsx index 621772c304b..886b5f8f09b 100644 --- a/src/components/Nav/Menu/SubMenu.tsx +++ b/src/components/Nav/Menu/SubMenu.tsx @@ -1,13 +1,5 @@ import { AnimatePresence, motion } from "framer-motion" import NextLink from "next/link" -import { - Box, - Button, - Grid, - Icon, - ListItem, - UnorderedList, -} from "@chakra-ui/react" import { Content, Item, @@ -18,16 +10,19 @@ import { Viewport, } from "@radix-ui/react-navigation-menu" -import { ButtonProps } from "@/components/Buttons" import { ChevronNext } from "@/components/Chevron" -import Link from "@/components/Link" +import { Button } from "@/components/ui/buttons/Button" +import { BaseLink } from "@/components/ui/Link" +import { ListItem, UnorderedList } from "@/components/ui/list" +import { cn } from "@/lib/utils/cn" import { trackCustomEvent } from "@/lib/utils/matomo" import { cleanPath } from "@/lib/utils/url" import type { Level, NavItem, NavSectionKey } from "../types" import ItemContent from "./ItemContent" +import { navMenuVariants } from "./MenuContent" import { useSubMenu } from "./useSubMenu" type LvlContentProps = { @@ -47,77 +42,41 @@ type LvlContentProps = { * @returns The JSX element representing the menu content. */ const SubMenu = ({ lvl, items, activeSection, onClose }: LvlContentProps) => { - const { asPath, locale, menuColors, menuVariants, PADDING } = useSubMenu() + const { asPath, locale, menuVariants } = useSubMenu() + const { submenu, item: itemClasses, link } = navMenuVariants({ level: lvl }) if (lvl > 3) return null - const templateColumns = `repeat(${4 - lvl}, 1fr)` - return ( - - + {items.map((item) => { - const { label, icon, ...action } = item + const { label, icon: Icon, ...action } = item const subItems = action.items || [] const isLink = "href" in action const isActivePage = isLink && cleanPath(asPath) === action.href - const activeStyles = { - outline: "none", - rounded: "md", - "p, svg": { color: menuColors.highlight }, - bg: menuColors.lvl[lvl].activeBackground, - boxShadow: "none", - } - const buttonProps: ButtonProps = { - color: menuColors.body, - leftIcon: lvl === 1 && icon ? : undefined, - rightIcon: isLink ? undefined : , - position: "relative", - w: "full", - me: -PADDING, - sx: { - "span:first-of-type": { m: 0, me: 4 }, // Spacing for icon - }, - py: PADDING, - bg: isActivePage - ? menuColors.lvl[lvl].activeBackground - : "none", - _hover: activeStyles, - _focus: activeStyles, - variant: "ghost", - } + + const buttonClasses = cn("no-underline text-body", link()) + return ( - + {isLink ? ( ) : ( <> - - +
- +
)} @@ -161,7 +128,7 @@ const SubMenu = ({ lvl, items, activeSection, onClose }: LvlContentProps) => {
-
+
) diff --git a/src/components/Nav/Menu/index.tsx b/src/components/Nav/Menu/index.tsx index 71c8a954dfb..8322a4a7784 100644 --- a/src/components/Nav/Menu/index.tsx +++ b/src/components/Nav/Menu/index.tsx @@ -18,6 +18,8 @@ import type { NavSections } from "../types" import { useNavMenu } from "./useNavMenu" +const MenuContent = dynamic(() => import("./MenuContent")) + type NavMenuProps = BaseHTMLAttributes & { sections: NavSections } @@ -26,8 +28,6 @@ const Menu = ({ sections, ...props }: NavMenuProps) => { const { activeSection, direction, handleSectionChange, isOpen } = useNavMenu(sections) - const MenuContent = dynamic(() => import("./MenuContent")) - return (
{ const { direction } = useRtlFlip() - const menuColors = useNavMenuColors() const [activeSection, setActiveSection] = useState(null) // Focus corresponding nav section when number keys pressed @@ -72,7 +70,6 @@ export const useNavMenu = (sections: NavSections) => { direction, handleSectionChange, isOpen, - menuColors, onClose, } } diff --git a/src/components/Nav/Menu/useSubMenu.ts b/src/components/Nav/Menu/useSubMenu.ts index 7d99f4ae67e..b44b39e7999 100644 --- a/src/components/Nav/Menu/useSubMenu.ts +++ b/src/components/Nav/Menu/useSubMenu.ts @@ -1,14 +1,10 @@ import type { MotionProps } from "framer-motion" import { useRouter } from "next/router" -import { useNavMenuColors } from "@/hooks/useNavMenuColors" import { useRtlFlip } from "@/hooks/useRtlFlip" -const PADDING = 4 // Chakra-UI space token - export const useSubMenu = () => { const { asPath, locale } = useRouter() - const menuColors = useNavMenuColors() const { isRtl } = useRtlFlip() const menuVariants: MotionProps["variants"] = { @@ -19,8 +15,6 @@ export const useSubMenu = () => { return { asPath, locale, - menuColors, menuVariants, - PADDING, } } diff --git a/src/components/Nav/Mobile/HamburgerButton.tsx b/src/components/Nav/Mobile/HamburgerButton.tsx index 3722c1c4617..1bb8c2c484d 100644 --- a/src/components/Nav/Mobile/HamburgerButton.tsx +++ b/src/components/Nav/Mobile/HamburgerButton.tsx @@ -37,7 +37,7 @@ const HamburgerButton = forwardRef( > import("./Mobile")) @@ -23,79 +22,66 @@ const MobileNavMenu = lazy(() => import("./Mobile")) const Nav = () => { const { toggleColorMode, linkSections } = useNav() const { t } = useTranslation("common") - const searchModalDisclosure = useDisclosure() const navWrapperRef = useRef(null) const isClient = useIsClient() const isDesktopFlag = isDesktop() return ( - - +
- + {/* Desktop */} - +
{/* avoid rendering desktop Menu version on mobile */} - {isClient && isDesktopFlag ? ( ) : ( - +
)} - - {/* Desktop */} - {/* avoid rendering desktop menu version on mobile */} - - - - + + {({ onOpen }) => ( +
+ {/* Desktop */} +
+ + + +
- - {/* Mobile */} - {/* use Suspense to display the Search & the Menu at the same time */} - - - - - - - - - - +
+ {/* Mobile */} + {/* use Suspense to display the Search & the Menu at the same time */} + + + + +
+
+ )} +
+
+
+ +
) } diff --git a/src/components/Nav/types.ts b/src/components/Nav/types.ts index fb78ad871b9..91c4859ec59 100644 --- a/src/components/Nav/types.ts +++ b/src/components/Nav/types.ts @@ -1,4 +1,4 @@ -import type { RefObject } from "react" +import type { FC, RefObject, SVGProps } from "react" import type { IconType } from "react-icons" import type { IconProps } from "@chakra-ui/react" @@ -9,7 +9,10 @@ type LinkXorItems = LinkOnly | ItemsOnly export type NavItem = { label: string description: string - icon?: IconType | ((props: IconProps) => JSX.Element) + icon?: + | IconType + | FC> + | ((props: IconProps) => JSX.Element) } & LinkXorItems export type NavSectionKey = diff --git a/src/components/Nav/useNav.ts b/src/components/Nav/useNav.ts index 0b3a2c20716..a996a3ac7c4 100644 --- a/src/components/Nav/useNav.ts +++ b/src/components/Nav/useNav.ts @@ -21,7 +21,7 @@ import { import { PiFlask, PiUsersFourLight } from "react-icons/pi" import { useColorMode } from "@chakra-ui/react" -import { EthereumIcon } from "@/components/icons/EthereumIcon" +import EthereumIcon from "@/components/icons/ethereum-icon.svg" import { trackCustomEvent } from "@/lib/utils/matomo" diff --git a/src/components/Search/SearchButton.tsx b/src/components/Search/SearchButton.tsx index 19ae404f87c..7bfde7b74b8 100644 --- a/src/components/Search/SearchButton.tsx +++ b/src/components/Search/SearchButton.tsx @@ -1,27 +1,28 @@ -import * as React from "react" +import { forwardRef } from "react" import { useTranslation } from "next-i18next" -import { DocSearchButton } from "@docsearch/react" +import { MdSearch } from "react-icons/md" + +import { cn } from "@/lib/utils/cn" import { Button, type ButtonProps } from "../ui/buttons/Button" -const SearchButton = React.forwardRef( - (props, ref) => { +const SearchButton = forwardRef( + ({ className, ...props }, ref) => { const { t } = useTranslation("common") return ( ) } diff --git a/src/components/Search/SearchInputButton.tsx b/src/components/Search/SearchInputButton.tsx new file mode 100644 index 00000000000..8959f776510 --- /dev/null +++ b/src/components/Search/SearchInputButton.tsx @@ -0,0 +1,38 @@ +import * as React from "react" +import { useTranslation } from "next-i18next" +import { DocSearchButton } from "@docsearch/react" + +import { cn } from "@/lib/utils/cn" + +import { Button, type ButtonProps } from "../ui/buttons/Button" + +const SearchButton = React.forwardRef( + ({ className, ...props }, ref) => { + const { t } = useTranslation("common") + + return ( + + ) + } +) + +SearchButton.displayName = "SearchButton" + +export default SearchButton diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 1ff7b8e88b3..b1fefabda5c 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -1,154 +1,124 @@ -import { forwardRef, useRef } from "react" +import { useRef } from "react" import dynamic from "next/dynamic" import { useRouter } from "next/router" import { useTranslation } from "next-i18next" -import { MdSearch } from "react-icons/md" import { useDocSearchKeyboardEvents } from "@docsearch/react" import { DocSearchHit } from "@docsearch/react/dist/esm/types" -import { useComposedRefs } from "@radix-ui/react-compose-refs" import * as Portal from "@radix-ui/react-portal" import { trackCustomEvent } from "@/lib/utils/matomo" import { sanitizeHitTitle } from "@/lib/utils/sanitizeHitTitle" import { sanitizeHitUrl } from "@/lib/utils/url" -import { Button } from "../ui/buttons/Button" - -import SearchButton from "./SearchButton" - -import { type useDisclosure } from "@/hooks/useDisclosure" +import { useDisclosure } from "@/hooks/useDisclosure" const SearchModal = dynamic(() => import("./SearchModal")) -type Props = ReturnType +type Props = { + children: (props: ReturnType) => React.ReactNode +} + +const Search = ({ children }: Props) => { + const disclosure = useDisclosure() + const { isOpen, onOpen, onClose } = disclosure -const Search = forwardRef( - ({ isOpen, onOpen, onClose }, ref) => { - const { locale } = useRouter() - const searchButtonRef = useRef(null) - const mergedButtonRefs = useComposedRefs(ref, searchButtonRef) - const { t } = useTranslation("common") + const { locale } = useRouter() + const searchButtonRef = useRef(null) + const { t } = useTranslation("common") - useDocSearchKeyboardEvents({ - isOpen, - onOpen, - onClose, - searchButtonRef, + const handleOpen = () => { + onOpen() + trackCustomEvent({ + eventCategory: "nav bar", + eventAction: "click", + eventName: "search open", }) + } - const appId = process.env.NEXT_PUBLIC_ALGOLIA_APP_ID || "" - const apiKey = process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY || "" - const indexName = - process.env.NEXT_PUBLIC_ALGOLIA_BASE_SEARCH_INDEX_NAME || "ethereumorg" + useDocSearchKeyboardEvents({ + isOpen, + onOpen: handleOpen, + onClose, + searchButtonRef, + }) - return ( - <> -
- { - onOpen() - trackCustomEvent({ - eventCategory: "nav bar", - eventAction: "click", - eventName: "search open", - }) + const appId = process.env.NEXT_PUBLIC_ALGOLIA_APP_ID || "" + const apiKey = process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY || "" + const indexName = + process.env.NEXT_PUBLIC_ALGOLIA_BASE_SEARCH_INDEX_NAME || "ethereumorg" + + return ( + <> + {children({ ...disclosure, onOpen: handleOpen })} + + {isOpen && ( + -
-
- -
- - {isOpen && ( - - items.map((item: DocSearchHit) => { - const newItem: DocSearchHit = structuredClone(item) - newItem.url = sanitizeHitUrl(item.url) - const newTitle = sanitizeHitTitle(item.hierarchy.lvl0 || "") - newItem.hierarchy.lvl0 = newTitle - return newItem - }) - } - placeholder={t("search-ethereum-org")} - translations={{ - searchBox: { - resetButtonTitle: t("clear"), - resetButtonAriaLabel: t("clear"), - cancelButtonText: t("close"), - cancelButtonAriaLabel: t("close"), - }, - footer: { - selectText: t("docsearch-to-select"), - selectKeyAriaLabel: t("docsearch-to-select"), - navigateText: t("docsearch-to-navigate"), - navigateUpKeyAriaLabel: t("up"), - navigateDownKeyAriaLabel: t("down"), - closeText: t("docsearch-to-close"), - closeKeyAriaLabel: t("docsearch-to-close"), - searchByText: t("docsearch-search-by"), - }, - errorScreen: { - titleText: t("docsearch-error-title"), - helpText: t("docsearch-error-help"), - }, - startScreen: { - recentSearchesTitle: t( - "docsearch-start-recent-searches-title" - ), - noRecentSearchesText: t("docsearch-start-no-recent-searches"), - saveRecentSearchButtonTitle: t( - "docsearch-start-save-recent-search" - ), - removeRecentSearchButtonTitle: t( - "docsearch-start-remove-recent-search" - ), - favoriteSearchesTitle: t("docsearch-start-favorite-searches"), - removeFavoriteSearchButtonTitle: t( - "docsearch-start-remove-favorite-search" - ), - }, - noResultsScreen: { - noResultsText: t("docsearch-no-results-text"), - suggestedQueryText: t("docsearch-no-results-suggested-query"), - reportMissingResultsText: t("docsearch-no-results-missing"), - reportMissingResultsLinkText: t( - "docsearch-no-results-missing-link" - ), - }, - }} - /> - )} - - - ) - } -) - -Search.displayName = "Search" + /> + )} + + + ) +} export default Search diff --git a/src/components/icons/EthHomeIcon.tsx b/src/components/icons/EthHomeIcon.tsx deleted file mode 100644 index 7fb0c596791..00000000000 --- a/src/components/icons/EthHomeIcon.tsx +++ /dev/null @@ -1,50 +0,0 @@ -/* eslint-disable react/jsx-key */ -import * as React from "react" -import { createIcon } from "@chakra-ui/react" - -export const EthHomeIcon = createIcon({ - displayName: "EthHomeIcon", - viewBox: "0 0 115 182", - defaultProps: { - width: "22px", - height: "35px", - }, - path: [ - , - , - , - , - , - , - ], -}) diff --git a/src/components/icons/EthereumIcon.tsx b/src/components/icons/EthereumIcon.tsx deleted file mode 100644 index af51f4545df..00000000000 --- a/src/components/icons/EthereumIcon.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { Icon, type IconProps } from "@chakra-ui/react" - -export const EthereumIcon = (props: IconProps) => ( - - - -) diff --git a/src/components/icons/Icons.stories.tsx b/src/components/icons/Icons.stories.tsx index 0600fa1e190..ba5c65f9da8 100644 --- a/src/components/icons/Icons.stories.tsx +++ b/src/components/icons/Icons.stories.tsx @@ -2,7 +2,7 @@ import * as React from "react" import { Center, Flex, Icon, SimpleGrid } from "@chakra-ui/react" import type { Meta, StoryObj } from "@storybook/react" -import { EthHomeIcon } from "./EthHomeIcon" +import EthHomeIcon from "./eth-home-icon.svg" import FeedbackThumbsUpIcon from "./feedback-thumbs-up-icon.svg" import { HighlightDarkIcon } from "./HighlightDarkIcon" import { HighlightIcon } from "./HighlightIcon" diff --git a/src/components/icons/eth-home-icon.svg b/src/components/icons/eth-home-icon.svg new file mode 100644 index 00000000000..0a120cffe0c --- /dev/null +++ b/src/components/icons/eth-home-icon.svg @@ -0,0 +1,43 @@ + + + + + + + + \ No newline at end of file diff --git a/src/components/icons/ethereum-icon.svg b/src/components/icons/ethereum-icon.svg new file mode 100644 index 00000000000..d639f9f2f9c --- /dev/null +++ b/src/components/icons/ethereum-icon.svg @@ -0,0 +1,13 @@ + + + \ No newline at end of file diff --git a/src/components/icons/feedback-glyph-icon.svg b/src/components/icons/feedback-glyph-icon.svg index 410ec68f28b..a208df2f8c6 100644 --- a/src/components/icons/feedback-glyph-icon.svg +++ b/src/components/icons/feedback-glyph-icon.svg @@ -1,5 +1,11 @@ - - - + + + \ No newline at end of file diff --git a/src/components/icons/index.ts b/src/components/icons/index.ts index 52ea0779fa3..65b0e0a6f6b 100644 --- a/src/components/icons/index.ts +++ b/src/components/icons/index.ts @@ -1,5 +1,5 @@ // General Icons -import { EthHomeIcon } from "./EthHomeIcon" +import EthHomeIcon from "./eth-home-icon.svg" import FeedbackGlyphIcon from "./feedback-glyph-icon.svg" import FeedbackThumbsUpIcon from "./feedback-thumbs-up-icon.svg" import { HighlightDarkIcon } from "./HighlightDarkIcon" diff --git a/src/styles/semantic-tokens.css b/src/styles/semantic-tokens.css index e8400ac7236..f454ac0e2c2 100644 --- a/src/styles/semantic-tokens.css +++ b/src/styles/semantic-tokens.css @@ -76,6 +76,24 @@ --shadow-window-box-3: 0px 32px 24px -6px hsla(var(--purple-800), var(--shadow-window-box-3-opacity)); --shadow-window-box-4: 0px 40px 40px -12px hsla(var(--purple-700), var(--shadow-window-box-4-opacity)); --shadow-window-box-5: 0px -64px 120px 80px hsla(var(--purple-100), var(--shadow-window-box-5-opacity)); + + /* Menu colors */ + --menu: var(--body); + --menu-hover: var(--gray-200); + --menu-active: var(--primary); + --menu-active-background: var(--primary-high-contrast); + --menu-1-subtext: var(--gray-400); + --menu-1-background: var(--white); + --menu-1-active-background: var(--gray-150); + --menu-2-subtext: var(--gray-400); + --menu-2-background: var(--gray-150); + --menu-2-active-background: var(--gray-200); + --menu-3-subtext: var(--gray-500); + --menu-3-background: var(--gray-200); + --menu-3-active-background: var(--gray-100); + --menu-4-subtext: var(--gray-700); + --menu-4-background: var(--gray-300); + --menu-4-active-background: var(--gray-200); } /* Dark mode token declarations */ @@ -127,5 +145,23 @@ --shadow-window-box-3-opacity: 0.16; --shadow-window-box-4-opacity: 0.06; --shadow-window-box-5-opacity: 0.06; + + /* Menu colors */ + --menu: var(--body); + --menu-hover: var(--gray-200); + --menu-active: var(--primary); + --menu-active-background: var(--primary-high-contrast); + --menu-1-subtext: var(--gray-400); + --menu-1-background: var(--black); + --menu-1-active-background: var(--gray-700); + --menu-2-subtext: var(--gray-300); + --menu-2-background: var(--gray-700); + --menu-2-active-background: var(--gray-600); + --menu-3-subtext: var(--gray-300); + --menu-3-background: var(--gray-600); + --menu-3-active-background: var(--gray-700); + --menu-4-subtext: var(--gray-300); + --menu-4-background: var(--gray-700); + --menu-4-active-background: var(--gray-800); } } diff --git a/tailwind.config.ts b/tailwind.config.ts index 9ad06a6a1ca..6b3a47c987e 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -171,6 +171,32 @@ const config = { outline: "hsla(var(--success-outline))", neutral: "hsla(var(--success-neutral))", }, + menu: { + DEFAULT: "hsla(var(--menu))", + hover: "hsla(var(--menu-hover))", + active: "hsla(var(--menu-active))", + "active-background": "hsla(var(--menu-active-background))", + 1: { + subtext: "hsla(var(--menu-1-subtext))", + background: "hsla(var(--menu-1-background))", + "active-background": "hsla(var(--menu-1-active-background))", + }, + 2: { + subtext: "hsla(var(--menu-2-subtext))", + background: "hsla(var(--menu-2-background))", + "active-background": "hsla(var(--menu-2-active-background))", + }, + 3: { + subtext: "hsla(var(--menu-3-subtext))", + background: "hsla(var(--menu-3-background))", + "active-background": "hsla(var(--menu-3-active-background))", + }, + 4: { + subtext: "hsla(var(--menu-4-subtext))", + background: "hsla(var(--menu-4-background))", + "active-background": "hsla(var(--menu-4-active-background))", + }, + }, }, backgroundImage: { "gradient-main": "var(--gradient-main)", diff --git a/yarn.lock b/yarn.lock index 3b7c075e1a8..9e79c0da5d7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13088,6 +13088,7 @@ prelude-ls@^1.2.1: integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== "prettier-fallback@npm:prettier@^3", prettier@^3.1.1: + name prettier-fallback version "3.3.2" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.2.tgz#03ff86dc7c835f2d2559ee76876a3914cec4a90a" integrity sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA== @@ -14726,11 +14727,23 @@ swiper@^11.1.10: resolved "https://registry.yarnpkg.com/swiper/-/swiper-11.1.10.tgz#4d3df50ff8afc4960e9644ed6e5828d35ab38853" integrity sha512-pAVM6vCb6bumj2B9aSh67l3wP1j5YR8dPQM1YhQKMpnBc33vs+RpyVz6NZYZl/ZopCBSYbbWK5nvESwbmU0QXQ== +tailwind-merge@^2.2.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-2.5.2.tgz#000f05a703058f9f9f3829c644235f81d4c08a1f" + integrity sha512-kjEBm+pvD+6eAwzJL2Bi+02/9LFLal1Gs61+QB7HvTfQQ0aXwC5LGT8PEt1gS0CWKktKe6ysPTAy3cBC5MeiIg== + tailwind-merge@^2.3.0: version "2.4.0" resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-2.4.0.tgz#1345209dc1f484f15159c9180610130587703042" integrity sha512-49AwoOQNKdqKPd9CViyH5wJoSKsCDjUlzL8DxuGp3P1FsGY36NJDAa18jLZcaHAUUuTj+JB8IAo8zWgBNvBF7A== +tailwind-variants@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tailwind-variants/-/tailwind-variants-0.2.1.tgz#132f2537b0150819036f6c4f47d5c50b929b758d" + integrity sha512-2xmhAf4UIc3PijOUcJPA1LP4AbxhpcHuHM2C26xM0k81r0maAO6uoUSHl3APmvHZcY5cZCY/bYuJdfFa4eGoaw== + dependencies: + tailwind-merge "^2.2.0" + tailwindcss-animate@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz#318b692c4c42676cc9e67b19b78775742388bef4"