From 61651a0f4dcda47f3957e147665227cb60d5a8e8 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Mon, 6 Oct 2025 11:34:29 -0700 Subject: [PATCH] action menu --- .../src/Components/v2/ActionsMenu/index.tsx | 50 ++++++++++++++ .../Components/v2/DesignElements/Table.tsx | 25 ++++++- client/src/Pages/v2/Uptime/MonitorTable.tsx | 67 +++++++++++++++++++ client/src/Utils/Theme/v2/theme.ts | 20 ++++++ 4 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 client/src/Components/v2/ActionsMenu/index.tsx diff --git a/client/src/Components/v2/ActionsMenu/index.tsx b/client/src/Components/v2/ActionsMenu/index.tsx new file mode 100644 index 000000000..fb5f48fc9 --- /dev/null +++ b/client/src/Components/v2/ActionsMenu/index.tsx @@ -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); + const open = Boolean(anchorEl); + + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + + const handleClose = () => { + setAnchorEl(null); + }; + + return ( +
+ + + + + {items.map((item) => ( + { + if (item.closeMenu) handleClose(); + item.action(); + }} + > + {item.label} + + ))} + +
+ ); +}; diff --git a/client/src/Components/v2/DesignElements/Table.tsx b/client/src/Components/v2/DesignElements/Table.tsx index b45a5bee9..118a238ea 100644 --- a/client/src/Components/v2/DesignElements/Table.tsx +++ b/client/src/Components/v2/DesignElements/Table.tsx @@ -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 = { id: number | string; content: React.ReactNode; @@ -22,10 +23,30 @@ export function DataTable) { + const theme = useTheme(); if (data.length === 0 || headers.length === 0) return
No data
; return ( - +
{headers.map((header, idx) => { diff --git a/client/src/Pages/v2/Uptime/MonitorTable.tsx b/client/src/Pages/v2/Uptime/MonitorTable.tsx index 55d3cdfe3..2d02359c1 100644 --- a/client/src/Pages/v2/Uptime/MonitorTable.tsx +++ b/client/src/Pages/v2/Uptime/MonitorTable.tsx @@ -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[] = [ { @@ -40,6 +100,13 @@ const getHeaders = (t: Function) => { return row.type; }, }, + { + id: "actions", + content: t("actions"), + render: (row) => { + return ; + }, + }, ]; return headers; }; diff --git a/client/src/Utils/Theme/v2/theme.ts b/client/src/Utils/Theme/v2/theme.ts index c278f9004..3d68613b9 100644 --- a/client/src/Utils/Theme/v2/theme.ts +++ b/client/src/Utils/Theme/v2/theme.ts @@ -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,