webui/src/app/ui/banner.tsx (116 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ "use client"; import { AppBar, Container, Toolbar, IconButton, Box, Tooltip, Typography } from "@mui/material"; import Image from "next/image"; import NavLinks from "./nav-links"; import { useTheme } from "../theme-provider"; import Brightness4Icon from "@mui/icons-material/Brightness4"; import Brightness7Icon from "@mui/icons-material/Brightness7"; import GitHubIcon from "@mui/icons-material/GitHub"; import HomeIcon from "@mui/icons-material/Home"; import FolderIcon from "@mui/icons-material/Folder"; import MenuBookIcon from "@mui/icons-material/MenuBook"; import { usePathname } from "next/navigation"; import { useEffect, useState } from "react"; const links = [ { url: "/", title: "Home", icon: <HomeIcon fontSize="small" />, }, { url: "/namespaces", title: "Namespaces", icon: <FolderIcon fontSize="small" />, }, { url: "https://kvrocks.apache.org", title: "Documentation", icon: <MenuBookIcon fontSize="small" />, _blank: true, }, ]; export default function Banner() { const { isDarkMode, toggleTheme } = useTheme(); const pathname = usePathname(); const [mounted, setMounted] = useState(false); useEffect(() => { const storedTheme = localStorage.getItem("theme"); const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches; const shouldBeDark = storedTheme === "dark" || (!storedTheme && prefersDark); if (shouldBeDark) { document.getElementById("navbar")?.classList.add("navbar-dark-mode"); } setMounted(true); }, []); // Generate breadcrumb from pathname const breadcrumbs = pathname.split("/").filter(Boolean); return ( <AppBar position="fixed" elevation={0} id="navbar" className={`backdrop-blur-sm transition-colors duration-300 ${ isDarkMode ? "navbar-dark-mode bg-opacity-95" : "bg-white bg-opacity-95 text-gray-800" }`} sx={{ bgcolor: isDarkMode ? "rgba(21, 101, 192, 0.98) !important" : "rgba(255, 255, 255, 0.98)", backdropFilter: "blur(8px)", borderBottom: isDarkMode ? "1px solid rgba(30, 64, 175, 0.3)" : "1px solid rgba(229, 231, 235, 0.6)", }} > <Container maxWidth={false}> <Toolbar className="flex justify-between"> <div className="flex items-center"> <Image src="/logo.svg" width={40} height={40} alt="logo" className="mr-4" /> <Typography variant="h6" component="div" className="hidden font-medium text-primary dark:text-primary-light sm:block" > Apache Kvrocks Controller </Typography> </div> <Box className="hidden items-center space-x-1 md:flex"> <NavLinks links={links} /> </Box> <Box className="flex items-center"> {breadcrumbs.length > 0 && ( <Box className="mr-4 hidden items-center rounded-md bg-gray-100 px-4 py-1 text-sm dark:bg-dark-border md:flex"> {breadcrumbs.map((breadcrumb, i) => ( <Typography key={i} variant="body2" className="text-gray-500 dark:text-gray-400" > {i > 0 && " / "} {breadcrumb} </Typography> ))} </Box> )} <Tooltip title="Toggle dark mode"> <IconButton onClick={toggleTheme} color="inherit" size="small"> {isDarkMode ? <Brightness7Icon /> : <Brightness4Icon />} </IconButton> </Tooltip> <Tooltip title="GitHub Repository"> <IconButton color="inherit" href="https://github.com/apache/kvrocks-controller" target="_blank" size="small" className="ml-2" > <GitHubIcon /> </IconButton> </Tooltip> </Box> </Toolbar> </Container> </AppBar> ); }