extend toolbar styling, add support for atomic menu

This commit is contained in:
Johannes Kirschbauer 2023-11-20 09:21:59 +01:00
parent 9d99f93b37
commit b4550b3dd9
Signed by: hsjobeki
SSH Key Fingerprint: SHA256:vX3utDqig7Ph5L0JPv87ZTPb/w7cMzREKVZzzLFg9qU
3 changed files with 97 additions and 65 deletions

View File

@ -1,24 +1,17 @@
"use client";
import { Sidebar } from "@/components/sidebar";
import { tw } from "@/utils/tailwind";
import MenuIcon from "@mui/icons-material/Menu";
import {
CssBaseline,
IconButton,
ThemeProvider,
useMediaQuery,
} from "@mui/material";
import { CssBaseline, ThemeProvider, useMediaQuery } from "@mui/material";
import { StyledEngineProvider } from "@mui/material/styles";
import axios from "axios";
import localFont from "next/font/local";
import Image from "next/image";
import * as React from "react";
import { Toaster } from "react-hot-toast";
import "./globals.css";
import { darkTheme, lightTheme } from "./theme/themes";
import { WithAppState } from "@/components/hooks/useAppContext";
import { ClanToolbar } from "@/components/clanToolbar";
import { WithAppState } from "@/components/hooks/useAppContext";
const roboto = localFont({
src: [
@ -70,29 +63,10 @@ export default function RootLayout({
!showSidebar && translate
} flex h-full w-full flex-col overflow-y-scroll transition-[margin] duration-150 ease-in-out`}
>
<ClanToolbar />
<div className="static top-0 mb-2 py-2">
<div className="grid grid-cols-3">
<div className="col-span-1">
<IconButton
hidden={showSidebar}
onClick={() => setShowSidebar((c) => !c)}
>
{!showSidebar && <MenuIcon />}
</IconButton>
</div>
<div className="col-span-1 block w-full bg-fixed text-center font-semibold dark:invert lg:hidden">
<Image
src="/favicon.png"
alt="Clan Logo"
width={58}
height={58}
priority
/>
</div>
</div>
</div>
<ClanToolbar
isSidebarVisible={showSidebar}
handleSidebar={setShowSidebar}
/>
<div className="px-1">
<div className="relative flex h-full flex-1 flex-col">
<main>{children}</main>

View File

@ -1,6 +1,7 @@
import { useFlakeHistoryList } from "@/api/flake/flake";
import DynamicFeedIcon from "@mui/icons-material/DynamicFeed";
import { IconButton, LinearProgress } from "@mui/material";
import MenuIcon from "@mui/icons-material/Menu";
import { Button, Divider, LinearProgress } from "@mui/material";
import Menu from "@mui/material/Menu";
import MenuItem from "@mui/material/MenuItem";
import * as React from "react";
@ -9,57 +10,112 @@ interface ToolbarButtonProps {
icon: React.ReactNode;
onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
}
function ToolbarButton(props: ToolbarButtonProps) {
export function ToolbarButton(props: ToolbarButtonProps) {
const { icon, onClick } = props;
return (
<div className="">
<IconButton onClick={onClick}>{icon}</IconButton>
</div>
<Button
sx={{
"& .MuiButton-startIcon": {
m: 0,
},
}}
onClick={onClick}
startIcon={icon}
variant="text"
color="inherit"
// fullWidth
/>
);
}
const ClanHistoryMenu = () => {
const { data, isLoading } = useFlakeHistoryList();
return (
<>
{isLoading ? (
<LinearProgress />
) : (
data?.data.map((item, index) => <MenuItem key={index}>{item}</MenuItem>)
)}
{!isLoading && data?.data.length === 0 && (
<MenuItem>No Clan History</MenuItem>
)}
</>
);
};
type ToolbarItem = {
icon: React.ReactNode;
menu: React.ReactNode;
};
const toolbarItems: ToolbarItem[] = [
{
icon: <DynamicFeedIcon />,
menu: <ClanHistoryMenu />,
},
];
export function ClanToolbar() {
const { data, isLoading } = useFlakeHistoryList();
interface ClanToolbarProps {
isSidebarVisible: boolean;
handleSidebar: React.Dispatch<React.SetStateAction<boolean>>;
}
export function ClanToolbar(props: ClanToolbarProps) {
const { isSidebarVisible, handleSidebar } = props;
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
const [openIdx, setOpenIdx] = React.useState<number | null>(null);
const handleClick = (
event: React.MouseEvent<HTMLButtonElement>,
idx: number
) => {
setAnchorEl(event.currentTarget);
setOpenIdx(idx);
};
const handleClose = () => {
setAnchorEl(null);
setOpenIdx(null);
};
return (
<div className="grid w-full auto-cols-min grid-flow-col grid-rows-1 place-items-end justify-end gap-2">
{toolbarItems.map((item, index) => (
<ToolbarButton key={index} icon={item.icon} onClick={handleClick} />
))}
<Menu
id="basic-menu"
anchorEl={anchorEl}
open={open}
onClose={handleClose}
MenuListProps={{
"aria-labelledby": "basic-button",
}}
<div
className="flex border-x-0 border-b
border-t-0 border-solid border-neutral-80"
>
{!isSidebarVisible && (
<ToolbarButton
icon={<MenuIcon />}
onClick={() => handleSidebar((c) => !c)}
/>
)}
<div
className="
grid w-full auto-cols-min grid-flow-col grid-rows-1
justify-end gap-0
"
>
{isLoading ? (
<LinearProgress />
) : (
data?.data.map((item, index) => (
<MenuItem key={index}>{item}</MenuItem>
))
)}
{!isLoading && data?.data.length === 0 && (
<MenuItem>No Clan History</MenuItem>
)}
</Menu>
{toolbarItems.map((item, index) => (
<React.Fragment key={index}>
<Divider flexItem orientation="vertical" />
<ToolbarButton
icon={item.icon}
onClick={(ev) => handleClick(ev, index)}
/>
<Menu
id="basic-menu"
anchorEl={anchorEl}
open={index == openIdx}
onClose={handleClose}
MenuListProps={{
"aria-labelledby": "basic-button",
}}
>
{item.menu}
</Menu>
</React.Fragment>
))}
</div>
</div>
);
}

View File

@ -5,8 +5,10 @@ import { toast } from "react-hot-toast";
export function clanErrorToast(error: AxiosError<HTTPValidationError>) {
console.error({ error });
const detail = error.response?.data.detail?.[0]?.msg;
const detailAlt = error.response?.data.detail as unknown as string;
const cause = error.cause?.message;
const axiosMessage = error.message;
const sanitizedMsg = detail || cause || axiosMessage || "Unexpected error";
const sanitizedMsg =
detail || detailAlt || cause || axiosMessage || "Unexpected error";
toast.error(sanitizedMsg);
}