From 5d5d1dbb233b0cb5b031bdaff95d35eb7cecf70e Mon Sep 17 00:00:00 2001 From: gorkem-bwl Date: Tue, 28 Apr 2026 23:56:10 -0400 Subject: [PATCH] feat(incidents): consistent typography, icons, and layout across the page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - All uppercase headers (Active Incidents, Latest Incidents, Incident Statistics, Resolved Incidents, summary card titles, details card sections) now use the existing 'eyebrow' typography variant. That's the same style used on the Logs page and lives in Theme.ts so future tweaks land in one place. - Latest Incidents and Incident Statistics rows now share a minHeight so both cards line up vertically; Latest Incidents items dropped their extra dividers and Box wrappers. - Body text in the summary cards (and the details dialog) uses variant=body1 (13px) consistently — previously a mix of body1/body2 and unspecified Typography. - All lucide icons in CardSummary go through the design-system wrapper so they share the project's strokeWidth=1.5 default rather than lucide's default 2. - ControlsIncidentFilter: replaced the missing pages.incidents.filters.clearFilters key (which was rendering as raw text) with the existing common.buttons.clearFilters. - CardDetails: extracted local SectionHeading and Cell helpers; switched the cards' bare cells to variant=body1 + variant=eyebrow for headings; dropped redundant title-dividers (eyebrow style already separates visually). --- .../Incidents/Components/CardDetails.tsx | 100 +++++++++--------- .../Incidents/Components/CardSummary.tsx | 63 +++++------ .../Components/ControlsIncidentFilter.tsx | 2 +- client/src/Pages/Incidents/index.tsx | 11 +- 4 files changed, 85 insertions(+), 91 deletions(-) diff --git a/client/src/Pages/Incidents/Components/CardDetails.tsx b/client/src/Pages/Incidents/Components/CardDetails.tsx index 448ba2e69..c4ae3a83d 100644 --- a/client/src/Pages/Incidents/Components/CardDetails.tsx +++ b/client/src/Pages/Incidents/Components/CardDetails.tsx @@ -20,6 +20,20 @@ interface CardDetailsProps { sx?: object; } +const SectionHeading = ({ children }: { children: React.ReactNode }) => ( + + {children} + +); + +const Cell = ({ children }: { children: React.ReactNode }) => ( + {children} +); + export const CardDetails = ({ incident, monitor, sx }: CardDetailsProps) => { const { t } = useTranslation(); const theme = useTheme(); @@ -33,22 +47,18 @@ export const CardDetails = ({ incident, monitor, sx }: CardDetailsProps) => { gap={theme.spacing(LAYOUT.MD)} sx={sx} > - - {t("pages.incidents.dialog.details.title")} - + {t("pages.incidents.dialog.details.title")} - - {t("pages.incidents.dialog.details.overview")} - - - + {t("pages.incidents.dialog.details.overview")} - {t("pages.incidents.dialog.details.status")} + + {t("pages.incidents.dialog.details.status")} + { {monitor && ( <> - {t("pages.incidents.dialog.details.monitor")} + + {t("pages.incidents.dialog.details.monitor")} + - {monitor.name ?? "N/A"} + {monitor.name ?? "N/A"} - {t("pages.incidents.dialog.details.url")} + {t("pages.incidents.dialog.details.url")} - {monitor.url ?? "N/A"} + {monitor.url ?? "N/A"} )} @@ -78,51 +90,48 @@ export const CardDetails = ({ incident, monitor, sx }: CardDetailsProps) => { - - {t("pages.incidents.dialog.details.analysis")} - - + {t("pages.incidents.dialog.details.analysis")} - {t("pages.incidents.dialog.details.timeline")} + {t("pages.incidents.dialog.details.timeline")} - {t("pages.incidents.dialog.details.detailsLabel")} + {t("pages.incidents.dialog.details.detailsLabel")} - + - + - {t("pages.incidents.dialog.details.startedAt")} + {t("pages.incidents.dialog.details.startedAt")} - + {formatDateWithTz(incident.startTime, "D MMM YYYY, h:mm A", uiTimezone)} - + - {t("pages.incidents.dialog.details.statusCode")} + {t("pages.incidents.dialog.details.statusCode")} - {incident.statusCode ?? "N/A"} + {incident.statusCode ?? "N/A"} - {t("pages.incidents.dialog.details.downtime")} + {t("pages.incidents.dialog.details.downtime")} - {getIncidentsDuration(incident)} + {getIncidentsDuration(incident)} - {t("pages.incidents.dialog.details.message")} + {t("pages.incidents.dialog.details.message")} - {incident.message ?? "N/A"} + {incident.message ?? "N/A"} @@ -130,60 +139,53 @@ export const CardDetails = ({ incident, monitor, sx }: CardDetailsProps) => { {!incident.status && ( - + {t("pages.incidents.dialog.details.resolutionDetails")} - - + - {t("pages.incidents.dialog.details.resolvedAt")} + {t("pages.incidents.dialog.details.resolvedAt")} - + {incident.endTime ? formatDateWithTz(incident.endTime, "D MMM YYYY, h:mm A", uiTimezone) : "N/A"} - + - - {t("pages.incidents.dialog.details.resolutionType")} - + {t("pages.incidents.dialog.details.resolutionType")} - + {incident.resolutionType ? t( `pages.incidents.dialog.details.resolutionTypes.${incident.resolutionType}` ) : "N/A"} - + {incident.resolvedBy && ( <> - - {t("pages.incidents.dialog.details.resolvedBy")} - + {t("pages.incidents.dialog.details.resolvedBy")} - - {incident.resolvedByEmail ?? incident.resolvedBy} - + {incident.resolvedByEmail ?? incident.resolvedBy} )} {incident.comment && ( <> - {t("pages.incidents.dialog.details.comment")} + {t("pages.incidents.dialog.details.comment")} - {incident.comment} + {incident.comment} )} diff --git a/client/src/Pages/Incidents/Components/CardSummary.tsx b/client/src/Pages/Incidents/Components/CardSummary.tsx index 938455808..ae75f5f37 100644 --- a/client/src/Pages/Incidents/Components/CardSummary.tsx +++ b/client/src/Pages/Incidents/Components/CardSummary.tsx @@ -1,8 +1,7 @@ import Stack from "@mui/material/Stack"; import Typography from "@mui/material/Typography"; -import Divider from "@mui/material/Divider"; import Grid from "@mui/material/Grid"; -import { BaseBox, ValueLabel } from "@/Components/design-elements"; +import { BaseBox, Icon, ValueLabel } from "@/Components/design-elements"; import { CircleCheck, TriangleAlert, Bell, Wrench, Globe } from "lucide-react"; import Box from "@mui/material/Box"; @@ -25,6 +24,7 @@ const SummaryItem = ({ icon, label, value }: SummaryItemProps) => { alignItems="center" justifyContent="space-between" gap={theme.spacing(2)} + minHeight={32} > { gap={theme.spacing(2)} > {icon} - {label} + {label} {value} @@ -67,15 +67,11 @@ export const SummaryCard = ({ > {title} - {children} @@ -97,10 +93,13 @@ export const SummaryCardActiveIncidents = ({ const activeCount = summary.totalActive; const hasActive = activeCount > 0; const color = hasActive ? theme.palette.error.main : theme.palette.success.main; - const icon = hasActive ? ( - - ) : ( - + const icon = ( + + + ); const msg = t("pages.incidents.summaryCard.activeIncidents.active", { count: activeCount, @@ -133,10 +132,7 @@ const SummaryIncidentItem = ({ incident }: { incident: IncidentSummaryItem }) => container alignItems="center" spacing={2} - sx={{ - width: "100%", - py: theme.spacing(0.5), - }} + sx={{ width: "100%", minHeight: 32 }} > gap: theme.spacing(2), }} > - + size={{ xs: 12, md: 6, lg: 4 }} sx={{ textAlign: { xs: "left", md: "right" }, - fontWeight: 500, + fontWeight: 600, }} > {duration} @@ -190,22 +184,17 @@ export const SummaryCardLatestIncidents = ({ summary, }: SummaryCardLatestIncidentsProps) => { const { t } = useTranslation(); - const theme = useTheme(); const latestIncidents = summary?.latestIncidents ?? []; return ( - - {latestIncidents.slice(0, 3).map((incident, index) => ( - - - {index < latestIncidents.length - 1 && ( - - )} - - ))} - + {latestIncidents.slice(0, 3).map((incident) => ( + + ))} ); }; @@ -224,17 +213,17 @@ export const SummaryCardStats = ({ summary }: SummaryCardStatsProps) => { return ( } + icon={} label={t("pages.incidents.summaryCard.incidentStats.totalIncidents")} value={summary?.total || 0} /> } + icon={} label={t("pages.incidents.summaryCard.incidentStats.mostAffectedMonitor")} value={mostAffected} /> } + icon={} label={t("pages.incidents.summaryCard.incidentStats.avgResolutionTime")} value={ summary.total > 0 diff --git a/client/src/Pages/Incidents/Components/ControlsIncidentFilter.tsx b/client/src/Pages/Incidents/Components/ControlsIncidentFilter.tsx index a0f4eb15a..af7cba105 100644 --- a/client/src/Pages/Incidents/Components/ControlsIncidentFilter.tsx +++ b/client/src/Pages/Incidents/Components/ControlsIncidentFilter.tsx @@ -75,7 +75,7 @@ export const ControlsIncidentFilter = ({ variant="contained" onClick={onClearFilters} > - {t("pages.incidents.filters.clearFilters")} + {t("common.buttons.clearFilters")} )} diff --git a/client/src/Pages/Incidents/index.tsx b/client/src/Pages/Incidents/index.tsx index 84c414b26..a0a7e04d8 100644 --- a/client/src/Pages/Incidents/index.tsx +++ b/client/src/Pages/Incidents/index.tsx @@ -15,6 +15,7 @@ import { HeaderTimeRange } from "@/Components/common"; import { ControlsIncidentFilter } from "@/Pages/Incidents/Components/ControlsIncidentFilter"; import { useGet } from "@/Hooks/UseApi"; +import { LAYOUT } from "@/Utils/Theme/constants"; import { useState, useEffect, useMemo } from "react"; import { useParams } from "react-router-dom"; import type { Incident, IncidentsResponse, IncidentSummary } from "@/Types/Incident"; @@ -186,8 +187,9 @@ const IncidentsPage = () => { {activeIncidentsCount > 0 && ( <> {t("pages.incidents.table.activeIncidents")} @@ -208,8 +210,9 @@ const IncidentsPage = () => { )} {t("pages.incidents.table.resolvedIncidents")}