milestone 23 s3: convert features/dashboard/StatCards.tsx to stylex

This commit is contained in:
2026-08-12 22:23:16 +02:00
parent 0fdbe25f7a
commit 9e12683acf
4 changed files with 54 additions and 15 deletions
@@ -69,9 +69,6 @@ const styles = stylex.create({
textOverflow: "ellipsis",
whiteSpace: "nowrap",
},
numeric: {
fontVariantNumeric: "tabular-nums",
},
actions: {
display: "flex",
gap: "0.75rem",
@@ -186,9 +183,9 @@ export default function BlocklistsPage() {
{...stylex.props(shared.focusRing)}
/>
</td>
<td {...stylex.props(shared.td, styles.numeric)}>{b.domain_count}</td>
<td {...stylex.props(shared.td, styles.numeric)}>{b.wildcard_count}</td>
<td {...stylex.props(shared.td, styles.numeric)}>{b.skipped_regex_count}</td>
<td {...stylex.props(shared.td, shared.tabularNums)}>{b.domain_count}</td>
<td {...stylex.props(shared.td, shared.tabularNums)}>{b.wildcard_count}</td>
<td {...stylex.props(shared.td, shared.tabularNums)}>{b.skipped_regex_count}</td>
<td {...stylex.props(shared.td)}>
{b.last_updated === null ? "never" : formatTime(b.last_updated)}
</td>
+46 -5
View File
@@ -1,8 +1,49 @@
import * as stylex from "@stylexjs/stylex";
import { formatMicros } from "@/lib/format";
import type { StatsTotals } from "@/lib/types";
import { styles as shared } from "@/ui/styles";
import { colors } from "@/ui/tokens.stylex";
const numberFormat = new Intl.NumberFormat();
const styles = stylex.create({
/** Two columns on a phone, three from `md`, five from `xl`, as before. */
grid: {
display: "grid",
gap: "0.75rem",
gridTemplateColumns: {
default: "repeat(2, minmax(0, 1fr))",
"@media (min-width: 768px)": "repeat(3, minmax(0, 1fr))",
"@media (min-width: 1280px)": "repeat(5, minmax(0, 1fr))",
},
},
card: {
borderRadius: "0.25rem",
borderWidth: 1,
borderStyle: "solid",
borderColor: colors.border,
backgroundColor: colors.surfaceRaised,
paddingInline: "1rem",
paddingBlock: "0.75rem",
},
label: {
fontSize: "0.875rem",
lineHeight: "1.25rem",
color: colors.textMuted,
},
value: {
fontSize: "1.5rem",
lineHeight: "2rem",
fontWeight: 600,
},
detail: {
marginLeft: "0.5rem",
fontSize: "0.875rem",
lineHeight: "1.25rem",
color: colors.textMuted,
},
});
function percentOf(part: number, total: number): string | null {
if (total === 0) return null;
return `${((part / total) * 100).toFixed(1)}%`;
@@ -10,11 +51,11 @@ function percentOf(part: number, total: number): string | null {
function Card({ label, value, detail }: { label: string; value: string; detail?: string | null }) {
return (
<div className="rounded border border-zinc-200 bg-white px-4 py-3 dark:border-zinc-800 dark:bg-zinc-900">
<dt className="text-sm text-zinc-500">{label}</dt>
<div {...stylex.props(styles.card)}>
<dt {...stylex.props(styles.label)}>{label}</dt>
<dd>
<span className="text-2xl font-semibold tabular-nums">{value}</span>
{detail != null && <span className="ml-2 text-sm text-zinc-500 tabular-nums">{detail}</span>}
<span {...stylex.props(styles.value, shared.tabularNums)}>{value}</span>
{detail != null && <span {...stylex.props(styles.detail, shared.tabularNums)}>{detail}</span>}
</dd>
</div>
);
@@ -22,7 +63,7 @@ function Card({ label, value, detail }: { label: string; value: string; detail?:
export default function StatCards({ stats }: { stats: StatsTotals }) {
return (
<dl className="grid grid-cols-2 gap-3 md:grid-cols-3 xl:grid-cols-5">
<dl {...stylex.props(styles.grid)}>
<Card label="Queries" value={numberFormat.format(stats.queries)} />
<Card
label="Blocked"
+1 -4
View File
@@ -43,9 +43,6 @@ const styles = stylex.create({
whiteSpace: "nowrap",
fontWeight: 500,
},
numeric: {
fontVariantNumeric: "tabular-nums",
},
actions: {
display: "flex",
gap: "0.75rem",
@@ -128,7 +125,7 @@ export default function UpstreamsPage() {
{u.url}
</span>
</td>
<td {...stylex.props(shared.td, styles.numeric)}>{u.priority}</td>
<td {...stylex.props(shared.td, shared.tabularNums)}>{u.priority}</td>
<td {...stylex.props(shared.td)}>
<input
type="checkbox"
+4
View File
@@ -151,6 +151,10 @@ export const styles = stylex.create({
color: colors.dangerText,
},
/** Digits of equal width, so a column of counts does not jitter as it updates. */
tabularNums: {
fontVariantNumeric: "tabular-nums",
},
/** For a value the operator reads character by character: a domain, an IP, a URL. */
mono: {
fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",