From 9a6602b9e1b1a1a9b8ca38d613b7033c1fd5dd34 Mon Sep 17 00:00:00 2001 From: gorkem-bwl Date: Fri, 28 Aug 2026 19:13:33 -0400 Subject: [PATCH 1/4] fix(client): add hover states to tables, cards, stat boxes and icon buttons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clickable surfaces across the app set `cursor: pointer` but gave no visual response on hover, so rows and cards read as static text. Two separate causes: - `DataTable` never passed MUI's opt-in `hover` prop on `TableRow`, which is `false` by default, so no table in the app shaded on hover. One change here covers all 16 page tables (Uptime, Incidents, Tags, Team, Notifications, Maintenance, Proxies, Status pages, Checks, Geo checks, Infrastructure, PageSpeed and the three Logs tables). - `IconButton` gates its hover style behind `props => !props.disableRipple`, and the theme sets `disableRipple: true` globally, so the row action gear and the pagination arrows lost their background. `MenuItem` is unaffected — its hover sits on the base style — so action menu items already worked and are left alone. Adds a `HOVER.ROW` (0.025) constant and an `action.rowHover` palette token, defined in both light and dark palettes so the overlay direction is correct on each surface. Kept separate from MUI's shared `action.hover` so menu items, which read that token, are not restyled as a side effect. Also fixes `cursor` on expandable rows, which showed `default` despite being clickable to expand. Claude-Session: https://claude.ai/code/session_01AbYLvwpEaZFXktHVcqrFRd --- client/src/Components/actions-menu/index.tsx | 11 +++++++- .../Components/design-elements/StatBox.tsx | 7 ++++- .../src/Components/design-elements/Table.tsx | 28 +++++++++++++++++-- client/src/Utils/Theme/Palette.ts | 7 +++++ client/src/Utils/Theme/Theme.ts | 6 ++++ client/src/Utils/Theme/constants.ts | 1 + 6 files changed, 55 insertions(+), 5 deletions(-) diff --git a/client/src/Components/actions-menu/index.tsx b/client/src/Components/actions-menu/index.tsx index 3b2f3688a..726ef6821 100644 --- a/client/src/Components/actions-menu/index.tsx +++ b/client/src/Components/actions-menu/index.tsx @@ -3,6 +3,7 @@ import Menu from "@mui/material/Menu"; import MenuItem from "@mui/material/MenuItem"; import IconButton from "@mui/material/IconButton"; import { Settings } from "lucide-react"; +import { useTheme } from "@mui/material/styles"; export type ActionMenuItem = { id: number | string; @@ -12,6 +13,7 @@ export type ActionMenuItem = { }; export const ActionsMenu = ({ items }: { items: ActionMenuItem[] }) => { + const theme = useTheme(); const [anchorEl, setAnchorEl] = useState(null); const open = Boolean(anchorEl); @@ -27,7 +29,14 @@ export const ActionsMenu = ({ items }: { items: ActionMenuItem[] }) => { return (
- + diff --git a/client/src/Components/design-elements/Table.tsx b/client/src/Components/design-elements/Table.tsx index a02f9be8f..e4e636f80 100644 --- a/client/src/Components/design-elements/Table.tsx +++ b/client/src/Components/design-elements/Table.tsx @@ -108,6 +108,11 @@ export function DataTable< borderRadius: theme.shape.borderRadius, padding: theme.spacing(LAYOUT.XS), cursor: onRowClick ? "pointer" : "default", + ...(onRowClick && { + "&:hover": { + backgroundColor: theme.palette.action.rowHover, + }, + }), }} key={key} > @@ -207,6 +212,10 @@ export function DataTable< "& .MuiTableBody-root .MuiTableRow-root:last-child .MuiTableCell-root": { borderBottom: "none", }, + "& .MuiTableBody-root .MuiTableRow-root.is-clickable:hover .MuiTableCell-root": + { + backgroundColor: theme.palette.action.rowHover, + }, }} > @@ -231,8 +240,9 @@ export function DataTable< return ( { @@ -314,7 +324,13 @@ function TablePaginationActions(props: TablePaginationActionsProps) { return ( Date: Fri, 28 Aug 2026 19:53:39 -0400 Subject: [PATCH 2/4] fix(client): correct StatBox hover and separate nested-control hover MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses review findings on the hover-states change. StatBox's hover was a no-op. `GradientBox` always paints an opaque `linear-gradient` via the `background` shorthand, which populates background-image and covers any `backgroundColor` beneath it, so the new hover was invisible — a regression from the `opacity: 0.95` it replaced. The overlay now layers onto the same gradient, and moves into `GradientBox` where `bg` is in scope, behind an `interactive` prop. The mobile card branch gated its cursor and hover on `onRowClick` alone, so expandable-row tables below the md breakpoint rendered cards that expand on click but showed no pointer and no hover — the exact inconsistency this change set out to fix, reintroduced on mobile. Both branches now share one `isInteractive` flag. The row action gear used the same overlay as the row beneath it. Alpha overlays compose, so it was not invisible as reported, but the resulting delta was 6 levels — too faint for a nested control. Adds `HOVER.CONTROL` (0.05) and an `action.controlHover` token for controls nested inside a hoverable row: the gear and the pagination arrows. Claude-Session: https://claude.ai/code/session_01AbYLvwpEaZFXktHVcqrFRd --- client/src/Components/actions-menu/index.tsx | 2 +- .../Components/design-elements/StatBox.tsx | 20 +++++++++---------- .../src/Components/design-elements/Table.tsx | 13 ++++++------ client/src/Utils/Theme/Palette.ts | 2 ++ client/src/Utils/Theme/Theme.ts | 2 ++ client/src/Utils/Theme/constants.ts | 3 ++- 6 files changed, 24 insertions(+), 18 deletions(-) diff --git a/client/src/Components/actions-menu/index.tsx b/client/src/Components/actions-menu/index.tsx index 726ef6821..2eca19cee 100644 --- a/client/src/Components/actions-menu/index.tsx +++ b/client/src/Components/actions-menu/index.tsx @@ -33,7 +33,7 @@ export const ActionsMenu = ({ items }: { items: ActionMenuItem[] }) => { onClick={handleClick} sx={{ "&:hover": { - backgroundColor: theme.palette.action.rowHover, + backgroundColor: theme.palette.action.controlHover, }, }} > diff --git a/client/src/Components/design-elements/StatBox.tsx b/client/src/Components/design-elements/StatBox.tsx index 81205e967..1543766fc 100644 --- a/client/src/Components/design-elements/StatBox.tsx +++ b/client/src/Components/design-elements/StatBox.tsx @@ -11,9 +11,10 @@ import type { SxProps } from "@mui/material"; type GradientBox = React.PropsWithChildren<{ palette?: PaletteKey; sx?: SxProps; + interactive?: boolean; }>; -export const GradientBox = ({ children, palette, sx }: GradientBox) => { +export const GradientBox = ({ children, palette, sx, interactive }: GradientBox) => { const theme = useTheme(); const isSmall = useMediaQuery(theme.breakpoints.down("md")); const isLight = theme.palette.mode === "light"; @@ -30,6 +31,12 @@ export const GradientBox = ({ children, palette, sx }: GradientBox) => { padding: `${theme.spacing(4)} ${theme.spacing(8)}`, width: isSmall ? `100%` : `calc(25% - (3 * ${theme.spacing(8)} / 4))`, background: bg, + ...(interactive && { + cursor: "pointer", + "&:hover": { + backgroundImage: `linear-gradient(${theme.palette.action.rowHover}, ${theme.palette.action.rowHover}), ${bg}`, + }, + }), ...sx, }} > @@ -62,15 +69,8 @@ export const StatBox = ({ return ( diff --git a/client/src/Components/design-elements/Table.tsx b/client/src/Components/design-elements/Table.tsx index e4e636f80..c57616740 100644 --- a/client/src/Components/design-elements/Table.tsx +++ b/client/src/Components/design-elements/Table.tsx @@ -79,6 +79,7 @@ export function DataTable< }; const isSmall = useMediaQuery(theme.breakpoints.down("md")); + const isInteractive = Boolean(onRowClick) || expandableRows; if (data.length === 0 || headers.length === 0) { return ( @@ -107,8 +108,8 @@ export function DataTable< borderColor: theme.palette.divider, borderRadius: theme.shape.borderRadius, padding: theme.spacing(LAYOUT.XS), - cursor: onRowClick ? "pointer" : "default", - ...(onRowClick && { + cursor: isInteractive ? "pointer" : "default", + ...(isInteractive && { "&:hover": { backgroundColor: theme.palette.action.rowHover, }, @@ -240,9 +241,9 @@ export function DataTable< return ( { @@ -328,7 +329,7 @@ function TablePaginationActions(props: TablePaginationActionsProps) { flexShrink: 0, ml: { xs: 0, md: 2.5 }, "& .MuiIconButton-root:not(.Mui-disabled):hover": { - backgroundColor: theme.palette.action.rowHover, + backgroundColor: theme.palette.action.controlHover, }, }} className="table-pagination-actions" @@ -432,7 +433,7 @@ function HasMoreTablePaginationActions(props: HasMoreTablePaginationActionsProps flexShrink: 0, ml: { xs: 0, md: 2.5 }, "& .MuiIconButton-root:not(.Mui-disabled):hover": { - backgroundColor: theme.palette.action.rowHover, + backgroundColor: theme.palette.action.controlHover, }, }} className="table-pagination-actions" diff --git a/client/src/Utils/Theme/Palette.ts b/client/src/Utils/Theme/Palette.ts index 9c9f4e04d..0d9168f8a 100644 --- a/client/src/Utils/Theme/Palette.ts +++ b/client/src/Utils/Theme/Palette.ts @@ -42,6 +42,7 @@ export const lightPalette = { }, action: { rowHover: alpha(colors.gray900, HOVER.ROW), + controlHover: alpha(colors.gray900, HOVER.CONTROL), }, secondary: { main: colors.gray200, @@ -71,6 +72,7 @@ export const darkPalette = { }, action: { rowHover: alpha("#FFFFFF", HOVER.ROW), + controlHover: alpha("#FFFFFF", HOVER.CONTROL), }, secondary: { main: colors.gray700, diff --git a/client/src/Utils/Theme/Theme.ts b/client/src/Utils/Theme/Theme.ts index b39ba4abb..9b95fb121 100644 --- a/client/src/Utils/Theme/Theme.ts +++ b/client/src/Utils/Theme/Theme.ts @@ -15,9 +15,11 @@ declare module "@mui/material/styles" { } interface TypeAction { rowHover: string; + controlHover: string; } interface TypeActionOptions { rowHover?: string; + controlHover?: string; } interface Palette { sidebar: { accent: string }; diff --git a/client/src/Utils/Theme/constants.ts b/client/src/Utils/Theme/constants.ts index c8641e7aa..70ddcd407 100644 --- a/client/src/Utils/Theme/constants.ts +++ b/client/src/Utils/Theme/constants.ts @@ -20,5 +20,6 @@ export const LAYOUT = { export const HOVER = { DARKEN: 0.06, // This is a coefficient for darkening function - ROW: 0.025, // Overlay alpha for hoverable rows, cards and icon buttons + ROW: 0.025, // Overlay alpha for hoverable rows and cards + CONTROL: 0.05, // Stronger overlay for controls nested inside a hoverable row } as const; From 13e49c518d12f56ee01589fffa6d796db5552d18 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Mon, 31 Aug 2026 09:42:04 -0700 Subject: [PATCH 3/4] remove dead code, fix mobile regeression --- client/src/Components/design-elements/Table.tsx | 4 ++-- client/src/Utils/Theme/Theme.ts | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/client/src/Components/design-elements/Table.tsx b/client/src/Components/design-elements/Table.tsx index c57616740..01bf76c74 100644 --- a/client/src/Components/design-elements/Table.tsx +++ b/client/src/Components/design-elements/Table.tsx @@ -108,8 +108,8 @@ export function DataTable< borderColor: theme.palette.divider, borderRadius: theme.shape.borderRadius, padding: theme.spacing(LAYOUT.XS), - cursor: isInteractive ? "pointer" : "default", - ...(isInteractive && { + cursor: onRowClick ? "pointer" : "default", + ...(onRowClick && { "&:hover": { backgroundColor: theme.palette.action.rowHover, }, diff --git a/client/src/Utils/Theme/Theme.ts b/client/src/Utils/Theme/Theme.ts index 9b95fb121..c63929a60 100644 --- a/client/src/Utils/Theme/Theme.ts +++ b/client/src/Utils/Theme/Theme.ts @@ -17,10 +17,6 @@ declare module "@mui/material/styles" { rowHover: string; controlHover: string; } - interface TypeActionOptions { - rowHover?: string; - controlHover?: string; - } interface Palette { sidebar: { accent: string }; rowStatus: { running: string; paused: string }; From 2fec09df62413e006d3b661470868d11aee7eb4c Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Mon, 31 Aug 2026 09:47:20 -0700 Subject: [PATCH 4/4] apply hover states to components directly rather than to parent --- .../src/Components/design-elements/Table.tsx | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/client/src/Components/design-elements/Table.tsx b/client/src/Components/design-elements/Table.tsx index 01bf76c74..df0d52b16 100644 --- a/client/src/Components/design-elements/Table.tsx +++ b/client/src/Components/design-elements/Table.tsx @@ -303,6 +303,12 @@ interface TablePaginationActionsProps { onPageChange: (event: React.MouseEvent, newPage: number) => void; } +const controlHoverSx = (theme: Theme): SxProps => ({ + "&:hover": { + backgroundColor: theme.palette.action.controlHover, + }, +}); + function TablePaginationActions(props: TablePaginationActionsProps) { const theme = useTheme(); const { count, page, rowsPerPage, onPageChange } = props; @@ -325,19 +331,14 @@ function TablePaginationActions(props: TablePaginationActionsProps) { return ( {theme.direction === "rtl" ? ( {theme.direction === "rtl" ? ( = Math.ceil(count / rowsPerPage) - 1} aria-label="next page" + sx={controlHoverSx(theme)} > {theme.direction === "rtl" ? ( = Math.ceil(count / rowsPerPage) - 1} aria-label="last page" + sx={controlHoverSx(theme)} > {theme.direction === "rtl" ? ( {theme.direction === "rtl" ? ( {theme.direction === "rtl" ? ( {theme.direction === "rtl" ? (