action menu

This commit is contained in:
Alex Holliday committed 2025-10-06 11:34:29 -07:00
1 parent 7c3a05077c
commit 61651a0f4d
4 files changed
+160 -2

No files matched your search

@@ -0,0 +1,50 @@
import { useState } from "react";
import Menu from "@mui/material/Menu";
import MenuItem from "@mui/material/MenuItem";
import IconButton from "@mui/material/IconButton";
import Settings from "@/assets/icons/settings-bold.svg?react";
export type ActionMenuItem = {
id: number | string;
label: string;
action: Function;
closeMenu?: boolean;
};
export const ActionsMenu = ({ items }: { items: ActionMenuItem[] }) => {
const [anchorEl, setAnchorEl] = useState<null | any>(null);
const open = Boolean(anchorEl);
const handleClick = (event: React.MouseEvent<any>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<div>
<IconButton onClick={handleClick}>
<Settings />
</IconButton>
<Menu
anchorEl={anchorEl}
open={open}
onClose={handleClose}
>
{items.map((item) => (
<MenuItem
key={item.id}
onClick={() => {
if (item.closeMenu) handleClose();
item.action();
}}
>
{item.label}
</MenuItem>
))}
</Menu>
</div>
);
};
@@ -5,7 +5,8 @@ import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import { useTheme } from "@mui/material/styles";
import { typographyLevels } from "@/Utils/Theme/v2/palette";
export type Header<T> = {
id: number | string;
content: React.ReactNode;
@@ -22,10 +23,30 @@ export function DataTable<T extends { id?: string | number; _id?: string | numbe
headers,
data,
}: DataTableProps<T>) {
const theme = useTheme();
if (data.length === 0 || headers.length === 0) return <div>No data</div>;
return (
<TableContainer component={Paper}>
<Table stickyHeader>
<Table
stickyHeader
sx={{
"&.MuiTable-root :is(.MuiTableHead-root, .MuiTableBody-root) :is(th, td)": {
paddingLeft: theme.spacing(8),
},
"& :is(th)": {
backgroundColor: theme.palette.secondary.main,
color: theme.palette.secondary.contrastText,
fontWeight: 600,
},
"& :is(td)": {
backgroundColor: theme.palette.primary.main,
color: theme.palette.primary.contrastTextSecondary,
},
"& .MuiTableBody-root .MuiTableRow-root:last-child .MuiTableCell-root": {
borderBottom: "none",
},
}}
>
<TableHead>
<TableRow>
{headers.map((header, idx) => {
@@ -6,6 +6,66 @@ import { Table } from "@/Components/v2/DesignElements";
import { useTranslation } from "react-i18next";
import { useMediaQuery } from "@mui/material";
import { useTheme } from "@mui/material/styles";
import { ActionsMenu } from "@/Components/v2/ActionsMenu";
import type { ActionMenuItem } from "@/Components/v2/ActionsMenu";
const getActions = (t: Function): ActionMenuItem[] => {
return [
{
id: 1,
label: "Open site",
action: () => {
console.log("Open site");
},
closeMenu: true,
},
{
id: 2,
label: "Details",
action: () => {
console.log("Open details");
},
},
{
id: 3,
label: "Incidents",
action: () => {
console.log("Open incidents");
},
},
{
id: 4,
label: "Configure",
action: () => {
console.log("Open configure");
},
},
{
id: 5,
label: "Clone",
action: () => {
console.log("Open clone");
},
},
{
id: 6,
label: "Pause",
action: () => {
console.log("Open pause");
},
closeMenu: true,
},
{
id: 7,
label: "Delete",
action: () => {
console.log("Open delete");
},
closeMenu: true,
},
];
};
const getHeaders = (t: Function) => {
const headers: Header<IMonitor>[] = [
{
@@ -40,6 +100,13 @@ const getHeaders = (t: Function) => {
return row.type;
},
},
{
id: "actions",
content: t("actions"),
render: (row) => {
return <ActionsMenu items={getActions(t)} />;
},
},
];
return headers;
};
+20
View File
@@ -1,6 +1,8 @@
import { createTheme } from "@mui/material";
import { lightPalette, darkPalette, typographyLevels } from "./palette";
const fontFamilyPrimary = '"Inter" , sans-serif';
const shadow =
"0px 4px 24px -4px rgba(16, 24, 40, 0.08), 0px 3px 3px -3px rgba(16, 24, 40, 0.03)";
export const theme = (mode: string, palette: any) =>
createTheme({
@@ -66,6 +68,24 @@ export const theme = (mode: string, palette: any) =>
},
},
},
MuiPaper: {
styleOverrides: {
root: ({ theme }) => {
return {
marginTop: 4,
padding: 0,
border: 1,
borderStyle: "solid",
borderColor: theme.palette.primary.lowContrast,
borderRadius: 4,
boxShadow: shadow,
backgroundColor: theme.palette.primary.main,
backgroundImage: "none",
};
},
},
},
},
shape: {
borderRadius: 2,