Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
| import React, { useState } from "react"; | |
| import { | |
| AppBar, | |
| Toolbar, | |
| Box, | |
| Link as MuiLink, | |
| IconButton, | |
| Tooltip, | |
| ButtonBase, | |
| Typography, | |
| } from "@mui/material"; | |
| import { useLocation, useNavigate, useSearchParams } from "react-router-dom"; | |
| import OpenInNewIcon from "@mui/icons-material/OpenInNew"; | |
| import LightModeOutlinedIcon from "@mui/icons-material/LightModeOutlined"; | |
| import DarkModeOutlinedIcon from "@mui/icons-material/DarkModeOutlined"; | |
| import { alpha } from "@mui/material/styles"; | |
| import MenuIcon from "@mui/icons-material/Menu"; | |
| import { Menu, MenuItem, useMediaQuery, useTheme } from "@mui/material"; | |
| const Navigation = ({ onToggleTheme, mode }) => { | |
| const location = useLocation(); | |
| const navigate = useNavigate(); | |
| const [searchParams] = useSearchParams(); | |
| const [anchorEl, setAnchorEl] = useState(null); | |
| const theme = useTheme(); | |
| const isMobile = useMediaQuery(theme.breakpoints.down("md")); | |
| const [hasChanged, setHasChanged] = useState(false); | |
| const handleThemeToggle = () => { | |
| setHasChanged(true); | |
| onToggleTheme(); | |
| }; | |
| const iconStyle = { | |
| fontSize: "1.125rem", | |
| ...(hasChanged && { | |
| animation: "rotateIn 0.3s cubic-bezier(0.4, 0, 0.2, 1)", | |
| "@keyframes rotateIn": { | |
| "0%": { | |
| opacity: 0, | |
| transform: | |
| mode === "light" | |
| ? "rotate(-90deg) scale(0.8)" | |
| : "rotate(90deg) scale(0.8)", | |
| }, | |
| "100%": { | |
| opacity: 1, | |
| transform: "rotate(0) scale(1)", | |
| }, | |
| }, | |
| }), | |
| }; | |
| // Function to sync URL with parent HF page | |
| const syncUrlWithParent = (queryString, hash) => { | |
| // Check if we're in an HF Space iframe | |
| const isHFSpace = window.location !== window.parent.location; | |
| if (isHFSpace) { | |
| try { | |
| // Build complete URL with hash | |
| const fullPath = `${queryString}${hash ? "#" + hash : ""}`; | |
| window.parent.postMessage( | |
| { | |
| type: "urlUpdate", | |
| path: fullPath, | |
| }, | |
| "https://huggingface.co" | |
| ); | |
| } catch (e) { | |
| console.warn("Unable to sync URL with parent:", e); | |
| } | |
| } | |
| }; | |
| const linkStyle = (isActive = false) => ({ | |
| textDecoration: "none", | |
| color: isActive ? "text.primary" : "text.secondary", | |
| fontSize: "0.8125rem", | |
| opacity: isActive ? 1 : 0.8, | |
| display: "flex", | |
| alignItems: "center", | |
| gap: 0.5, | |
| paddingBottom: "2px", | |
| cursor: "pointer", | |
| position: "relative", | |
| "&:hover": { | |
| opacity: 1, | |
| color: "text.primary", | |
| }, | |
| "&::after": isActive | |
| ? { | |
| content: '""', | |
| position: "absolute", | |
| bottom: "-4px", | |
| left: "0", | |
| width: "100%", | |
| height: "2px", | |
| backgroundColor: (theme) => | |
| alpha( | |
| theme.palette.text.primary, | |
| theme.palette.mode === "dark" ? 0.3 : 0.2 | |
| ), | |
| borderRadius: "2px", | |
| } | |
| : {}, | |
| }); | |
| const Separator = () => ( | |
| <Box | |
| sx={(theme) => ({ | |
| width: "4px", | |
| height: "4px", | |
| borderRadius: "100%", | |
| backgroundColor: alpha( | |
| theme.palette.text.primary, | |
| theme.palette.mode === "dark" ? 0.2 : 0.15 | |
| ), | |
| })} | |
| /> | |
| ); | |
| const handleNavigation = (path) => (e) => { | |
| e.preventDefault(); | |
| const searchString = searchParams.toString(); | |
| const queryString = searchString ? `?${searchString}` : ""; | |
| const newPath = `${path}${queryString}`; | |
| // Local navigation via React Router | |
| navigate(newPath); | |
| // If in HF Space, sync with parent | |
| if (window.location !== window.parent.location) { | |
| syncUrlWithParent(queryString, newPath); | |
| } | |
| }; | |
| const handleMenuOpen = (event) => { | |
| setAnchorEl(event.currentTarget); | |
| }; | |
| const handleMenuClose = () => { | |
| setAnchorEl(null); | |
| }; | |
| return ( | |
| <AppBar | |
| position="static" | |
| sx={{ | |
| backgroundColor: "transparent", | |
| boxShadow: "none", | |
| width: "100%", | |
| }} | |
| > | |
| <Toolbar sx={{ justifyContent: "center" }}> | |
| {isMobile ? ( | |
| <Box | |
| sx={{ | |
| display: "flex", | |
| width: "100%", | |
| justifyContent: "space-between", | |
| alignItems: "center", | |
| }} | |
| > | |
| <IconButton | |
| onClick={handleMenuOpen} | |
| sx={{ color: "text.secondary" }} | |
| > | |
| <MenuIcon /> | |
| </IconButton> | |
| <Menu | |
| anchorEl={anchorEl} | |
| open={Boolean(anchorEl)} | |
| onClose={handleMenuClose} | |
| PaperProps={{ | |
| elevation: 3, | |
| sx: { | |
| mt: 1.5, | |
| minWidth: 220, | |
| borderRadius: "12px", | |
| border: (theme) => | |
| `1px solid ${alpha(theme.palette.divider, 0.1)}`, | |
| backgroundColor: (theme) => | |
| theme.palette.mode === "dark" | |
| ? alpha(theme.palette.background.paper, 0.8) | |
| : theme.palette.background.paper, | |
| backdropFilter: "blur(20px)", | |
| "& .MuiList-root": { | |
| py: 1, | |
| }, | |
| "& .MuiMenuItem-root": { | |
| px: 2, | |
| py: 1, | |
| fontSize: "0.8125rem", | |
| color: "text.secondary", | |
| transition: "all 0.2s ease-in-out", | |
| position: "relative", | |
| "&:hover": { | |
| backgroundColor: (theme) => | |
| alpha( | |
| theme.palette.text.primary, | |
| theme.palette.mode === "dark" ? 0.1 : 0.06 | |
| ), | |
| color: "text.primary", | |
| }, | |
| "&.Mui-selected": { | |
| backgroundColor: "transparent", | |
| color: "text.primary", | |
| "&::after": { | |
| content: '""', | |
| position: "absolute", | |
| left: "8px", | |
| width: "4px", | |
| height: "100%", | |
| top: "0", | |
| backgroundColor: (theme) => | |
| alpha( | |
| theme.palette.text.primary, | |
| theme.palette.mode === "dark" ? 0.3 : 0.2 | |
| ), | |
| borderRadius: "2px", | |
| }, | |
| "&:hover": { | |
| backgroundColor: (theme) => | |
| alpha( | |
| theme.palette.text.primary, | |
| theme.palette.mode === "dark" ? 0.1 : 0.06 | |
| ), | |
| }, | |
| }, | |
| }, | |
| }, | |
| }} | |
| transformOrigin={{ horizontal: "left", vertical: "top" }} | |
| anchorOrigin={{ horizontal: "left", vertical: "bottom" }} | |
| > | |
| {/* Navigation Section */} | |
| <Box sx={{ px: 2, pb: 1.5, pt: 0.5 }}> | |
| <Typography variant="caption" sx={{ color: "text.disabled" }}> | |
| Navigation | |
| </Typography> | |
| </Box> | |
| <MenuItem | |
| onClick={(e) => { | |
| handleNavigation("/")(e); | |
| handleMenuClose(); | |
| }} | |
| selected={location.pathname === "/"} | |
| > | |
| Leaderboard | |
| </MenuItem> | |
| <MenuItem | |
| onClick={(e) => { | |
| handleNavigation("/quote")(e); | |
| handleMenuClose(); | |
| }} | |
| selected={location.pathname === "/quote"} | |
| > | |
| Citations | |
| </MenuItem> | |
| {/* Separator */} | |
| <Box | |
| sx={{ | |
| my: 1, | |
| borderTop: (theme) => | |
| `1px solid ${alpha(theme.palette.divider, 0.1)}`, | |
| }} | |
| /> | |
| {/* External Links Section */} | |
| <Box sx={{ px: 2, pb: 1.5 }}> | |
| <Typography variant="caption" sx={{ color: "text.disabled" }}> | |
| External links | |
| </Typography> | |
| </Box> | |
| <MenuItem | |
| component={MuiLink} | |
| href="https://huggingface.co/spaces/open-llm-leaderboard/comparator" | |
| target="_blank" | |
| sx={{ | |
| "& svg": { | |
| ml: "auto", | |
| fontSize: "0.875rem", | |
| opacity: 0.6, | |
| }, | |
| }} | |
| > | |
| Compare models | |
| <OpenInNewIcon /> | |
| </MenuItem> | |
| <MenuItem | |
| component={MuiLink} | |
| href="https://huggingface.co/docs/leaderboards/open_llm_leaderboard/about" | |
| target="_blank" | |
| sx={{ | |
| "& svg": { | |
| ml: "auto", | |
| fontSize: "0.875rem", | |
| opacity: 0.6, | |
| }, | |
| }} | |
| > | |
| About | |
| <OpenInNewIcon /> | |
| </MenuItem> | |
| </Menu> | |
| <Tooltip | |
| title={ | |
| mode === "light" | |
| ? "Switch to dark mode" | |
| : "Switch to light mode" | |
| } | |
| > | |
| <ButtonBase | |
| onClick={handleThemeToggle} | |
| sx={(theme) => ({ | |
| color: "text.secondary", | |
| borderRadius: "100%", | |
| padding: 0, | |
| width: "36px", | |
| height: "36px", | |
| display: "flex", | |
| alignItems: "center", | |
| justifyContent: "center", | |
| transition: "all 0.2s ease-in-out", | |
| "&:hover": { | |
| color: "text.primary", | |
| backgroundColor: alpha( | |
| theme.palette.text.primary, | |
| theme.palette.mode === "dark" ? 0.1 : 0.06 | |
| ), | |
| }, | |
| "&.MuiButtonBase-root": { | |
| overflow: "hidden", | |
| }, | |
| "& .MuiTouchRipple-root": { | |
| color: alpha(theme.palette.text.primary, 0.3), | |
| }, | |
| })} | |
| > | |
| {mode === "light" ? ( | |
| <DarkModeOutlinedIcon sx={iconStyle} /> | |
| ) : ( | |
| <LightModeOutlinedIcon sx={iconStyle} /> | |
| )} | |
| </ButtonBase> | |
| </Tooltip> | |
| </Box> | |
| ) : ( | |
| // Desktop version | |
| <Box | |
| sx={{ | |
| display: "flex", | |
| gap: 2.5, | |
| alignItems: "center", | |
| padding: "0.5rem 0", | |
| }} | |
| > | |
| {/* Internal navigation */} | |
| <Box sx={{ display: "flex", gap: 2.5, alignItems: "center" }}> | |
| <Box | |
| onClick={handleNavigation("/")} | |
| sx={linkStyle(location.pathname === "/")} | |
| > | |
| Leaderboard | |
| </Box> | |
| <Box | |
| onClick={handleNavigation("/quote")} | |
| sx={linkStyle(location.pathname === "/quote")} | |
| > | |
| Citations | |
| </Box> | |
| </Box> | |
| <Separator /> | |
| {/* External links */} | |
| <Box sx={{ display: "flex", gap: 2.5, alignItems: "center" }}> | |
| <MuiLink | |
| href="https://huggingface.co/spaces/open-llm-leaderboard/comparator" | |
| target="_blank" | |
| rel="noopener noreferrer" | |
| sx={{ | |
| ...linkStyle(), | |
| "& svg": { | |
| fontSize: "0.75rem", | |
| ml: 0.5, | |
| opacity: 0.6, | |
| transition: "opacity 0.2s ease-in-out", | |
| }, | |
| "&:hover svg": { | |
| opacity: 0.8, | |
| }, | |
| }} | |
| > | |
| Compare models | |
| <OpenInNewIcon /> | |
| </MuiLink> | |
| <MuiLink | |
| href="https://huggingface.co/docs/leaderboards/open_llm_leaderboard/about" | |
| target="_blank" | |
| rel="noopener noreferrer" | |
| sx={{ | |
| ...linkStyle(), | |
| "& svg": { | |
| fontSize: "0.75rem", | |
| ml: 0.5, | |
| opacity: 0.6, | |
| transition: "opacity 0.2s ease-in-out", | |
| }, | |
| "&:hover svg": { | |
| opacity: 0.8, | |
| }, | |
| }} | |
| > | |
| About | |
| <OpenInNewIcon /> | |
| </MuiLink> | |
| </Box> | |
| <Separator /> | |
| {/* Dark mode toggle */} | |
| <Tooltip | |
| title={ | |
| mode === "light" | |
| ? "Switch to dark mode" | |
| : "Switch to light mode" | |
| } | |
| > | |
| <ButtonBase | |
| onClick={handleThemeToggle} | |
| sx={(theme) => ({ | |
| color: "text.secondary", | |
| borderRadius: "100%", | |
| padding: 0, | |
| width: "36px", | |
| height: "36px", | |
| display: "flex", | |
| alignItems: "center", | |
| justifyContent: "center", | |
| transition: "all 0.2s ease-in-out", | |
| "&:hover": { | |
| color: "text.primary", | |
| backgroundColor: alpha( | |
| theme.palette.text.primary, | |
| theme.palette.mode === "dark" ? 0.1 : 0.06 | |
| ), | |
| }, | |
| "&.MuiButtonBase-root": { | |
| overflow: "hidden", | |
| }, | |
| "& .MuiTouchRipple-root": { | |
| color: alpha(theme.palette.text.primary, 0.3), | |
| }, | |
| })} | |
| > | |
| {mode === "light" ? ( | |
| <DarkModeOutlinedIcon sx={iconStyle} /> | |
| ) : ( | |
| <LightModeOutlinedIcon sx={iconStyle} /> | |
| )} | |
| </ButtonBase> | |
| </Tooltip> | |
| </Box> | |
| )} | |
| </Toolbar> | |
| </AppBar> | |
| ); | |
| }; | |
| export default Navigation; | |