diff --git a/web/src/features/dashboard/DashboardPage.tsx b/web/src/features/dashboard/DashboardPage.tsx index d25c06c..740d74e 100644 --- a/web/src/features/dashboard/DashboardPage.tsx +++ b/web/src/features/dashboard/DashboardPage.tsx @@ -1,9 +1,11 @@ import { useState } from "react"; import { keepPreviousData, useQuery } from "@tanstack/react-query"; +import * as stylex from "@stylexjs/stylex"; import { healthQuery, statsQuery, timeseriesQuery, upstreamHealthQuery } from "@/lib/queries"; import type { Period } from "@/lib/types"; import InlineError from "@/lib/InlineError"; -import { focusRing } from "@/ui/classes"; +import { styles as shared } from "@/ui/styles"; +import { colors } from "@/ui/tokens.stylex"; import DiskCard from "./DiskCard"; import HealthBanners from "./HealthBanners"; import StatCards from "./StatCards"; @@ -12,20 +14,98 @@ import UpstreamHealthTable from "./UpstreamHealthTable"; const PERIODS: Period[] = ["1h", "24h", "7d", "30d"]; +const styles = stylex.create({ + page: { + display: "flex", + flexDirection: "column", + gap: "1rem", + }, + titleRow: { + display: "flex", + flexWrap: "wrap", + alignItems: "center", + justifyContent: "space-between", + gap: "0.75rem", + }, + heading: { + fontSize: "1.5rem", + lineHeight: "2rem", + fontWeight: 600, + }, + periodGroup: { + display: "flex", + gap: "0.25rem", + }, + period: { + borderStyle: "none", + borderRadius: "0.25rem", + paddingInline: "0.625rem", + paddingBlock: "0.25rem", + fontSize: "0.875rem", + lineHeight: "1.25rem", + }, + /** The pressed fill is heavier than `surfaceHover`, so a hover cannot mimic it. */ + periodSelected: { + backgroundColor: { + default: "oklch(92% 0.004 286.32)", + "@media (prefers-color-scheme: dark)": "oklch(37% 0.013 285.805)", + }, + color: colors.text, + fontWeight: 500, + }, + periodIdle: { + backgroundColor: { default: "transparent", ":hover": colors.surfaceHover }, + color: colors.textMuted, + }, + /** Dynamic: the caller sizes the placeholder to the widget it stands in for. */ + skeletonHeight: (height: number) => ({ height }), + skeleton: { + borderRadius: "0.25rem", + backgroundColor: { + default: "oklch(92% 0.004 286.32)", + "@media (prefers-color-scheme: dark)": "oklch(27.4% 0.006 286.033)", + }, + }, + /** The chart takes two thirds beside the disk card from `lg`, one column below. */ + panelGrid: { + display: "grid", + gap: "1rem", + gridTemplateColumns: { + default: "repeat(1, minmax(0, 1fr))", + "@media (min-width: 1024px)": "2fr 1fr", + }, + }, + panel: { + borderRadius: "0.25rem", + borderWidth: 1, + borderStyle: "solid", + borderColor: colors.border, + backgroundColor: colors.surfaceRaised, + paddingInline: "1rem", + paddingBlock: "0.75rem", + }, + panelHeading: { + marginBottom: "0.75rem", + fontSize: "0.875rem", + lineHeight: "1.25rem", + fontWeight: 600, + }, +}); + function PeriodPicker({ period, onChange }: { period: Period; onChange: (period: Period) => void }) { return ( -
+
{PERIODS.map((option) => ( @@ -35,7 +115,7 @@ function PeriodPicker({ period, onChange }: { period: Period; onChange: (period: } function Skeleton({ height }: { height: number }) { - return