refactor(telemetry): text-only list empty states, distinct p50/p95 series

- paginated-list empty prop is a plain string, no icon block
- second sparkline series drawn in dimmed color; area disabled on dual charts
- duration legend shows latest p50/p95 values
This commit is contained in:
2026-08-25 22:38:45 -07:00
parent fd0489a22f
commit 5d7747839c
9 changed files with 145 additions and 142 deletions
@@ -1,7 +1,7 @@
import { useState, useMemo } from "react";
import { Trans, Plural, useLingui } from "@lingui/react/macro";
import { Alert, Code, Container, Group, Stack, Text } from "@mantine/core";
import { CheckIcon, XIcon, PulseIcon } from "@phosphor-icons/react";
import { CheckIcon, XIcon } from "@phosphor-icons/react";
import { Activity, ActivitySearchParams } from "../types";
import { useActivities } from "../queries";
import { usePlayers } from "@/features/players/queries";
@@ -129,7 +129,7 @@ export const ActivitiesTable = () => {
<PaginatedList
items={items}
keyOf={(activity) => activity.id}
empty={{ icon: <PulseIcon size={32} />, title: t`No Activities Found` }}
empty={t`No Activities Found`}
page={page}
totalPages={result.totalPages}
onPageChange={setPage}
@@ -17,6 +17,7 @@ interface SparklineProps {
showArea?: boolean;
label?: string;
color?: string;
series2Color?: string;
scale?: SparklineScale;
}
@@ -27,6 +28,7 @@ export const Sparkline = ({
showArea = false,
label,
color = "var(--mantine-color-anchor)",
series2Color = "var(--mantine-color-dimmed)",
scale,
}: SparklineProps) => {
if (data.length === 0) {
@@ -42,7 +44,7 @@ export const Sparkline = ({
const secondPath = series2?.length
? pointsToPath(series2, VIEW_WIDTH, height, PAD, extent)
: null;
const areaPath = showArea
const areaPath = showArea && !secondPath
? `${path} L${VIEW_WIDTH - PAD},${height - PAD} L${PAD},${height - PAD} Z`
: null;
@@ -74,7 +76,7 @@ export const Sparkline = ({
<path
d={secondPath}
fill="none"
stroke={color}
stroke={series2Color}
strokeWidth={2}
strokeDasharray="4 3"
strokeLinecap="round"
@@ -1,7 +1,6 @@
import { useState, useMemo } from "react";
import { Trans, Plural, useLingui } from "@lingui/react/macro";
import { Code, Container, Stack } from "@mantine/core";
import { CursorClickIcon } from "@phosphor-icons/react";
import { usePlayers } from "@/features/players/queries";
import { useSheet } from "@/hooks/use-sheet";
import { useClientEvents } from "../queries";
@@ -91,7 +90,7 @@ export const ClientEventsTable = () => {
<PaginatedList
items={result.items}
keyOf={(event) => event.id}
empty={{ icon: <CursorClickIcon size={32} />, title: t`No Events Found` }}
empty={t`No Events Found`}
page={page}
totalPages={result.totalPages}
onPageChange={setPage}
@@ -1,12 +1,11 @@
import { ReactNode } from "react";
import { Box, Divider, Group, Pagination, Stack } from "@mantine/core";
import EmptyState from "@/components/empty-state";
import { Box, Divider, Group, Pagination, Stack, Text } from "@mantine/core";
interface PaginatedListProps<T> {
items: T[];
renderItem: (item: T) => ReactNode;
keyOf: (item: T) => string;
empty: { icon: ReactNode; title: string; description?: string };
empty: string;
page?: number;
totalPages?: number;
onPageChange?: (page: number) => void;
@@ -32,7 +31,9 @@ export const PaginatedList = <T,>({
</Stack>
{items.length === 0 && (
<EmptyState icon={empty.icon} title={empty.title} description={empty.description} />
<Text size="sm" c="dimmed" px="md" py="xl" ta="center">
{empty}
</Text>
)}
{totalPages > 1 && onPageChange && (
@@ -77,6 +77,8 @@ const FnDurationDetail = ({ fn, from, to }: { fn: string; from: string; to: stri
const days = listDays({ from, to });
const p50 = fillDailySeries(rows, "server_fn.duration.p50", fn, days);
const p95 = fillDailySeries(rows, "server_fn.duration.p95", fn, days);
const lastNonZero = (series: number[]) =>
[...series].reverse().find((value) => value > 0) ?? 0;
return (
<Stack gap="xs">
@@ -84,7 +86,6 @@ const FnDurationDetail = ({ fn, from, to }: { fn: string; from: string; to: stri
data={p50}
series2={p95}
height={64}
showArea
scale={{
start: dayLabel(i18n, from),
end: dayLabel(i18n, to),
@@ -97,7 +98,7 @@ const FnDurationDetail = ({ fn, from, to }: { fn: string; from: string; to: stri
<line x1={0} y1={4} x2={18} y2={4} stroke="var(--mantine-color-anchor)" strokeWidth={2} />
</svg>
<Text size="xs" c="dimmed">
<Trans>p50</Trans>
<Trans>p50</Trans> · {Math.round(lastNonZero(p50))}ms
</Text>
</Group>
<Group gap={6}>
@@ -107,13 +108,13 @@ const FnDurationDetail = ({ fn, from, to }: { fn: string; from: string; to: stri
y1={4}
x2={18}
y2={4}
stroke="var(--mantine-color-anchor)"
stroke="var(--mantine-color-dimmed)"
strokeWidth={2}
strokeDasharray="4 3"
/>
</svg>
<Text size="xs" c="dimmed">
<Trans>p95</Trans>
<Trans>p95</Trans> · {Math.round(lastNonZero(p95))}ms
</Text>
</Group>
</Group>