diff --git a/client/src/Pages/StatusPage/Status/index.tsx b/client/src/Pages/StatusPage/Status/index.tsx index 5ccc5f44c..3889adb85 100644 --- a/client/src/Pages/StatusPage/Status/index.tsx +++ b/client/src/Pages/StatusPage/Status/index.tsx @@ -38,6 +38,7 @@ import { BoldHero } from "@/Pages/StatusPage/Status/themes/bold/BoldHero"; import { editorialStyles } from "@/Pages/StatusPage/Status/themes/editorial/styles"; import { EditorialHeader } from "@/Pages/StatusPage/Status/themes/editorial/EditorialHeader"; import { EditorialHero } from "@/Pages/StatusPage/Status/themes/editorial/EditorialHero"; +import { minimalStyles } from "@/Pages/StatusPage/Status/themes/minimal/styles"; const THEME_CONFIGS: Record> = { refined: { @@ -63,6 +64,11 @@ const THEME_CONFIGS: Record> = { HeroSlot: EditorialHero, overallStatusOptions: { allUpKey: "pages.statusPages.editorial.allUp" }, }, + minimal: { + createStyles: minimalStyles, + HeaderSlot: RefinedHeader, + HeroSlot: RefinedHero, + }, }; const StatusPageView = () => { diff --git a/client/src/Pages/StatusPage/Status/themes/minimal/styles.ts b/client/src/Pages/StatusPage/Status/themes/minimal/styles.ts new file mode 100644 index 000000000..27370c0ad --- /dev/null +++ b/client/src/Pages/StatusPage/Status/themes/minimal/styles.ts @@ -0,0 +1,66 @@ +import type { SxProps, Theme } from "@mui/material/styles"; +import type { StatusPageThemeTokens } from "../tokens"; +import type { OverallTone } from "../shared/overallStatus"; +import { refinedStyles, type RefinedStyles } from "../refined/styles"; + +type FlatSx = Exclude, readonly unknown[] | ((theme: Theme) => unknown)>; + +const extend = (base: SxProps, overrides: SxProps): SxProps => [ + base as FlatSx, + overrides as FlatSx, +]; + +export const minimalStyles = ( + tokens: StatusPageThemeTokens, + isDark: boolean +): RefinedStyles => { + const base = refinedStyles(tokens, isDark); + + return { + ...base, + page: extend(base.page, { + maxWidth: 820, + p: { xs: "32px 16px 64px", md: "48px 20px 72px" }, + }), + top: extend(base.top, { + mb: "44px", + pb: "16px", + borderBottom: `1px solid ${tokens.border}`, + }), + logoMono: extend(base.logoMono, { + borderRadius: "50%", + background: tokens.text, + }), + hero: extend(base.hero, { + alignItems: "center", + background: "transparent", + border: 0, + boxShadow: "none", + p: 0, + mb: "40px", + }), + heroRow: extend(base.heroRow, { justifyContent: "center" }), + heroTitle: extend(base.heroTitle, { + flex: "initial", + fontSize: { xs: 22, md: 28 }, + fontWeight: 650, + textAlign: "center", + }), + heroIcon: (_tone: OverallTone) => ({ display: "none" }), + heroSub: extend(base.heroSub, { textAlign: "center", mt: "4px" }), + chartSwitch: extend(base.chartSwitch, { borderRadius: tokens.radius }), + card: extend(base.card, { + boxShadow: "none", + transition: "none", + "&:hover": { transform: "none", boxShadow: "none" }, + }), + cardRow: extend(base.cardRow, { p: "14px 16px" }), + badge: (tone) => + extend(base.badge(tone), { + background: "transparent", + p: 0, + }), + gauge: extend(base.gauge, { borderRadius: tokens.radius }), + footer: extend(base.footer, { mt: "48px", fontSize: 11 }), + }; +}; diff --git a/client/src/Pages/StatusPage/Status/themes/tokens.ts b/client/src/Pages/StatusPage/Status/themes/tokens.ts index f84b6f100..fdb251c07 100644 --- a/client/src/Pages/StatusPage/Status/themes/tokens.ts +++ b/client/src/Pages/StatusPage/Status/themes/tokens.ts @@ -191,9 +191,47 @@ const editorial: ThemeVariants = { }, }; +const minimal: ThemeVariants = { + light: { + bg: "#ffffff", + surface: "#ffffff", + border: "#dfe3e8", + text: "#17191c", + textMuted: "#667085", + up: "#12a174", + upStrong: "#087a57", + upSoft: "#e7f7f1", + degraded: "#b54708", + degradedSoft: "#fff1dc", + down: "#c4323f", + downSoft: "#fde8ea", + warn: "#c27803", + warnSoft: "#fff3d6", + radius: "6px", + }, + dark: { + bg: "#0d0f12", + surface: "#111419", + border: "#2b3038", + text: "#f2f4f7", + textMuted: "#98a2b3", + up: "#32d6a0", + upStrong: "#1eb783", + upSoft: "rgba(50,214,160,0.14)", + degraded: "#f0a44b", + degradedSoft: "rgba(240,164,75,0.16)", + down: "#ff6675", + downSoft: "rgba(255,102,117,0.16)", + warn: "#f2b84b", + warnSoft: "rgba(242,184,75,0.16)", + radius: "6px", + }, +}; + export const themeTokens: Record = { refined, modern, bold, editorial, + minimal, }; diff --git a/client/src/Types/StatusPage.ts b/client/src/Types/StatusPage.ts index 822ab7345..bbe1f41f2 100644 --- a/client/src/Types/StatusPage.ts +++ b/client/src/Types/StatusPage.ts @@ -21,7 +21,13 @@ export const getMonitorTypeLabel = ( return key ? t(key) : type; }; -export const STATUS_PAGE_THEMES = ["refined", "modern", "bold", "editorial"] as const; +export const STATUS_PAGE_THEMES = [ + "refined", + "modern", + "bold", + "editorial", + "minimal", +] as const; export type StatusPageTheme = (typeof STATUS_PAGE_THEMES)[number]; export const DEFAULT_STATUS_PAGE_THEME: StatusPageTheme = "refined"; diff --git a/client/src/locales/en.json b/client/src/locales/en.json index e4bbc0f69..f62679b4a 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -1585,6 +1585,10 @@ "editorial": { "name": "Editorial", "description": "Serif headings and hairline dividers. Distinctive and calm." + }, + "minimal": { + "name": "Minimal", + "description": "Flat, focused, and compact with only the essentials." } } }, diff --git a/server/src/domain/status-pages/status-page.type.ts b/server/src/domain/status-pages/status-page.type.ts index db08b7398..254a411e1 100644 --- a/server/src/domain/status-pages/status-page.type.ts +++ b/server/src/domain/status-pages/status-page.type.ts @@ -1,7 +1,7 @@ export const StatusPageTypes = ["uptime", "infrastructure"] as const; export type StatusPageType = (typeof StatusPageTypes)[number]; -export const StatusPageThemes = ["refined", "modern", "bold", "editorial"] as const; +export const StatusPageThemes = ["refined", "modern", "bold", "editorial", "minimal"] as const; export type StatusPageTheme = (typeof StatusPageThemes)[number]; export const DEFAULT_STATUS_PAGE_THEME: StatusPageTheme = "refined";