import * as stylex from "@stylexjs/stylex"; import { colors, metrics } from "@/ui/tokens.stylex"; import { useAuthority, type Authority } from "./authority"; const styles = stylex.create({ row: { display: "inline-flex", alignItems: "baseline", flexWrap: "wrap", gap: "0.375rem", }, /** The sentence is secondary to the word, and wraps rather than stretching a row. */ reason: { fontSize: "0.75rem", lineHeight: "1rem", color: colors.textMuted, }, tag: { marginLeft: "0.5rem", borderWidth: 1, borderStyle: "solid", borderColor: colors.border, borderRadius: metrics.radius, paddingInline: "0.375rem", paddingBlock: "0.125rem", fontSize: "0.75rem", lineHeight: "1rem", color: colors.textMuted, }, }); /** * The compact lock, for a configuration control that survives outside a * configuration page — the Clients page edits a group assignment the file may * own. The configuration pages themselves do not use it: they change rendering * rather than annotate a control they left up. * * The word is real text, not colour or an icon, so a screen reader announces * the reason the control will not answer. */ /** * Why a configuration control will not answer. Exported because a page that * shows the compact tag has to print this sentence itself, once, somewhere the * tag can point at. */ export function lockReason(authority: Authority): string { if (authority.state === "pending") return "Checking which configuration source this server obeys"; if (authority.state === "failed") return "Configuration status unavailable, so edits are held back"; return `Managed by ${authority.status.path ?? "the configuration file"}; edit the file and restart nxdns`; } export default function ConfigLockIndicator({ compact = false }: { compact?: boolean }) { const authority = useAuthority(); if (authority.state === "resolved" && authority.status.authority === "database") return null; const reason = lockReason(authority); // A compact caller has no room for the sentence and must print it once // nearby instead: the Clients table would otherwise repeat it down every row. if (compact) return Locked; // Everywhere else the reason is visible text rather than a `title` or an // `aria-label`. A tooltip reaches neither a keyboard nor a touch screen, and // screen-reader-only text is the same failure pointed the other way. return ( Locked {reason} ); }