diff --git a/client/src/Pages/StatusPage/Status/themes/refined/RefinedStatusPage.tsx b/client/src/Pages/StatusPage/Status/themes/refined/RefinedStatusPage.tsx
index ef4f73596..332e263bc 100644
--- a/client/src/Pages/StatusPage/Status/themes/refined/RefinedStatusPage.tsx
+++ b/client/src/Pages/StatusPage/Status/themes/refined/RefinedStatusPage.tsx
@@ -1,4 +1,4 @@
-import { useState } from "react";
+import { useMemo, useState } from "react";
import Box from "@mui/material/Box";
import Stack from "@mui/material/Stack";
import { useTranslation } from "react-i18next";
@@ -27,7 +27,7 @@ interface Props {
export const RefinedStatusPage = ({ statusPage, monitors }: Props) => {
const { t } = useTranslation();
const { tokens, mode } = useStatusPageTheme();
- const styles = refinedStyles(tokens, mode === "dark");
+ const styles = useMemo(() => refinedStyles(tokens, mode === "dark"), [tokens, mode]);
const [chartMode, setChartMode] = useState<"heatmap" | "histogram">("heatmap");
const overall = resolveOverallStatus(monitors, t);
@@ -62,7 +62,7 @@ export const RefinedStatusPage = ({ statusPage, monitors }: Props) => {
-
+
{
})}
- {overall.icon}
+ {overall.icon}
{statusPage.showCharts && (
@@ -94,7 +94,7 @@ export const RefinedStatusPage = ({ statusPage, monitors }: Props) => {
role="radio"
aria-checked={chartMode === "heatmap"}
onClick={() => setChartMode("heatmap")}
- sx={(styles.chartSwitchButton as Function)(chartMode === "heatmap")}
+ sx={styles.chartSwitchButton(chartMode === "heatmap")}
>
{t("pages.statusPages.monitorsList.chartTypeHeatmap")}
@@ -104,7 +104,7 @@ export const RefinedStatusPage = ({ statusPage, monitors }: Props) => {
role="radio"
aria-checked={chartMode === "histogram"}
onClick={() => setChartMode("histogram")}
- sx={(styles.chartSwitchButton as Function)(chartMode === "histogram")}
+ sx={styles.chartSwitchButton(chartMode === "histogram")}
>
{t("pages.statusPages.monitorsList.chartTypeHistogram")}
@@ -151,7 +151,7 @@ export const RefinedStatusPage = ({ statusPage, monitors }: Props) => {
{t(statusBadgeKey[monitor.status])}
@@ -167,10 +167,7 @@ export const RefinedStatusPage = ({ statusPage, monitors }: Props) => {
gaugeLabelSx: styles.gaugeLabel,
gaugeValueSx: styles.gaugeValue,
gaugeBarSx: styles.gaugeBar,
- gaugeFillSx: styles.gaugeFill as (
- level: "ok" | "warm" | "hot",
- width: number
- ) => any,
+ gaugeFillSx: styles.gaugeFill,
gaugeSubSx: styles.gaugeSub,
}}
/>
@@ -180,13 +177,13 @@ export const RefinedStatusPage = ({ statusPage, monitors }: Props) => {
any}
+ cellSx={styles.heatmapCell}
/>
) : (
any}
+ barSx={styles.bar}
statsSx={styles.chartStats}
/>
))}
diff --git a/client/src/Pages/StatusPage/Status/themes/refined/styles.ts b/client/src/Pages/StatusPage/Status/themes/refined/styles.ts
index 39bc9bf56..0789efd87 100644
--- a/client/src/Pages/StatusPage/Status/themes/refined/styles.ts
+++ b/client/src/Pages/StatusPage/Status/themes/refined/styles.ts
@@ -1,10 +1,53 @@
+import type { SxProps, Theme } from "@mui/material/styles";
import type { StatusPageThemeTokens } from "../tokens";
+import { type OverallTone, toneColor, toneSoft } from "../shared/overallStatus";
-export type RefinedTone = "up" | "warn" | "down";
export type RefinedHeatCell = "fast" | "med" | "slow" | "down" | "empty";
export type RefinedBarKind = "up" | "down" | "empty";
export type RefinedGaugeFill = "ok" | "warm" | "hot";
+export interface RefinedStyles {
+ page: SxProps;
+ top: SxProps;
+ brand: SxProps;
+ logoMono: SxProps;
+ logoImg: SxProps;
+ company: SxProps;
+ hero: SxProps;
+ statusDot: (tone: OverallTone) => SxProps;
+ statusCopy: SxProps;
+ heroTitle: SxProps;
+ heroSub: SxProps;
+ heroIcon: (tone: OverallTone) => SxProps;
+ chartSwitchWrap: SxProps;
+ chartSwitch: SxProps;
+ chartSwitchButton: (active: boolean) => SxProps;
+ monitorList: SxProps;
+ card: SxProps;
+ cardRow: SxProps;
+ cardLeft: SxProps;
+ monitorName: SxProps;
+ monitorMeta: SxProps;
+ pill: SxProps;
+ pillHardware: SxProps;
+ monitorUrl: SxProps;
+ badge: (tone: OverallTone) => SxProps;
+ heatmap: SxProps;
+ heatmapCell: (kind: RefinedHeatCell) => SxProps;
+ histogram: SxProps;
+ bar: (kind: RefinedBarKind, heightPct: number) => SxProps;
+ chartStats: SxProps;
+ infra: SxProps;
+ infraEmpty: SxProps;
+ gauge: SxProps;
+ gaugeLabel: SxProps;
+ gaugeValue: SxProps;
+ gaugeBar: SxProps;
+ gaugeFill: (level: RefinedGaugeFill, widthPct: number) => SxProps;
+ gaugeSub: SxProps;
+ footer: SxProps;
+}
+
const sansFontStack =
'-apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", Roboto, sans-serif';
@@ -12,13 +55,10 @@ const cardShadow = "0 1px 2px rgba(10, 16, 32, 0.06), 0 6px 18px rgba(10, 16, 32
const cardShadowHover =
"0 2px 4px rgba(16, 24, 40, 0.06), 0 10px 24px rgba(16, 24, 40, 0.06)";
-const toneColor = (tone: RefinedTone, t: StatusPageThemeTokens) =>
- tone === "down" ? t.down : tone === "warn" ? t.warn : t.up;
-
-const toneSoft = (tone: RefinedTone, t: StatusPageThemeTokens) =>
- tone === "down" ? t.downSoft : tone === "warn" ? t.warnSoft : t.upSoft;
-
-export const refinedStyles = (tokens: StatusPageThemeTokens, isDark: boolean) => {
+export const refinedStyles = (
+ tokens: StatusPageThemeTokens,
+ isDark: boolean
+): RefinedStyles => {
const heatCellBg: Record = {
fast: tokens.up,
med: `color-mix(in srgb, ${tokens.up} 60%, #ffffff 40%)`,
@@ -39,7 +79,7 @@ export const refinedStyles = (tokens: StatusPageThemeTokens, isDark: boolean) =>
hot: tokens.down,
};
- const sx: Record = {
+ return {
page: {
flex: "1 0 auto",
maxWidth: 960,
@@ -78,11 +118,7 @@ export const refinedStyles = (tokens: StatusPageThemeTokens, isDark: boolean) =>
fontWeight: 700,
fontSize: 13,
},
- logoImg: {
- maxHeight: 32,
- maxWidth: 120,
- objectFit: "contain",
- },
+ logoImg: { maxHeight: 32, maxWidth: 120, objectFit: "contain" },
company: { fontSize: 14 },
hero: {
@@ -96,7 +132,7 @@ export const refinedStyles = (tokens: StatusPageThemeTokens, isDark: boolean) =>
boxShadow: cardShadow,
mb: "20px",
},
- statusDot: (tone: RefinedTone) => ({
+ statusDot: (tone) => ({
width: 10,
height: 10,
borderRadius: "50%",
@@ -114,17 +150,13 @@ export const refinedStyles = (tokens: StatusPageThemeTokens, isDark: boolean) =>
color: tokens.text,
},
heroSub: { m: 0, color: tokens.textMuted, fontSize: 13 },
- heroIcon: (tone: RefinedTone) => ({
+ heroIcon: (tone) => ({
color: toneColor(tone, tokens),
display: "flex",
alignItems: "center",
}),
- chartSwitchWrap: {
- display: "flex",
- justifyContent: "flex-end",
- mb: "12px",
- },
+ chartSwitchWrap: { display: "flex", justifyContent: "flex-end", mb: "12px" },
chartSwitch: {
display: "inline-flex",
border: `1px solid ${tokens.border}`,
@@ -133,7 +165,7 @@ export const refinedStyles = (tokens: StatusPageThemeTokens, isDark: boolean) =>
p: "3px",
gap: "2px",
},
- chartSwitchButton: (active: boolean) => ({
+ chartSwitchButton: (active) => ({
border: 0,
background: active ? tokens.upSoft : "transparent",
fontFamily: "inherit",
@@ -199,29 +231,19 @@ export const refinedStyles = (tokens: StatusPageThemeTokens, isDark: boolean) =>
borderRadius: "999px",
fontWeight: 600,
},
- pillHardware: isDark
- ? {
- fontSize: 10,
- textTransform: "uppercase",
- letterSpacing: "0.08em",
- padding: "2px 8px",
- borderRadius: "999px",
- fontWeight: 600,
- color: "#60a5fa",
- border: "1px solid rgba(96, 165, 250, 0.3)",
- background: "rgba(96, 165, 250, 0.1)",
- }
- : {
- fontSize: 10,
- textTransform: "uppercase",
- letterSpacing: "0.08em",
- padding: "2px 8px",
- borderRadius: "999px",
- fontWeight: 600,
- color: "#1d4ed8",
- border: "1px solid rgba(29, 78, 216, 0.3)",
- background: "rgba(29, 78, 216, 0.06)",
- },
+ pillHardware: {
+ fontSize: 10,
+ textTransform: "uppercase",
+ letterSpacing: "0.08em",
+ padding: "2px 8px",
+ borderRadius: "999px",
+ fontWeight: 600,
+ color: isDark ? "#60a5fa" : "#1d4ed8",
+ border: `1px solid ${
+ isDark ? "rgba(96, 165, 250, 0.3)" : "rgba(29, 78, 216, 0.3)"
+ }`,
+ background: isDark ? "rgba(96, 165, 250, 0.1)" : "rgba(29, 78, 216, 0.06)",
+ },
monitorUrl: {
fontSize: 12,
color: tokens.textMuted,
@@ -232,7 +254,7 @@ export const refinedStyles = (tokens: StatusPageThemeTokens, isDark: boolean) =>
maxWidth: 280,
},
- badge: (tone: RefinedTone) => ({
+ badge: (tone) => ({
fontSize: 11,
fontWeight: 600,
padding: "4px 10px",
@@ -249,7 +271,7 @@ export const refinedStyles = (tokens: StatusPageThemeTokens, isDark: boolean) =>
gap: "3px",
height: 42,
},
- heatmapCell: (kind: RefinedHeatCell) => ({
+ heatmapCell: (kind) => ({
borderRadius: "2px",
background: heatCellBg[kind],
opacity: kind === "empty" ? 0.4 : 1,
@@ -265,7 +287,7 @@ export const refinedStyles = (tokens: StatusPageThemeTokens, isDark: boolean) =>
alignItems: "flex-end",
height: 42,
},
- bar: (kind: RefinedBarKind, heightPct: number) => ({
+ bar: (kind, heightPct) => ({
background: barBg[kind],
borderRadius: "2px",
minHeight: 3,
@@ -318,7 +340,7 @@ export const refinedStyles = (tokens: StatusPageThemeTokens, isDark: boolean) =>
overflow: "hidden",
mt: "8px",
},
- gaugeFill: (level: RefinedGaugeFill, widthPct: number) => ({
+ gaugeFill: (level, widthPct) => ({
display: "block",
height: "100%",
background: gaugeFillBg[level],
@@ -347,6 +369,4 @@ export const refinedStyles = (tokens: StatusPageThemeTokens, isDark: boolean) =>
},
},
};
-
- return sx;
};
diff --git a/client/src/Pages/StatusPage/Status/themes/shared/ThemedHeatmap.tsx b/client/src/Pages/StatusPage/Status/themes/shared/ThemedHeatmap.tsx
index 2a442405c..ebd275ddc 100644
--- a/client/src/Pages/StatusPage/Status/themes/shared/ThemedHeatmap.tsx
+++ b/client/src/Pages/StatusPage/Status/themes/shared/ThemedHeatmap.tsx
@@ -30,7 +30,7 @@ const classify = (check: CheckSnapshot): Exclude => {
export const ThemedHeatmap = ({ checks, containerSx, cellSx, classPrefix }: Props) => {
const { t } = useTranslation();
- const useSxApi = Boolean(cellSx);
+ const useSxApi = Boolean(containerSx && cellSx);
const source = checks.slice(0, CELLS).reverse();
const padded: (CheckSnapshot | null)[] = [
diff --git a/client/src/Pages/StatusPage/Status/themes/shared/ThemedHistogram.tsx b/client/src/Pages/StatusPage/Status/themes/shared/ThemedHistogram.tsx
index 65027731b..af73095df 100644
--- a/client/src/Pages/StatusPage/Status/themes/shared/ThemedHistogram.tsx
+++ b/client/src/Pages/StatusPage/Status/themes/shared/ThemedHistogram.tsx
@@ -36,7 +36,7 @@ export const ThemedHistogram = ({
statsGap = 1,
}: Props) => {
const { t } = useTranslation();
- const useSxApi = Boolean(barSx);
+ const useSxApi = Boolean(containerSx && barSx && statsSx);
const { padded, max, avg, peak } = useMemo(() => {
const source = checks.slice(0, CELLS).reverse();
diff --git a/client/src/Pages/StatusPage/Status/themes/shared/ThemedInfrastructure.tsx b/client/src/Pages/StatusPage/Status/themes/shared/ThemedInfrastructure.tsx
index d4334e959..8c642a344 100644
--- a/client/src/Pages/StatusPage/Status/themes/shared/ThemedInfrastructure.tsx
+++ b/client/src/Pages/StatusPage/Status/themes/shared/ThemedInfrastructure.tsx
@@ -118,8 +118,8 @@ export const ThemedInfrastructure = ({ monitor, sxApi, classPrefix }: Props) =>
return (
{gauges.map((g) => {
- const heatClass =
- g.value > 85 ? `${classPrefix}-hot` : g.value > 70 ? `${classPrefix}-warm` : "";
+ const level = heatLevel(g.value);
+ const heatClass = level === "ok" ? "" : `${classPrefix}-${level}`;
return (
+ tone === "down" ? t.down : tone === "warn" ? t.warn : t.up;
+
+export const toneSoft = (tone: OverallTone, t: StatusPageThemeTokens): string =>
+ tone === "down" ? t.downSoft : tone === "warn" ? t.warnSoft : t.upSoft;
+
export interface OverallStatus {
tone: OverallTone;
message: string;