Spaces:
Running
Running
import React, { useState } from "react"; | |
import { | |
AppBar, | |
Toolbar, | |
Box, | |
Link as MuiLink, | |
IconButton, | |
Tooltip, | |
ButtonBase, | |
Typography, | |
Menu, | |
MenuItem, | |
useMediaQuery, | |
useTheme, | |
} from "@mui/material"; | |
import { alpha } from "@mui/material/styles"; | |
import OpenInNewIcon from "@mui/icons-material/OpenInNew"; | |
import LightModeOutlinedIcon from "@mui/icons-material/LightModeOutlined"; | |
import DarkModeOutlinedIcon from "@mui/icons-material/DarkModeOutlined"; | |
import MenuIcon from "@mui/icons-material/Menu"; | |
import { Link, useLocation } from "react-router-dom"; | |
const Navigation = ({ onToggleTheme, mode }) => { | |
const [anchorEl, setAnchorEl] = useState(null); | |
const theme = useTheme(); | |
const isMobile = useMediaQuery(theme.breakpoints.down("md")); | |
const [hasChanged, setHasChanged] = useState(false); | |
const location = useLocation(); | |
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)", | |
}, | |
}, | |
}), | |
}; | |
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 handleMenuClose = () => { | |
setAnchorEl(null); | |
}; | |
const handleMenuOpen = (event) => { | |
setAnchorEl(event.currentTarget); | |
}; | |
return ( | |
<AppBar | |
position="static" | |
elevation={0} | |
sx={{ | |
backgroundColor: "transparent", | |
}} | |
> | |
<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)", | |
}, | |
}} | |
> | |
<MenuItem | |
component={Link} | |
to="/" | |
onClick={handleMenuClose} | |
selected={location.pathname === "/"} | |
sx={linkStyle(location.pathname === "/")} | |
> | |
Explorer | |
</MenuItem> | |
<MenuItem | |
component={Link} | |
to="/submit" | |
onClick={handleMenuClose} | |
selected={location.pathname === "/submit"} | |
sx={linkStyle(location.pathname === "/submit")} | |
> | |
How to submit? | |
</MenuItem> | |
<MenuItem | |
component={MuiLink} | |
href="https://huggingface.co/docs/leaderboards/open_llm_leaderboard/about" | |
target="_blank" | |
sx={{ | |
...linkStyle(), | |
px: 2, | |
py: 1, | |
"& 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 | |
), | |
}, | |
})} | |
> | |
{mode === "light" ? ( | |
<DarkModeOutlinedIcon sx={iconStyle} /> | |
) : ( | |
<LightModeOutlinedIcon sx={iconStyle} /> | |
)} | |
</ButtonBase> | |
</Tooltip> | |
</Box> | |
) : ( | |
<Box | |
sx={{ | |
display: "flex", | |
gap: 2.5, | |
alignItems: "center", | |
padding: "0.5rem 0", | |
}} | |
> | |
<Box sx={{ display: "flex", gap: 2.5, alignItems: "center" }}> | |
<Link | |
to="/" | |
style={{ textDecoration: "none" }} | |
sx={linkStyle(location.pathname === "/")} | |
> | |
<Box sx={linkStyle(location.pathname === "/")}>Explorer</Box> | |
</Link> | |
<Link | |
to="/submit" | |
style={{ textDecoration: "none" }} | |
sx={linkStyle(location.pathname === "/submit")} | |
> | |
<Box sx={linkStyle(location.pathname === "/submit")}> | |
How to submit? | |
</Box> | |
</Link> | |
<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 /> | |
<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 | |
), | |
}, | |
})} | |
> | |
{mode === "light" ? ( | |
<DarkModeOutlinedIcon sx={iconStyle} /> | |
) : ( | |
<LightModeOutlinedIcon sx={iconStyle} /> | |
)} | |
</ButtonBase> | |
</Tooltip> | |
</Box> | |
)} | |
</Toolbar> | |
</AppBar> | |
); | |
}; | |
export default Navigation; | |