milestone 23 s3: convert features/blocklists/SourceStatusSection.tsx to stylex
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
|
import * as stylex from "@stylexjs/stylex";
|
||||||
import { formatTime } from "@/lib/format";
|
import { formatTime } from "@/lib/format";
|
||||||
import type { SourceStatus } from "@/lib/types";
|
import type { SourceStatus } from "@/lib/types";
|
||||||
import { tdClass, thClass } from "@/ui/classes";
|
import { styles as shared } from "@/ui/styles";
|
||||||
|
import { colors } from "@/ui/tokens.stylex";
|
||||||
|
|
||||||
function formatAttempt(unixSeconds: number): string {
|
function formatAttempt(unixSeconds: number): string {
|
||||||
return unixSeconds === 0 ? "never" : formatTime(unixSeconds);
|
return unixSeconds === 0 ? "never" : formatTime(unixSeconds);
|
||||||
@@ -11,61 +13,108 @@ interface SourceStatusSectionProps {
|
|||||||
namesById: ReadonlyMap<number, string>;
|
namesById: ReadonlyMap<number, string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const styles = stylex.create({
|
||||||
|
section: {
|
||||||
|
marginTop: "2rem",
|
||||||
|
},
|
||||||
|
heading: {
|
||||||
|
fontSize: "1.125rem",
|
||||||
|
lineHeight: "1.75rem",
|
||||||
|
fontWeight: 500,
|
||||||
|
},
|
||||||
|
note: {
|
||||||
|
marginTop: "0.5rem",
|
||||||
|
color: colors.textMuted,
|
||||||
|
},
|
||||||
|
tableWrap: {
|
||||||
|
marginTop: "0.5rem",
|
||||||
|
overflowX: "auto",
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
width: "100%",
|
||||||
|
minWidth: "max-content",
|
||||||
|
borderCollapse: "collapse",
|
||||||
|
fontSize: "0.875rem",
|
||||||
|
lineHeight: "1.25rem",
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
fontWeight: 500,
|
||||||
|
},
|
||||||
|
url: {
|
||||||
|
marginTop: "0.125rem",
|
||||||
|
display: "block",
|
||||||
|
maxWidth: "16rem",
|
||||||
|
overflow: "hidden",
|
||||||
|
textOverflow: "ellipsis",
|
||||||
|
whiteSpace: "nowrap",
|
||||||
|
fontSize: "0.75rem",
|
||||||
|
lineHeight: "1rem",
|
||||||
|
color: colors.textMuted,
|
||||||
|
},
|
||||||
|
/** Green has no token: a loaded source is the only success state in the app. */
|
||||||
|
loaded: {
|
||||||
|
color: {
|
||||||
|
default: "oklch(52.7% 0.154 150.069)",
|
||||||
|
"@media (prefers-color-scheme: dark)": "oklch(79.2% 0.209 151.711)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
failed: {
|
||||||
|
color: colors.danger,
|
||||||
|
},
|
||||||
|
absent: {
|
||||||
|
color: colors.textMuted,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export default function SourceStatusSection({ sources, namesById }: SourceStatusSectionProps) {
|
export default function SourceStatusSection({ sources, namesById }: SourceStatusSectionProps) {
|
||||||
return (
|
return (
|
||||||
<section className="mt-8">
|
<section {...stylex.props(styles.section)}>
|
||||||
<h2 className="text-lg font-medium">Source status</h2>
|
<h2 {...stylex.props(styles.heading)}>Source status</h2>
|
||||||
{sources === null ? (
|
{sources === null ? (
|
||||||
<p className="mt-2 text-zinc-500">
|
<p {...stylex.props(styles.note)}>
|
||||||
No status snapshot yet — run “Update now” to fetch status for every enabled source.
|
No status snapshot yet — run “Update now” to fetch status for every enabled source.
|
||||||
</p>
|
</p>
|
||||||
) : sources.length === 0 ? (
|
) : sources.length === 0 ? (
|
||||||
<p className="mt-2 text-zinc-500">The last update ran against no enabled sources.</p>
|
<p {...stylex.props(styles.note)}>The last update ran against no enabled sources.</p>
|
||||||
) : (
|
) : (
|
||||||
<div className="mt-2 overflow-x-auto">
|
<div {...stylex.props(styles.tableWrap)}>
|
||||||
<table className="w-full min-w-max border-collapse text-sm">
|
<table {...stylex.props(styles.table)}>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th className={thClass}>Source</th>
|
<th {...stylex.props(shared.th)}>Source</th>
|
||||||
<th className={thClass}>State</th>
|
<th {...stylex.props(shared.th)}>State</th>
|
||||||
<th className={thClass}>Last attempt</th>
|
<th {...stylex.props(shared.th)}>Last attempt</th>
|
||||||
<th className={thClass}>Last success</th>
|
<th {...stylex.props(shared.th)}>Last success</th>
|
||||||
<th className={thClass}>Domains</th>
|
<th {...stylex.props(shared.th)}>Domains</th>
|
||||||
<th className={thClass}>Wildcards</th>
|
<th {...stylex.props(shared.th)}>Wildcards</th>
|
||||||
<th className={thClass}>Skipped regex</th>
|
<th {...stylex.props(shared.th)}>Skipped regex</th>
|
||||||
<th className={thClass}>Last error</th>
|
<th {...stylex.props(shared.th)}>Last error</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{sources.map((source) => (
|
{sources.map((source) => (
|
||||||
<tr key={source.id}>
|
<tr key={source.id}>
|
||||||
<td className={tdClass}>
|
<td {...stylex.props(shared.td)}>
|
||||||
<span className="font-medium">{namesById.get(source.id) ?? source.url}</span>
|
<span {...stylex.props(styles.name)}>
|
||||||
<span className="mt-0.5 block max-w-64 truncate text-xs text-zinc-500">
|
{namesById.get(source.id) ?? source.url}
|
||||||
{source.url}
|
|
||||||
</span>
|
</span>
|
||||||
|
<span {...stylex.props(styles.url)}>{source.url}</span>
|
||||||
</td>
|
</td>
|
||||||
<td className={tdClass}>
|
<td {...stylex.props(shared.td)}>
|
||||||
<span
|
<span {...stylex.props(source.loaded ? styles.loaded : styles.failed)}>
|
||||||
className={
|
|
||||||
source.loaded
|
|
||||||
? "text-green-700 dark:text-green-400"
|
|
||||||
: "text-red-600 dark:text-red-400"
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{source.state}
|
{source.state}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td className={tdClass}>{formatAttempt(source.last_attempt)}</td>
|
<td {...stylex.props(shared.td)}>{formatAttempt(source.last_attempt)}</td>
|
||||||
<td className={tdClass}>{formatAttempt(source.last_success)}</td>
|
<td {...stylex.props(shared.td)}>{formatAttempt(source.last_success)}</td>
|
||||||
<td className={`${tdClass} tabular-nums`}>{source.domains}</td>
|
<td {...stylex.props(shared.td, shared.tabularNums)}>{source.domains}</td>
|
||||||
<td className={`${tdClass} tabular-nums`}>{source.wildcards}</td>
|
<td {...stylex.props(shared.td, shared.tabularNums)}>{source.wildcards}</td>
|
||||||
<td className={`${tdClass} tabular-nums`}>{source.skipped_regex}</td>
|
<td {...stylex.props(shared.td, shared.tabularNums)}>{source.skipped_regex}</td>
|
||||||
<td className={tdClass}>
|
<td {...stylex.props(shared.td)}>
|
||||||
{source.last_error === "" ? (
|
{source.last_error === "" ? (
|
||||||
<span className="text-zinc-400">—</span>
|
<span {...stylex.props(styles.absent)}>—</span>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-red-600 dark:text-red-400">{source.last_error}</span>
|
<span {...stylex.props(styles.failed)}>{source.last_error}</span>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user