admin: title-only information becomes visible text

the client address follows its name as visible muted text in the query tables, the config lock indicator prints its reason beside the tag except in table rows where a page-level note explains the lock instead, and the locked delete buttons describe themselves through that one visible note. the chart legend tooltip is deleted because a named client is deliberately not addressed in the chart, and the dead series address field went with it. titles that merely repeat visible copyable text stay.
This commit is contained in:
2026-08-29 13:03:30 +02:00
parent 207252acee
commit c65d92d8f8
9 changed files with 154 additions and 51 deletions
+2 -8
View File
@@ -69,8 +69,6 @@ const styles = stylex.create({
interface Series {
key: string;
label: string;
/** Kept beside the label so a renamed client is still identifiable by address. */
address: string | null;
color: string;
buckets: number[];
}
@@ -89,15 +87,11 @@ function seriesOf(data: ClientChartData, names: ClientNames): Series[] {
// the same precedence and the same lookup the query tables use. The colour
// keys on the address regardless, so naming a client never repaints it.
label: clientLabel(client.client, names)?.text ?? client.client,
address: client.client,
color: seriesColor(clientKey(client.client)),
buckets: client.buckets,
}));
if (data.other.every((count) => count === 0)) return named;
return [
...named,
{ key: OTHER_KEY, label: "Other", address: null, color: seriesColor(OTHER_KEY), buckets: data.other },
];
return [...named, { key: OTHER_KEY, label: "Other", color: seriesColor(OTHER_KEY), buckets: data.other }];
}
/**
@@ -219,7 +213,7 @@ export default function ClientChart({ data }: { data: ClientChartData }) {
)}
<ul {...stylex.props(styles.legend)}>
{series.map((one) => (
<li key={one.key} title={one.address ?? undefined} {...stylex.props(styles.legendItem)}>
<li key={one.key} {...stylex.props(styles.legendItem)}>
<span aria-hidden="true" {...stylex.props(styles.swatch, styles.swatchColor(one.color))} />
{one.label}
</li>
@@ -214,6 +214,16 @@ test("a registered client is named in the chart, an unregistered one keeps its a
await waitFor(() => expect(within(chart).getAllByText("kitchen-pi")).toHaveLength(2));
expect(within(chart).queryByText("192.0.2.30")).toBeNull();
expect(within(chart).getAllByText("192.0.2.31")).toHaveLength(2);
// Nor on hover: a pointer-only tooltip would say what the design just chose
// not to, and only to a reader holding a mouse.
const legendItem = within(chart)
.getAllByText("kitchen-pi")
.map((node) => node.closest("li"))
.find((node) => node !== null);
expect(legendItem).toBeTruthy();
expect(legendItem?.getAttribute("title")).toBeNull();
expect(within(chart).getByRole("list").querySelectorAll("[title]")).toHaveLength(0);
});
test("a client named only by reverse DNS is named by it too", async () => {