From 32e304ad3535437802cb3d7196bbbaa701555709 Mon Sep 17 00:00:00 2001 From: Theo Gravity Date: Sat, 17 Oct 2026 00:54:55 -0700 Subject: [PATCH 1/6] fix: unify dashboard facts and conditional form behavior --- .changeset/tidy-dashboard-forms.md | 6 + .../__tests__/add-node-dialog.test.tsx | 8 +- .../__tests__/backup-settings.test.tsx | 4 +- .../__tests__/network-plugin-card.test.tsx | 22 +- .../__tests__/restart-dialog.test.tsx | 2 +- .../__tests__/sharing-dialog.test.tsx | 40 +- .../src/components/auth/provider-dialog.tsx | 28 +- .../src/components/auth/providers-table.tsx | 19 +- .../components/backups/backup-workflow.tsx | 40 +- .../components/backups/create-backup-card.tsx | 10 +- .../backups/restore-backup-card.tsx | 449 ++++++++++-------- .../src/components/clone-subshell-dialog.tsx | 19 +- .../connect/__tests__/ssh-wizard.test.tsx | 10 +- .../components/connect/ssh-forward-fields.tsx | 167 ++++--- .../web/src/components/connect/ssh-wizard.tsx | 185 ++++---- .../verify-browser-key-destination.tsx | 32 +- .../components/connect/verify-destination.tsx | 21 +- .../web/src/components/device-name-card.tsx | 13 +- apps/server/web/src/components/fact-list.tsx | 19 + .../web/src/components/instance-name-card.tsx | 12 +- .../components/networking/addresses-card.tsx | 5 +- .../networking/network-addresses.tsx | 24 +- .../networking/network-settings-form.tsx | 12 +- .../src/components/nodes/node-key-setup.tsx | 31 +- .../__tests__/ssh-preset-editor.test.tsx | 2 +- .../presets/command-paste-field.tsx | 20 +- .../web/src/components/profile-card.tsx | 22 +- .../__tests__/stack-form-dialog.test.tsx | 6 +- .../components/prompts/prompt-form-dialog.tsx | 14 +- .../components/prompts/stack-form-dialog.tsx | 14 +- .../src/components/service/restart-dialog.tsx | 14 +- .../components/service/supervision-dialog.tsx | 38 +- .../src/components/sharing-dialog-core.tsx | 47 +- .../components/system-key-create-dialog.tsx | 2 +- .../web/src/components/ui/choice-fields.tsx | 13 + apps/server/web/src/components/ui/notice.tsx | 21 + .../src/components/updates/update-dialog.tsx | 25 +- apps/server/web/src/routes/nodes_.$id.tsx | 65 +-- docs/README.md | 1 + docs/design-system.md | 33 +- docs/ux-review-2026-10-17.md | 65 +++ .../node-admin/src/components/fact-list.tsx | 9 +- .../src/components/node-runtime-card.tsx | 2 +- .../src/components/ssh-trust-card.tsx | 30 +- 44 files changed, 952 insertions(+), 669 deletions(-) create mode 100644 .changeset/tidy-dashboard-forms.md create mode 100644 apps/server/web/src/components/fact-list.tsx create mode 100644 apps/server/web/src/components/ui/choice-fields.tsx create mode 100644 apps/server/web/src/components/ui/notice.tsx create mode 100644 docs/ux-review-2026-10-17.md diff --git a/.changeset/tidy-dashboard-forms.md b/.changeset/tidy-dashboard-forms.md new file mode 100644 index 000000000..2dd74d378 --- /dev/null +++ b/.changeset/tidy-dashboard-forms.md @@ -0,0 +1,6 @@ +--- +"@internal/server": patch +"@internal/node": patch +--- + +Make dashboard information easier to scan with consistent labels, readable values, and wrapping for long paths and addresses. Keep conditional fields beneath their selected radio option, disable Save for unchanged drafts, and clarify warnings and validation. Apply the shared fact styling to the node dashboard as well. diff --git a/apps/server/web/src/components/__tests__/add-node-dialog.test.tsx b/apps/server/web/src/components/__tests__/add-node-dialog.test.tsx index 6012f0564..113628f26 100644 --- a/apps/server/web/src/components/__tests__/add-node-dialog.test.tsx +++ b/apps/server/web/src/components/__tests__/add-node-dialog.test.tsx @@ -656,9 +656,9 @@ describe("AddNodeDialog", () => { // dropdown's items are in the DOM too — Base UI force-mounts them once the // trigger has focus, which is where the dialog's initial focus lands (the // old count of 2 rode the two-step never focusing the trigger — timing, not - // truth). The paste target is the CODE row, and + // truth). The paste target is the fact value, and // there is exactly one. The key shows ONCE. - expect(screen.getAllByText("https://plane.example").filter((el) => el.tagName === "CODE")).toHaveLength(1); + expect(screen.getAllByText("https://plane.example").filter((el) => el.closest("dd") !== null)).toHaveLength(1); expect(screen.getAllByText(/nsk_secret/)).toHaveLength(1); expect(screen.getByRole("button", { name: "Copy setup key" })).toBeDefined(); expect(screen.getByRole("button", { name: "Copy server address" })).toBeDefined(); @@ -716,11 +716,11 @@ describe("AddNodeDialog", () => { expect(label.compareDocumentPosition(trigger) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy(); expect(trigger.compareDocumentPosition(switchButton) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy(); - // The pick is the same value the app path's paste row carries — one CODE row + // The pick is the same value the app path's paste row carries — one fact value // (the closed dropdown holds further copies in the DOM; see the count comment // in the test above). fireEvent.click(screen.getByRole("button", { name: "Desktop App" })); - expect(screen.getAllByText("https://plane.example").filter((el) => el.tagName === "CODE")).toHaveLength(1); + expect(screen.getAllByText("https://plane.example").filter((el) => el.closest("dd") !== null)).toHaveLength(1); } finally { restore(); } diff --git a/apps/server/web/src/components/__tests__/backup-settings.test.tsx b/apps/server/web/src/components/__tests__/backup-settings.test.tsx index 0d953b88a..3ed506c61 100644 --- a/apps/server/web/src/components/__tests__/backup-settings.test.tsx +++ b/apps/server/web/src/components/__tests__/backup-settings.test.tsx @@ -159,7 +159,7 @@ describe("Settings backup workflows", () => { expect(activity.at(-1)).toBe(false); }); - it("gates encryption on shared validation and keeps gold errors beside blurred fields", async () => { + it("gates encryption and distinguishes invalid values from missing input", async () => { const requests = mockApi(); mount(); fireEvent.click(screen.getByRole("switch", { name: "Encrypt the archive with a password" })); @@ -170,7 +170,7 @@ describe("Settings backup workflows", () => { for (const input of [password, confirm]) fireEvent.change(input, { target: { value: "short" } }); fireEvent.blur(password); expect(screen.getByRole("alert").textContent).toContain("at least 8"); - expect(screen.getByRole("alert").className).toContain("text-warning"); + expect(screen.getByRole("alert").className).toContain("text-destructive"); fireEvent.focus(password); fireEvent.change(password, { target: { value: "unique archive password" } }); fireEvent.change(confirm, { target: { value: "different" } }); diff --git a/apps/server/web/src/components/__tests__/network-plugin-card.test.tsx b/apps/server/web/src/components/__tests__/network-plugin-card.test.tsx index 92844f32a..3b3c8257e 100644 --- a/apps/server/web/src/components/__tests__/network-plugin-card.test.tsx +++ b/apps/server/web/src/components/__tests__/network-plugin-card.test.tsx @@ -1163,29 +1163,20 @@ describe("NetworkPluginCard: the state matrix", () => { }); it("labels each address above its value, in the QUIET data-label grammar", async () => { - // Two defects, in order, both from the same operator's live card. First the - // tag-after-URL row (`http://… MagicDNS name`) read as two disjoint - // things, because a small muted word after a big bold URL names nothing - // until you scan back — so the label moved ABOVE the value. Then the - // grammar it moved into was the wrong one: the form label's `font-strong - // text-label` put a bold "MagicDNS name" over its URL while the `Fact` - // rows above it set a quiet "Client version" over theirs, and a card - // holding both grammars reads as two systems. These are read-only facts, so - // the label carries `Fact`'s `dt` classes — quiet colour, no weight token, - // and the body size from the LIST, exactly as the `
` supplies it. + // Facts use smaller muted labels and full-size values across cards and dialogs. await renderCard(row({ state: "joined", status: { state: "joined", addresses: ADDRESSES, hints: [] } })); - const items = screen.getAllByRole("listitem"); + const items = ADDRESSES.map((address) => screen.getByText(address.label).closest("div") as HTMLElement); const first = items[0] as HTMLElement; expect(first.children[0]?.textContent).toBe("MagicDNS name"); expect(first.children[0]?.className).toContain("text-muted-foreground"); expect(first.children[0]?.className).not.toContain("font-strong"); expect(first.children[0]?.className).not.toContain("text-label"); - // The size comes from the list so it cannot drift from the `
` beside it. - expect(first.parentElement?.className).toContain("text-sm"); + expect(first.children[0]?.className).toContain("text-detail"); + expect(first.children[1]?.className).toContain("text-body"); expect(first.children[1]?.textContent).toContain("https://box.tail1234.ts.net"); // The secure-context sentence keeps its own line below the value, and it // is still the address's own — one per address, comparative by repetition. - expect(first.children[2]?.textContent).toBe("Passkeys and secure cookies work at this address."); + expect(first.children[1]?.textContent).toContain("Passkeys and secure cookies work at this address."); const second = items[1] as HTMLElement; expect(second.children[0]?.textContent).toBe("Tailscale IP"); }); @@ -1196,7 +1187,8 @@ describe("NetworkPluginCard: the state matrix", () => { // here by scheme, by secure context or by label would make the page // contradict its own data for a reason no reader can see. await renderCard(row({ state: "joined", status: { state: "joined", addresses: ADDRESSES, hints: [] } })); - const shown = screen.getAllByRole("listitem").map((item) => item.textContent ?? ""); + const list = screen.getByText(ADDRESSES[0]!.label).closest("dl")!; + const shown = Array.from(list.children, (item) => item.textContent ?? ""); expect(shown[0]).toContain("https://box.tail1234.ts.net"); expect(shown[1]).toContain("http://100.64.0.1:3080"); }); diff --git a/apps/server/web/src/components/__tests__/restart-dialog.test.tsx b/apps/server/web/src/components/__tests__/restart-dialog.test.tsx index ef688e9fd..7971a85f4 100644 --- a/apps/server/web/src/components/__tests__/restart-dialog.test.tsx +++ b/apps/server/web/src/components/__tests__/restart-dialog.test.tsx @@ -46,6 +46,6 @@ describe("RestartDialog pane safety", () => { // Absence of evidence is not evidence of safety: a definition that could // not be read gets the same refusal as one known to be lethal. open({ installed: true, paneSafety: "unknown" }); - expect(screen.getByText(/close every running subshell/)).toBeTruthy(); + expect(screen.getByText(/Restarting may close them/)).toBeTruthy(); }); }); diff --git a/apps/server/web/src/components/__tests__/sharing-dialog.test.tsx b/apps/server/web/src/components/__tests__/sharing-dialog.test.tsx index 9977bf7cf..52a6514f8 100644 --- a/apps/server/web/src/components/__tests__/sharing-dialog.test.tsx +++ b/apps/server/web/src/components/__tests__/sharing-dialog.test.tsx @@ -59,7 +59,40 @@ describe("SharingDialog", () => { // The grant row renders (Everyone, one Remove control); the add-row // picker omits Everyone since it's already shared. expect(await screen.findByText("Everyone")).toBeDefined(); - expect(screen.getByRole("button", { name: "Remove" })).toBeDefined(); + expect(screen.getByRole("button", { name: /^Remove access for/ })).toBeDefined(); + } finally { + restore(); + } + }); + + it("disables Save until access changes and disables it again when changes are undone", async () => { + const { calls, restore } = mockFetch([{ granteeUserId: null, permission: "view" }]); + try { + renderDialog(); + await screen.findByText("Everyone"); + const save = () => screen.getByRole("button", { name: "Save" }); + const disabled = () => save().matches(":disabled, [aria-disabled=true]"); + await waitFor(() => expect(disabled()).toBe(true)); + fireEvent.click(save()); + expect(calls.some((call) => call.method === "PUT")).toBe(false); + fireEvent.click(screen.getByRole("combobox", { name: "Access for Everyone" })); + const editOption = await screen.findByRole("option", { name: "View + edit" }); + fireEvent.pointerDown(editOption); + fireEvent.pointerUp(editOption); + fireEvent.click(editOption); + await waitFor(() => expect(disabled()).toBe(false)); + fireEvent.click(screen.getByRole("combobox", { name: "Access for Everyone" })); + const viewOption = await screen.findByRole("option", { name: "View" }); + fireEvent.pointerDown(viewOption); + fireEvent.pointerUp(viewOption); + fireEvent.click(viewOption); + await waitFor(() => expect(disabled()).toBe(true)); + fireEvent.click(screen.getByRole("button", { name: "Remove access for Everyone" })); + await waitFor(() => expect(disabled()).toBe(false)); + // Re-adding the original grant also restores the saved state. + fireEvent.click(screen.getByRole("button", { name: "Add" })); + await waitFor(() => expect(disabled()).toBe(true)); + expect(calls.some((call) => call.method === "PUT")).toBe(false); } finally { restore(); } @@ -100,7 +133,10 @@ describe("SharingDialog", () => { try { renderDialog(); await screen.findByText("Everyone"); - fireEvent.click(screen.getByRole("button", { name: "Remove" })); + fireEvent.click(screen.getByRole("button", { name: /^Remove access for/ })); + expect(screen.queryByText("You have unsaved sharing changes.")).toBeNull(); + expect(screen.getByText("No one will have shared access after you save.")).toBeTruthy(); + expect(calls.some((call) => call.method === "PUT")).toBe(false); fireEvent.click(screen.getByRole("button", { name: "Save" })); await waitFor(() => { const put = calls.find((c) => c.method === "PUT" && c.url.endsWith("/shares")); diff --git a/apps/server/web/src/components/auth/provider-dialog.tsx b/apps/server/web/src/components/auth/provider-dialog.tsx index 964ab758a..4a14c5839 100644 --- a/apps/server/web/src/components/auth/provider-dialog.tsx +++ b/apps/server/web/src/components/auth/provider-dialog.tsx @@ -106,9 +106,22 @@ function ProviderForm({ provider, onDone }: { provider: ProviderAdminView | null // sends this exact slug as `id`, so the preview and the truth are one // string (§5a's "live while filling"). const displayId = editing ? provider.id : slug; + const unchanged = + provider !== null && + name.trim() === provider.name && + issuer.trim() === (provider.issuer ?? "") && + clientId.trim() === (provider.clientId ?? "") && + secret === "" && + overrideOrigin === (provider.callbackBaseUrl ?? null) && + domains + .split(",") + .map((value) => value.trim()) + .filter(Boolean) + .sort() + .join(",") === [...(provider.allowedDomains ?? [])].sort().join(","); async function save(): Promise { setSaveError(null); - if (invalidOverride) return; + if (invalidOverride || unchanged || busy) return; const shared = { name: name.trim(), issuer: issuer.trim(), @@ -161,6 +174,7 @@ function ProviderForm({ provider, onDone }: { provider: ProviderAdminView | null : null; const saveDisabled = + unchanged || busy || name.trim() === "" || issuer.trim() === "" || @@ -408,11 +422,13 @@ function ProviderForm({ provider, onDone }: { provider: ProviderAdminView | null disabledReason={ busy ? "Wait for the sign-in provider to save." - : invalidOverride - ? "Fix the provider endpoint addresses before saving." - : entries.length === 0 - ? "Add an entry point first." - : "Complete the required provider fields first." + : unchanged + ? "No provider changes to save." + : invalidOverride + ? "Fix the provider endpoint addresses before saving." + : entries.length === 0 + ? "Add an entry point first." + : "Complete the required provider fields first." } > {busy ? "Saving…" : editing ? "Save" : "Add provider"} diff --git a/apps/server/web/src/components/auth/providers-table.tsx b/apps/server/web/src/components/auth/providers-table.tsx index bd5ebb8ba..7c204ad49 100644 --- a/apps/server/web/src/components/auth/providers-table.tsx +++ b/apps/server/web/src/components/auth/providers-table.tsx @@ -3,6 +3,7 @@ import { Pencil, Settings2, Trash2 } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import { type ActionItem, ActionsMenu } from "@/components/actions-menu"; import { ProviderSettingsDialog } from "@/components/auth/provider-settings-dialog"; +import { FactList } from "@/components/fact-list"; import { useDeleteAuthProvider, usePatchAuthProvider } from "@/hooks/use-auth-providers"; import { EMAIL_PROVIDER_ID, @@ -127,16 +128,14 @@ function ProviderRow({ can repeat, so the two strings that actually identify the row — the slug id and the issuer — get label-over-value rows, the values in the mono foreground voice they wear everywhere else. */} -
-
-
Slug id
-
{provider.id}
-
-
-
Issuer
-
{provider.issuer ?? ""}
-
-
+
+ +
), confirmLabel: "Remove", diff --git a/apps/server/web/src/components/backups/backup-workflow.tsx b/apps/server/web/src/components/backups/backup-workflow.tsx index 4cabf64d8..840978279 100644 --- a/apps/server/web/src/components/backups/backup-workflow.tsx +++ b/apps/server/web/src/components/backups/backup-workflow.tsx @@ -3,13 +3,13 @@ import { CardFooter, CardHeader, CardTitle, - cn, Card as WorkflowCard, CardContent as WorkflowContent, } from "@internal/node-admin"; import { CheckCircle2, LoaderCircle } from "lucide-react"; -import { Fragment, type ReactNode } from "react"; -import { CopyButton } from "@/components/copy-button"; +import type { ReactNode } from "react"; +import { FactList } from "@/components/fact-list"; +import { ErrorNotice } from "@/components/ui/notice"; import { Card, CardContent } from "./backup-card"; export function BackupWorkflow({ @@ -69,34 +69,16 @@ export function BackupProgress({ export function BackupFacts({ rows }: { rows: { label: string; value: string; copy?: boolean }[] }) { return ( -
- {rows.map(({ label, value, copy }) => ( - -
{label}
-
-
- - {value} - - {copy && } -
-
-
- ))} -
+ ({ + ...row, + mono: row.copy && row.label !== "Control plane URL", + copyText: row.copy ? row.value : undefined, + }))} + /> ); } export function BackupError({ message, className }: { message: string; className?: string }) { - return ( -

- {message} -

- ); + return {message}; } diff --git a/apps/server/web/src/components/backups/create-backup-card.tsx b/apps/server/web/src/components/backups/create-backup-card.tsx index 07dda50b5..0d25b11ff 100644 --- a/apps/server/web/src/components/backups/create-backup-card.tsx +++ b/apps/server/web/src/components/backups/create-backup-card.tsx @@ -237,7 +237,10 @@ export function CreateBackupCard({ onBusy }: { onBusy?: (busy: boolean) => void disabled={busy} /> {problem && ( -

+

{problem}

)} @@ -273,7 +276,10 @@ export function CreateBackupCard({ onBusy }: { onBusy?: (busy: boolean) => void disabled={busy} /> {problem && ( -

+

{problem}

)} diff --git a/apps/server/web/src/components/backups/restore-backup-card.tsx b/apps/server/web/src/components/backups/restore-backup-card.tsx index 1c2d347fb..a2d574fa1 100644 --- a/apps/server/web/src/components/backups/restore-backup-card.tsx +++ b/apps/server/web/src/components/backups/restore-backup-card.tsx @@ -1,9 +1,10 @@ -import { Button, Input, Switch } from "@internal/node-admin"; +import { Button, cn, Input, Switch } from "@internal/node-admin"; import { BACKUP_RESTORE_DEFAULTS, BACKUP_RESTORE_MODES, type RestoreMode } from "@internal/subshell-protocol"; import { useStore } from "@tanstack/react-form"; import { LoaderCircle } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import { Checkbox } from "@/components/ui/checkbox"; +import { ChoiceFields } from "@/components/ui/choice-fields"; import { Field, FieldGroup, FieldLabel } from "@/components/ui/field"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; @@ -421,7 +422,11 @@ export function RestoreBackupCard({ onBusy }: { onBusy?: (busy: boolean) => void onChange={(event) => field.handleChange(event.target.value)} /> {problem && ( - )} @@ -690,7 +695,6 @@ export function RestoreBackupCard({ onBusy }: { onBusy?: (busy: boolean) => void @@ -698,17 +702,41 @@ export function RestoreBackupCard({ onBusy }: { onBusy?: (busy: boolean) => void } > {BACKUP_RESTORE_MODES.map((item) => ( - - - - {item.label} - + + +
+ + {item.label} + + {item.description} + + + {!inspection?.legacyDatabaseOnly && draft.mode === item.value && ( + + {textField("databasePath", "Database path (optional)")} + {textField("dataDir", "Data directory (optional)")} + {textField("configDir", "Configuration directory (optional)")} + {textField("baseUrl", "Control plane URL (optional)")} + {textField("host", "Bind address (optional)")} + {textField("port", "Port (optional)")} + {textField("trustedOrigins", "Trusted origins (optional)")} + + )} +
))}
-

- {BACKUP_RESTORE_MODES.find((mode) => mode.value === draft.mode)?.description} -

{inspection?.legacyDatabaseOnly && (

This backup contains only the database. It restores into this server using its current @@ -716,17 +744,6 @@ export function RestoreBackupCard({ onBusy }: { onBusy?: (busy: boolean) => void

)} - {!inspection?.legacyDatabaseOnly && ( - <> - {textField("databasePath", "Database path (optional)")} - {textField("dataDir", "Data directory (optional)")} - {textField("configDir", "Configuration directory (optional)")} - {textField("baseUrl", "Control plane URL (optional)")} - {textField("host", "Bind address (optional)")} - {textField("port", "Port (optional)")} - {textField("trustedOrigins", "Trusted origins (optional)")} - - )} void } > - - Restore from - { - setSource(value === "saved" ? "saved" : "file"); - void resetSelection().catch((error) => setSelectionProblem(String(error))); - }} - > - - - - Open a backup file - - - - - - Use a saved backup - - - -
{ @@ -858,168 +850,213 @@ export function RestoreBackupCard({ onBusy }: { onBusy?: (busy: boolean) => void }} className="flex flex-col gap-4" > - {source === "file" ? ( - - { - const file = event.target.files?.[0] ?? null; - if (!file) return; - const values = { file, path: "", password: "", encrypted: false }; - inspectForm.reset(values, { keepDefaultValues: true }); - void validateSelection(values); - }} - /> - - {selected.file &&

{selected.file.name}

} -
- ) : ( - - - Available backups - - - - - Available backups - - - {restore.saved.isPending ? ( -

Loading saved backups…

- ) : !restore.saved.data?.backups.length && !restore.saved.error ? ( -

No saved backups are available. Open a backup file instead.

- ) : null} - {restore.saved.error && } - {selected.path && ( -

- {restore.saved.data?.backups.find((file) => file.path === selected.path)?.name} -

- )} -
-
-
- )} - {selected.encrypted && ( - - {(field) => { - const problem = - !busy && focusedField !== "password" - ? (passwordProblem ?? (field.state.meta.isTouched ? fieldError(field.state.meta.errors) : null)) - : null; - return ( - - - Archive password + {option.label} - setFocusedField("password")} - onBlur={() => { - field.handleBlur(); - setFocusedField(null); - }} - onChange={(event) => { - field.handleChange(event.target.value); - setInspection(null); - setPasswordProblem(null); - }} - /> - {problem && ( - + {source === option.value && ( + + {source === "file" ? ( + + { + const file = event.target.files?.[0] ?? null; + if (!file) return; + const values = { file, path: "", password: "", encrypted: false }; + inspectForm.reset(values, { keepDefaultValues: true }); + void validateSelection(values); + }} + /> + + {selected.file &&

{selected.file.name}

} +
+ ) : ( +
+ + Available backups + + {restore.saved.isPending ? ( +

Loading saved backups…

+ ) : !restore.saved.data?.backups.length && !restore.saved.error ? ( +

+ No saved backups are available. Open a backup file instead. +

+ ) : null} + {restore.saved.error && } + {selected.path && ( +

+ {restore.saved.data?.backups.find((file) => file.path === selected.path)?.name} +

+ )} +
+
+ )} + {selected.encrypted && ( + + {(field) => { + const problem = + !busy && focusedField !== "password" + ? (passwordProblem ?? + (field.state.meta.isTouched ? fieldError(field.state.meta.errors) : null)) + : null; + return ( + + + Archive password + + setFocusedField("password")} + onBlur={() => { + field.handleBlur(); + setFocusedField(null); + }} + onChange={(event) => { + field.handleChange(event.target.value); + setInspection(null); + setPasswordProblem(null); + }} + /> + {problem && ( + + )} + + ); + }} + + )} + {selectionProblem && } + {restore.inspect.isPending && ( +

+

+ )} + {inspection ? ( +

+ Backup validated. Select Configure backup to continue. +

+ ) : ( + (selected.file || selected.path) && ( + + ) + )} + {source === "file" && ( +

+ Browser uploads support archives up to 128 MB. Use the CLI or desktop assistant for larger + files. +

+ )} +
)} -
- ); - }} -
- )} - {selectionProblem && ( -

- {selectionProblem} -

- )} - {restore.inspect.isPending && ( -

-

- )} - {inspection ? ( -

- Backup validated. Select Configure backup to continue. -

- ) : ( - (selected.file || selected.path) && ( - - ) - )} - {source === "file" && ( -

- Browser uploads support archives up to 128 MB. Use the CLI or desktop assistant for larger files. -

- )} + + + ))} + +
); diff --git a/apps/server/web/src/components/clone-subshell-dialog.tsx b/apps/server/web/src/components/clone-subshell-dialog.tsx index 93df2ec68..31e4f4300 100644 --- a/apps/server/web/src/components/clone-subshell-dialog.tsx +++ b/apps/server/web/src/components/clone-subshell-dialog.tsx @@ -1,6 +1,7 @@ import { Button, Input } from "@internal/node-admin"; import { useNavigate } from "@tanstack/react-router"; import { type JSX, useState } from "react"; +import { FactList } from "@/components/fact-list"; import { Dialog, DialogContent, @@ -115,16 +116,14 @@ export function CloneSubshellDialog({ the date and time. -
-
Agent
-
{agentName}
-
Preset
-
{presetName}
-
Node
-
{nodeLabel}
-
Working directory
-
{source.workingDir}
-
+
)} diff --git a/apps/server/web/src/components/presets/__tests__/ssh-preset-editor.test.tsx b/apps/server/web/src/components/presets/__tests__/ssh-preset-editor.test.tsx index c35b51307..ecb63be29 100644 --- a/apps/server/web/src/components/presets/__tests__/ssh-preset-editor.test.tsx +++ b/apps/server/web/src/components/presets/__tests__/ssh-preset-editor.test.tsx @@ -92,7 +92,7 @@ it("saves the local-key radio choice without requiring a file or approval", asyn expect(screen.getByRole("radio", { name: "Use a key from my machine" }).getAttribute("aria-checked")).toBe("true"); const localKeyChoice = screen.getByRole("radio", { name: "Use a key from my machine" }); expect(document.getElementById(localKeyChoice.getAttribute("aria-describedby") ?? "")?.textContent).toContain( - "Choose a key from your machine when creating a new SSH subshell", + "Choose a private key on the device you’re using now.", ); expect(screen.queryByRole("button", { name: "Choose key…" })).toBeNull(); expect(screen.queryByRole("checkbox", { name: "I trust this website and its operator" })).toBeNull(); diff --git a/apps/server/web/src/components/presets/command-paste-field.tsx b/apps/server/web/src/components/presets/command-paste-field.tsx index 619aa3e0f..5aa34bbd5 100644 --- a/apps/server/web/src/components/presets/command-paste-field.tsx +++ b/apps/server/web/src/components/presets/command-paste-field.tsx @@ -1,4 +1,4 @@ -import { errMessage } from "@internal/node-admin"; +import { errMessage, Fact } from "@internal/node-admin"; import { useMemo, useState } from "react"; import { Textarea } from "@/components/ui/textarea"; import { parseCommandPaste, presetFormToCommand } from "@/lib/preset-command"; @@ -116,25 +116,23 @@ export function CommandPasteField({ : `${envCount} env var${envCount === 1 ? "" : "s"} · ${flagCount} flag${flagCount === 1 ? "" : "s"}`}

{command.env.length > 0 && ( -
+
{command.env.map((row) => ( -
-
{row.key}
-
{row.value || "(empty)"}
-
+ + {row.value || "(empty)"} + ))}
)} {command.flags.length > 0 && ( -
+
{command.flags.map((row, i) => ( // Flags are positional and may legitimately repeat // (`--allow a --allow b`), so the index is the only key. // biome-ignore lint/suspicious/noArrayIndexKey: see above -
-
{row.flag}
-
{row.value}
-
+ + {row.value || "No value"} + ))}
)} diff --git a/apps/server/web/src/components/profile-card.tsx b/apps/server/web/src/components/profile-card.tsx index 00df53583..99700acb0 100644 --- a/apps/server/web/src/components/profile-card.tsx +++ b/apps/server/web/src/components/profile-card.tsx @@ -1,6 +1,7 @@ import { Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Input, Label } from "@internal/node-admin"; import { useQueryClient } from "@tanstack/react-query"; import { useState } from "react"; +import { FactList } from "@/components/fact-list"; import { useCurrentUser } from "@/lib/auth"; import { authClient } from "@/lib/auth-client"; import { CURRENT_USER_QUERY_KEY } from "@/lib/query-keys"; @@ -55,9 +56,11 @@ export function ProfileCard({ updateUser = (input) => authClient.updateUser(inpu const shown = nameDraft ?? user?.name ?? ""; + const unchanged = nameIsUsable(shown) === user?.name; + async function save() { const name = nameIsUsable(shown); - if (name === null) return; + if (name === null || unchanged || busy) return; setBusy(true); setError(null); setSaved(false); @@ -111,19 +114,20 @@ export function ProfileCard({ updateUser = (input) => authClient.updateUser(inpu {saved && saved} -
- - {/* Read-only by design: the email IS the credential; changing it - is not offered here (muted to say so at a glance). */} - -
+ {error &&

{error}

} )} diff --git a/apps/server/web/src/components/prompts/__tests__/stack-form-dialog.test.tsx b/apps/server/web/src/components/prompts/__tests__/stack-form-dialog.test.tsx index 5e63d3ef1..5f6dfcf02 100644 --- a/apps/server/web/src/components/prompts/__tests__/stack-form-dialog.test.tsx +++ b/apps/server/web/src/components/prompts/__tests__/stack-form-dialog.test.tsx @@ -132,11 +132,13 @@ describe("StackFormDialog", () => { shared: false, }, }); + expect(saveButton(true).matches(":disabled, [aria-disabled=true]")).toBe(true); + fireEvent.change(screen.getByLabelText(/Label/), { target: { value: "Changed label" } }); fireEvent.click(saveButton(true)); await waitFor(() => expect(m.calls.length).toBe(1)); // The unlabeled inline row rides UNLABELED (the placeholder is display). expect(m.calls[0]?.body).toEqual({ - label: "Mixed", + label: "Changed label", items: [{ promptId: "p1" }, { body: "mine" }], shared: false, }); @@ -149,6 +151,8 @@ describe("StackFormDialog", () => { const m = mockFetch({ failWith: "The stack's text joined is 30000 characters" }); try { renderDialog({ editingId: "st1", initial: { label: "Big", blocks: [block({ body: "x" })], shared: false } }); + expect(saveButton(true).matches(":disabled, [aria-disabled=true]")).toBe(true); + fireEvent.change(screen.getByLabelText(/Label/), { target: { value: "Changed label" } }); fireEvent.click(saveButton(true)); const alert = await screen.findByRole("alert"); expect(alert.textContent).toContain("30000 characters"); diff --git a/apps/server/web/src/components/prompts/prompt-form-dialog.tsx b/apps/server/web/src/components/prompts/prompt-form-dialog.tsx index 1ce6a083e..8d6223a23 100644 --- a/apps/server/web/src/components/prompts/prompt-form-dialog.tsx +++ b/apps/server/web/src/components/prompts/prompt-form-dialog.tsx @@ -1,4 +1,5 @@ import { Button, errMessage, Input, Label, Switch } from "@internal/node-admin"; +import { useStore } from "@tanstack/react-form"; import { useState } from "react"; import { Dialog, @@ -45,10 +46,17 @@ export function PromptFormDialog({ const update = useUpdatePrompt(); const busy = create.isPending || update.isPending; + const unchangedDraft = (values: PromptDraft) => + !!editingId && + !!initial && + values.description.trim() === initial.description.trim() && + values.body === initial.body && + values.shared === initial.shared; const form = makeForm({ defaultValues: initial ?? { description: "", body: "", shared: false }, validator: promptDraftSchema, onSubmit: async (draft) => { + if (unchangedDraft(draft)) return; // The guard behind the gate (Enter-key paths, races). if (draft.description.trim() === "" || draft.body.trim() === "") return; setServerError(null); @@ -65,8 +73,10 @@ export function PromptFormDialog({ } }, }); - const disabled = useSubmitDisabled(form, busy); - const disabledReason = useSubmitDisabledReason(form, busy); + const unchanged = useStore(form.store, (state) => unchangedDraft(state.values)); + const disabled = useSubmitDisabled(form, busy) || unchanged; + const validationReason = useSubmitDisabledReason(form, busy); + const disabledReason = validationReason ?? (unchanged ? "No changes to save." : undefined); return ( diff --git a/apps/server/web/src/components/prompts/stack-form-dialog.tsx b/apps/server/web/src/components/prompts/stack-form-dialog.tsx index 1c78b94b3..b4942e2f2 100644 --- a/apps/server/web/src/components/prompts/stack-form-dialog.tsx +++ b/apps/server/web/src/components/prompts/stack-form-dialog.tsx @@ -1,4 +1,5 @@ import { Button, errMessage, Input, Label, Switch } from "@internal/node-admin"; +import { useStore } from "@tanstack/react-form"; import { Plus } from "lucide-react"; import { useId, useState } from "react"; import { PromptPickerBody } from "@/components/prompts/prompt-picker-body"; @@ -55,6 +56,12 @@ export function StackFormDialog({ const update = useUpdatePromptStack(); const busy = create.isPending || update.isPending; + const unchangedDraft = (values: { label: string; blocks: PromptBlock[]; shared: boolean }) => + !!editingId && + !!initial && + values.label.trim() === initial.label.trim() && + values.shared === initial.shared && + JSON.stringify(stackMembersFromBlocks(values.blocks)) === JSON.stringify(stackMembersFromBlocks(initial.blocks)); const form = makeForm({ defaultValues: { label: initial?.label ?? "", @@ -63,6 +70,7 @@ export function StackFormDialog({ }, validator: makePromptStackSchema(editingId ? 0 : 1), onSubmit: async (values) => { + if (unchangedDraft(values)) return; // The guard behind the gate (Enter-key paths, races). if (values.label.trim() === "" || (!editingId && values.blocks.length === 0)) return; setServerError(null); @@ -82,8 +90,10 @@ export function StackFormDialog({ } }, }); - const disabled = useSubmitDisabled(form, busy); - const disabledReason = useSubmitDisabledReason(form, busy); + const unchanged = useStore(form.store, (state) => unchangedDraft(state.values)); + const disabled = useSubmitDisabled(form, busy) || unchanged; + const validationReason = useSubmitDisabledReason(form, busy); + const disabledReason = validationReason ?? (unchanged ? "No changes to save." : undefined); return ( diff --git a/apps/server/web/src/components/service/restart-dialog.tsx b/apps/server/web/src/components/service/restart-dialog.tsx index 56c5297ea..f1f1fa42d 100644 --- a/apps/server/web/src/components/service/restart-dialog.tsx +++ b/apps/server/web/src/components/service/restart-dialog.tsx @@ -9,6 +9,7 @@ import { DialogHeader, DialogTitle, } from "@/components/ui/dialog"; +import { WarningNotice } from "@/components/ui/notice"; import type { ServerDeployment } from "@/types/server-deployment"; /** @@ -96,12 +97,19 @@ export function RestartDialog({ Restart the server? {kills - ? view.service.manager === "docker" - ? "Restarting the Docker container closes every running subshell. Open terminals reconnect after the server returns." - : `This server's service definition will close every running subshell. Rewrite it by running ${REINSTALL_COMMAND} on this machine, or restart anyway.` + ? "Open terminals reconnect after the server returns." : "Running subshells keep running; open terminals reconnect in a few seconds."} + {kills && ( + + {view.service.manager === "docker" + ? "Restarting the Docker container closes every running subshell." + : view.service.paneSafety === "kills" + ? `This server's service definition will close every running subshell. Rewrite it by running ${REINSTALL_COMMAND} on this machine, or restart anyway.` + : `We couldn't determine whether running subshells will survive. Restarting may close them. Rewrite the service definition by running ${REINSTALL_COMMAND} on this machine, or restart anyway.`} + + )} {enables ? (

{enables}

) : ( diff --git a/apps/server/web/src/components/service/supervision-dialog.tsx b/apps/server/web/src/components/service/supervision-dialog.tsx index ad4207d4b..97b1f8c17 100644 --- a/apps/server/web/src/components/service/supervision-dialog.tsx +++ b/apps/server/web/src/components/service/supervision-dialog.tsx @@ -10,6 +10,7 @@ import { DialogHeader, DialogTitle, } from "@/components/ui/dialog"; +import { WarningNotice } from "@/components/ui/notice"; import type { PaneSafety, ServerDeployment } from "@/types/server-deployment"; /** @@ -120,14 +121,18 @@ export function SupervisionDialog({
    {target && - consequences(target, view.platform, autostart, view.service.paneSafety).map((line) => ( -
  • - - • - - {line} -
  • - ))} + consequences(target, view.platform, autostart, view.service.paneSafety) + .filter((_, index) => !lethal || index !== 3) + .map((line) => ( +
  • + + • + + + {line} + +
  • + ))}
{!toApp && (
@@ -136,11 +141,18 @@ export function SupervisionDialog({
)} {lethal && ( -

- {view.service.paneSafety === "kills" - ? "This machine's service definition predates the setting that spares live panes. Running `subshell-server service install` on that machine rewrites it." - : "This machine's service definition could not be read, so this is the safe assumption."} -

+ +

+ {view.service.paneSafety === "kills" + ? "Every running subshell will be closed" + : "Whether running subshells survive could not be determined"} +

+

+ {view.service.paneSafety === "kills" + ? "This machine's service definition predates the setting that spares live panes. Running `subshell-server service install` on that machine rewrites it." + : "This machine's service definition could not be read. Switching may close running subshells."} +

+
)}

This page will lose its connection for a few seconds while the server comes back. diff --git a/apps/server/web/src/components/sharing-dialog-core.tsx b/apps/server/web/src/components/sharing-dialog-core.tsx index 32c5f7196..21462ab59 100644 --- a/apps/server/web/src/components/sharing-dialog-core.tsx +++ b/apps/server/web/src/components/sharing-dialog-core.tsx @@ -9,6 +9,7 @@ import { DialogHeader, DialogTitle, } from "@/components/ui/dialog"; +import { ErrorNotice, WarningNotice } from "@/components/ui/notice"; import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import type { RosterUser, ShareDraft } from "@/hooks/use-subshell-shares"; import type { SubshellAccess } from "@/types/subshell"; @@ -116,6 +117,12 @@ export function SharingDialogCore({ const pickerId = useId(); const grants = draft ?? serverGrants; + // Grant order isn't meaningful: removing and re-adding the same access is unchanged. + const savedPermissions = new Map(serverGrants.map((grant) => [grant.granteeUserId, grant.permission])); + const hasChanges = + grants.length !== serverGrants.length || + grants.some((grant) => savedPermissions.get(grant.granteeUserId) !== grant.permission); + const saveDisabled = saving || isLoading || !hasChanges; const alreadyShared = new Set(grants.map((g) => g.granteeUserId ?? EVERYONE)); const recipientOptions = [ @@ -149,6 +156,7 @@ export function SharingDialogCore({ } async function save() { + if (!canManage || saveDisabled) return; setError(null); try { await onSave(grants); @@ -168,23 +176,26 @@ export function SharingDialogCore({ {/* Before the grant rows, not after: the disclosure has to be read while deciding, not discovered under the Save button. */} - {warning != null && ( -

- {warning} -

- )} + {warning != null && {warning}}
+ {canManage && ( +

+ Save applies all additions, removals, and access changes. Cancel discards them. +

+ )} {isLoading &&

Loading…

} {!isLoading && grants.length === 0 && ( -

Not shared with anyone yet.

+

+ {hasChanges ? "No one will have shared access after you save." : "Not shared with anyone yet."} +

)} {grants.map((g, i) => (
- + {g.granteeUserId === null ? "Everyone" : (roster.find((u) => u.id === g.granteeUserId)?.email ?? g.granteeUserId)} @@ -196,7 +207,13 @@ export function SharingDialogCore({ value={g.permission} onChange={(level) => changeLevel(i, level)} /> - @@ -237,11 +254,7 @@ export function SharingDialogCore({
)} - {error && ( -

- {error} -

- )} + {error && {error}}
@@ -251,9 +264,13 @@ export function SharingDialogCore({ {canManage && (
diff --git a/docs/README.md b/docs/README.md index 77cf9a5a7..f88970d05 100644 --- a/docs/README.md +++ b/docs/README.md @@ -12,6 +12,7 @@ notes should link to them and explain only the additional engineering details. - [Security follow-ups](security-actionable.md): unresolved work, decision triggers, and regression history. - [Release and CI](release-and-ci.md): build, signing, publishing, updates, and deployment mechanics. - [Design system](design-system.md): product tokens, dashboard layouts, responsive tables, interaction patterns, and implementation constraints. +- [Dashboard UX review](ux-review-2026-10-17.md): October 2026 findings, corrections, verification scope, and remaining coverage limits. - [Documentation authoring](../apps/docs/AGENTS.md) and [style guide](../apps/docs/STYLE.md): public site structure, language, visuals, and verification. - [Proxmox submission research](proxmox-community-submission.md): external acceptance criteria and future integration work. diff --git a/docs/design-system.md b/docs/design-system.md index 5af48e115..3d8450d9e 100644 --- a/docs/design-system.md +++ b/docs/design-system.md @@ -252,9 +252,9 @@ admitted here. - **Line item**: `label` over `detail`, differing by weight AND colour, never by tone alone. *(15px regular over 13px muted read as one paragraph.)* - **Quiet label vs control label**: a read-only data row labels over its value - with the label in `muted-foreground` at `body` size, the `Fact`/`dt` grammar, - and it takes that size from the list or `
` around it rather than from the - label itself. `font-strong` label weight belongs to a control's label and to a + with the label in `muted-foreground` at `detail` size and the value at `body` + size in `foreground`, using the shared `Fact` component. Monospace values keep + the same body size. Size and colour together distinguish labels from values. `font-strong` label weight belongs to a control's label and to a section heading, ONLY. *(A networking card set bold "NetBird FQDN" over its URL six pixels above a quiet "Client version" over its: two label grammars in one card, so one row read as a heading and the other as data, and neither was the @@ -364,10 +364,31 @@ admitted here. label. Use `aria-labelledby` for the title and `aria-describedby` for the description so assistive technology announces their separate roles. This applies to native radios and shared radio components across web and desktop surfaces. +- **Dependent forms**: keep a selected radio option's fields directly beneath + that option, inside a bordered, inset panel (`ChoiceFields` in the SPA). + Keep the panel outside the clickable label, associate it with the option's + title, and keep field labels visible. The boundary distinguishes the subform + from option descriptions without moving it away from its choice. Every option + keeps its short clickable description. Settings shared by the whole group can + use a named section below it. Equivalent branches use the same + container treatment. +- **Dialog facts**: use the SPA's `FactList` for review and approval details: + muted detail-size labels over foreground body-size values, using the shared + `Fact` component also used by status and node cards. Technical values may + use monospace without becoming smaller. Wrap decision-critical values rather + than truncating paths, destinations, or fingerprints; offer copying when useful. +- **Pending list edits**: when Add or Remove changes a draft, explain that Save + applies the changes. Disable Save until the draft differs from saved data, + including after edits are undone; don't add an unsaved-changes message. + Compare list contents rather than their order. Empty-state wording must describe + the pending result rather than claiming the saved state has changed. +- **Confirmation warnings**: present disruptive consequences in `WarningNotice`, + separate from introductory text and target facts. Failed operations use + `ErrorNotice`; prerequisites and restrictions remain gold. - **Choice group**: radios inside `role="radiogroup"` with an `aria-label`; a - dependent setting sits BELOW the group after a rule, never indented under one - option; its dependency is a disabled control that says why and names what - would answer. *("needs the box above" named a widget.)* + setting specific to one option uses its inset `ChoiceFields` panel. Settings + shared by the group sit below it after a rule; unavailable settings explain + their dependency and what would make them available. *("needs the box above" named a widget.)* - **Copy affordance**: the copy ICON, at `icon-sm`, never the word "Copy" as a button label, and never a caption of its own: what is copied is named by `aria-label` (`Copy server address`), and the icon is a `Check` in `text-success` for the 1.5 s the diff --git a/docs/ux-review-2026-10-17.md b/docs/ux-review-2026-10-17.md new file mode 100644 index 000000000..e1992384b --- /dev/null +++ b/docs/ux-review-2026-10-17.md @@ -0,0 +1,65 @@ +# Dashboard UX review, 2026-10-17 + +This review covers the server dashboard and the shared node-admin components +it renders. The first pass missed shared runtime facts and some conditional +forms. This follow-up reviews the recurring patterns across routes and their +components; it is not a claim that every possible product state was exercised. + +## Findings addressed + +| Pattern | Finding and correction | Surfaces | +| --- | --- | --- | +| Read-only facts | Labels and values had similar size and color, and several screens implemented their own pairs. Shared `Fact` now uses smaller muted labels and body-sized foreground values, including monospace values. | Runtime, Status, node details, SSH trust, Networking, clone, enrollment, backup summaries, destination verification, provider removal, command previews | +| Long values | Some review values were truncated or could force a wide layout. Facts wrap complete values; machine facts collapse to one column on narrow screens. | Addresses, paths, fingerprints, commands, SSH summaries, node metadata | +| Radio-dependent fields | Fields below the whole group made their association unclear. The selected option now contains an inset, bordered field panel immediately below its description, outside its clickable label. | SSH authentication, SSH forwarding, Restore source and mode | +| Save availability | Touched fields and unchanged drafts could enable Save. Save now compares the effective draft with saved data, including reverting edits. Sharing no longer displays a separate unsaved-changes sentence. | Sharing, profile, device name, instance name, providers, prompts, prompt stacks, network plugin settings, server addresses | +| Notices and validation | Consequence notices and error styling varied. Shared notices distinguish warnings from failures; backup validation distinguishes missing input from an invalid supplied value. | Sharing, restart, update, supervision, destination verification, backup creation and restore, generated API keys | +| Review information | Destination identity details were hidden behind a disclosure. Destination and copyable fingerprint are now visible at the trust decision. Profile email is presented as a fact instead of an editable-looking field. | SSH verification, account profile | + +The [design system](design-system.md) records the shared rules. Creation, +immediate-save switches, and actions that also apply an existing configuration +retain their respective behavior; they are not ordinary draft-save actions. + +## Coverage and evidence + +Source review covered dashboard routes, their dialogs and editors, and the +shared node-admin fact components. The main review criteria were information +hierarchy, complete values, conditional-field association, validation tone, +Save availability, and narrow-screen layout. + +Browser checks used the isolated review backend and Vite frontend, with a +seeded terminal containing a long working-directory path. At both 320px and +1600px, the following route entries had no document-level horizontal overflow +with the available data: + +- Subshells, Nodes, the server node detail, Presets, Prompts, Workspaces. +- Account and Preferences. +- Server Settings: General, Users, Auth, API keys, Plugins, Service, + Networking, Updates, Backups, Status, and Logs. +- The legacy SSH settings entry redirected to Presets as expected. + +That is 20 route entries and 19 distinct rendered surfaces. Many lists were +empty in the sandbox; a successful page-width check does not prove every +populated row or dialog fits. Additional browser checks opened the SSH +authentication field panel at both widths and the saved-backup Restore panel. +The SSH dialog had no horizontal overflow, and Restore exposed its associated +region. Runtime and Restore screenshots were visually inspected. + +Component tests cover the changed radio association, sharing change/revert +behavior, backup validation, stack editing, address presentation, enrollment +facts, and restart wording. Workspace build, type checks, lint, and tests are +the automated verification for the changes; these are distinct from browser +workflow coverage. + +## Limits + +This was not a full accessibility certification or an end-to-end exercise of +every role, failure, and integration state. Remote node/key availability, +external identity providers, native key approval, actual server replacement, +live network changes, and populated saved-backup recovery were not exercised +through the review browser. Existing component tests cover some of those +states, but they do not substitute for integration testing. + +The native desktop assistant and mobile app were outside this dashboard +review. Shared node-admin changes reach their consumers, but those native +surfaces were not visually checked in this pass. diff --git a/packages/node-admin/src/components/fact-list.tsx b/packages/node-admin/src/components/fact-list.tsx index d46be1739..54b07c666 100644 --- a/packages/node-admin/src/components/fact-list.tsx +++ b/packages/node-admin/src/components/fact-list.tsx @@ -1,4 +1,5 @@ import type { ReactNode } from "react"; +import { cn } from "../lib/utils"; import { Card, CardContent, CardHeader, CardTitle } from "../ui/card"; /** @@ -17,9 +18,9 @@ export function Fact({ wide?: boolean; }) { return ( -
-
{label}
-
{children}
+
+
{label}
+
{children}
); } @@ -36,7 +37,7 @@ export function FactCard({ title, children }: { title: string; children: ReactNo {title} -
{children}
+
{children}
); diff --git a/packages/node-admin/src/components/node-runtime-card.tsx b/packages/node-admin/src/components/node-runtime-card.tsx index e2a22815d..eef1966f2 100644 --- a/packages/node-admin/src/components/node-runtime-card.tsx +++ b/packages/node-admin/src/components/node-runtime-card.tsx @@ -117,7 +117,7 @@ export function NodeRuntimeCard({ node, local = false }: { node: NodeDetail; loc {runtime.tmuxPath ? ( - {runtime.tmuxPath} + {runtime.tmuxPath} ) : ( // Said here rather than discovered at launch time: without tmux the // node accepts nothing, and nothing else on this page would say so. diff --git a/packages/node-admin/src/components/ssh-trust-card.tsx b/packages/node-admin/src/components/ssh-trust-card.tsx index f3c2a2311..86a9e7b6d 100644 --- a/packages/node-admin/src/components/ssh-trust-card.tsx +++ b/packages/node-admin/src/components/ssh-trust-card.tsx @@ -3,6 +3,7 @@ import type { NodeDetail, NodeSshTrustPeer } from "../types/node"; import { Badge } from "../ui/badge"; import { Card, CardContent, CardHeader, CardTitle } from "../ui/card"; import { CopyableValue } from "../ui/copyable-value"; +import { Fact } from "./fact-list"; /** * The machine trust card (spec 2026-10-08 §4.6): this machine's own SSH relay @@ -77,20 +78,18 @@ export function NodeSshTrustCard({ copyLabel="This machine's encryption fingerprint" /> {trust.peers.length === 0 ? ( -
-
Saved machine identities
-
No saved machine identities yet.
-
+ + No saved machine identities yet. + ) : ( trust.peers.map((peer) => ( -
-
Peer {peer.nodeId}
-
+ +
-
+
{renderPeerAction &&
{renderPeerAction(peer)}
} -
+ )) )}
@@ -100,22 +99,19 @@ export function NodeSshTrustCard({ return embedded ?
{content}
: {content}; } -/** One labelled fingerprint: `label` over a mono `detail`, the line-item shape. */ +/** Fingerprints use the same label/value hierarchy as other machine facts. */ function FingerprintFact({ label, value, copyLabel }: { label: string; value: string; copyLabel: string }) { return ( -
-
{label}
-
- -
-
+ + + ); } /** The value plus its copy affordance, the thing a person takes to the other machine. */ function FingerprintValue({ value, copyLabel }: { value: string; copyLabel: string }) { return ( - + ); From d7a4feb9fe389a9b73cbd5a98e6f536ea17db55b Mon Sep 17 00:00:00 2001 From: Theo Gravity Date: Sat, 17 Oct 2026 01:47:11 -0700 Subject: [PATCH 2/6] fix: address review findings on dashboard UX consistency Fact copying, validation tone, and the Save-unchanged comparison now go through shared logic instead of per-site guesses, the restore overrides move to a named section below their mode group (they apply to both), and the supervision dialog drops the panes line by its text rather than its index. The destination-confirmation e2e spec and docs follow the fingerprint out of the disclosure it shipped behind; a whitespace-only field reads the same tone on both backup cards; the ChoiceFields-in-group decision is recorded where the a11y rules live. Co-Authored-By: Claude Fable 5 --- apps/docs/content/docs/guides/ssh.mdx | 6 +- .../ssh-destination-confirmation.png | Bin 84532 -> 131587 bytes .../__tests__/backup-settings.test.tsx | 19 ++++++ .../__tests__/network-plugin-card.test.tsx | 14 +++-- .../__tests__/sharing-dialog.test.tsx | 4 +- .../__tests__/supervision-dialog.test.tsx | 58 ++++++++++++++++++ .../components/backups/create-backup-card.tsx | 11 +--- .../components/backups/field-problem-tone.ts | 16 +++++ .../backups/restore-backup-card.tsx | 49 ++++++++------- apps/server/web/src/components/fact-list.tsx | 36 ++++++++--- .../__tests__/addresses-card.test.ts | 25 +++++++- .../components/networking/addresses-card.tsx | 22 ++++++- .../networking/network-plugin-card.tsx | 2 +- .../src/components/nodes/node-key-setup.tsx | 4 +- .../presets/command-paste-field.tsx | 2 +- .../src/components/service/restart-dialog.tsx | 2 +- .../components/service/supervision-dialog.tsx | 56 ++++++++++------- .../web/src/components/ui/choice-fields.tsx | 12 +++- docs/design-system.md | 12 +++- e2e/tests/24-ssh-ux.spec.ts | 4 +- 20 files changed, 273 insertions(+), 81 deletions(-) create mode 100644 apps/server/web/src/components/backups/field-problem-tone.ts diff --git a/apps/docs/content/docs/guides/ssh.mdx b/apps/docs/content/docs/guides/ssh.mdx index 69654fe2b..2a58c6e53 100644 --- a/apps/docs/content/docs/guides/ssh.mdx +++ b/apps/docs/content/docs/guides/ssh.mdx @@ -80,11 +80,11 @@ Select **Start SSH subshell**. If you're using another node's keys and neither t A host key is the destination machine's public SSH key. It identifies that machine; your login key or password identifies you. Remembering the host key lets SSH detect a different machine answering at the same address later. You don't need to generate, paste, or manage host keys in the dashboard.
- -
A first connection using another node's keys asks before remembering an unfamiliar destination. This screenshot uses a disposable local SSH destination. Select the image to enlarge it.
+ +
A first connection using another node's keys asks before remembering an unfamiliar destination. This screenshot was captured from a sandboxed review instance with test data. Select the image to enlarge it.
-Check the address. If you need to verify the machine, expand **Verification details** and compare the fingerprint with one obtained from its administrator through a trusted channel. Choose **Trust and connect** to remember that identity and retry the connection, or **Cancel** to leave it untrusted. +Check the address. The dialog shows the destination's host fingerprint and warns that the fingerprint came from the destination itself, not an independent check. If you need to verify the machine, compare the fingerprint with one obtained from its administrator through a trusted channel. Choose **Trust and connect** to remember that identity and retry the connection, or **Cancel** to leave it untrusted. > [!warning] First-connection trust > A key retrieved from the destination isn't independent proof that you've reached the right machine. Accepting it without checking the fingerprint trusts the first response. Subshell blocks later connections if the identity changes; it doesn't silently replace the saved identity. If that happens, stop and verify the change with the destination's administrator. diff --git a/apps/docs/public/screenshots/ssh-destination-confirmation.png b/apps/docs/public/screenshots/ssh-destination-confirmation.png index 84980f9ace681710adb6875b0a75620f42639e6f..3a251f02d442457d9d6c4328c3a63ac729fc96bd 100644 GIT binary patch literal 131587 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 OLT6zLH>ol5iTgMAu#BDn literal 84532 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 diff --git a/apps/server/web/src/components/__tests__/backup-settings.test.tsx b/apps/server/web/src/components/__tests__/backup-settings.test.tsx index 3ed506c61..68bd11075 100644 --- a/apps/server/web/src/components/__tests__/backup-settings.test.tsx +++ b/apps/server/web/src/components/__tests__/backup-settings.test.tsx @@ -399,6 +399,25 @@ describe("Settings backup workflows", () => { }); }); + it("keeps the restore overrides below the mode group, not inside the selected option", async () => { + // The seven override fields apply to BOTH modes identically. They once + // rendered inside whichever mode was selected, so flipping the radio + // teleported the block (and remounted every input in it). They are a + // named section below the group now, and switching modes must not move + // the person's typing. + mockApi(); + mount(); + await configureFile(); + expect(screen.getByRole("region", { name: "Restore overrides" })).toBeTruthy(); + const port = screen.getByLabelText("Port (optional)"); + fireEvent.change(port, { target: { value: "4000" } }); + fireEvent.click(screen.getByRole("radio", { name: "This machine is different from the original" })); + expect(screen.getByLabelText("Port (optional)")).toBe(port); + expect((port as HTMLInputElement).value).toBe("4000"); + fireEvent.click(screen.getByRole("radio", { name: "Same-machine recovery" })); + expect((port as HTMLInputElement).value).toBe("4000"); + }); + it("revalidates expired extraction before preparation and stops for review if the source changed", async () => { let inspected = 0; const requests = mockApi((request) => { diff --git a/apps/server/web/src/components/__tests__/network-plugin-card.test.tsx b/apps/server/web/src/components/__tests__/network-plugin-card.test.tsx index 3b3c8257e..ba0dc176a 100644 --- a/apps/server/web/src/components/__tests__/network-plugin-card.test.tsx +++ b/apps/server/web/src/components/__tests__/network-plugin-card.test.tsx @@ -1174,9 +1174,13 @@ describe("NetworkPluginCard: the state matrix", () => { expect(first.children[0]?.className).toContain("text-detail"); expect(first.children[1]?.className).toContain("text-body"); expect(first.children[1]?.textContent).toContain("https://box.tail1234.ts.net"); - // The secure-context sentence keeps its own line below the value, and it - // is still the address's own — one per address, comparative by repetition. - expect(first.children[1]?.textContent).toContain("Passkeys and secure cookies work at this address."); + // The secure-context sentence keeps its OWN element below the value (a + // merged line would pass a plain textContent check), and it is still the + // address's own — one per address, comparative by repetition. + const sentence = first.children[1]?.querySelector("p"); + expect(sentence?.textContent).toBe("Passkeys and secure cookies work at this address."); + // The value and its copy button come first; the sentence follows them. + expect(first.children[1]?.firstElementChild).not.toBe(sentence); const second = items[1] as HTMLElement; expect(second.children[0]?.textContent).toBe("Tailscale IP"); }); @@ -1187,8 +1191,8 @@ describe("NetworkPluginCard: the state matrix", () => { // here by scheme, by secure context or by label would make the page // contradict its own data for a reason no reader can see. await renderCard(row({ state: "joined", status: { state: "joined", addresses: ADDRESSES, hints: [] } })); - const list = screen.getByText(ADDRESSES[0]!.label).closest("dl")!; - const shown = Array.from(list.children, (item) => item.textContent ?? ""); + const list = screen.getByText(ADDRESSES[0]?.label ?? "").closest("dl"); + const shown = Array.from(list?.children ?? [], (item) => item.textContent ?? ""); expect(shown[0]).toContain("https://box.tail1234.ts.net"); expect(shown[1]).toContain("http://100.64.0.1:3080"); }); diff --git a/apps/server/web/src/components/__tests__/sharing-dialog.test.tsx b/apps/server/web/src/components/__tests__/sharing-dialog.test.tsx index 52a6514f8..29d2adcbe 100644 --- a/apps/server/web/src/components/__tests__/sharing-dialog.test.tsx +++ b/apps/server/web/src/components/__tests__/sharing-dialog.test.tsx @@ -134,7 +134,9 @@ describe("SharingDialog", () => { renderDialog(); await screen.findByText("Everyone"); fireEvent.click(screen.getByRole("button", { name: /^Remove access for/ })); - expect(screen.queryByText("You have unsaved sharing changes.")).toBeNull(); + // No unsaved-changes sentence (design rule: Save's disabled state carries + // that fact); the empty state names the PENDING result instead. + expect(screen.queryByText(/unsaved/i)).toBeNull(); expect(screen.getByText("No one will have shared access after you save.")).toBeTruthy(); expect(calls.some((call) => call.method === "PUT")).toBe(false); fireEvent.click(screen.getByRole("button", { name: "Save" })); diff --git a/apps/server/web/src/components/__tests__/supervision-dialog.test.tsx b/apps/server/web/src/components/__tests__/supervision-dialog.test.tsx index ef53dac3c..cb0aa769e 100644 --- a/apps/server/web/src/components/__tests__/supervision-dialog.test.tsx +++ b/apps/server/web/src/components/__tests__/supervision-dialog.test.tsx @@ -7,6 +7,12 @@ afterEach(cleanup); const noop = () => {}; +/** The base view with only the service's pane-safety answer changed. */ +function withPaneSafety(paneSafety: "kills" | "unknown") { + const view = deploymentView(); + return { ...view, service: { ...view.service, paneSafety } }; +} + describe("consequences", () => { it("names the platform's own agent and ends on the fact people are actually asking about", () => { const mac = consequences("app", "darwin", true); @@ -116,6 +122,58 @@ describe("SupervisionDialog", () => { expect(screen.getByText(/Stopped the server this app was running/)).toBeTruthy(); }); + it("states the lethal panes fact once: the notice carries it, the list drops it", () => { + // The filter is by the line's own text, not its position in the list, so + // a reorder of `consequences` cannot silently drop a different step while + // the notice repeats the panes one. + render( + , + ); + expect(screen.getAllByText("Every running subshell will be closed")).toHaveLength(1); + expect(screen.getByText("Quitting the app will stop the server")).toBeTruthy(); + expect(screen.getAllByRole("listitem")).toHaveLength(3); + }); + + it("says survival is undetermined once when the definition cannot be read", () => { + render( + , + ); + expect(screen.getAllByText("Whether running subshells survive could not be determined")).toHaveLength(1); + expect(screen.getAllByRole("listitem")).toHaveLength(3); + }); + + it("keeps every step in the list when the switch is not lethal", () => { + render( + , + ); + expect(screen.getAllByRole("listitem")).toHaveLength(4); + expect(screen.getByText("Running subshells keep running")).toBeTruthy(); + }); + it("shows the refusal where the person is", () => { render( void disabled={busy} /> {problem && ( -

+

{problem}

)} @@ -276,10 +274,7 @@ export function CreateBackupCard({ onBusy }: { onBusy?: (busy: boolean) => void disabled={busy} /> {problem && ( -

+

{problem}

)} diff --git a/apps/server/web/src/components/backups/field-problem-tone.ts b/apps/server/web/src/components/backups/field-problem-tone.ts new file mode 100644 index 000000000..fe54a7020 --- /dev/null +++ b/apps/server/web/src/components/backups/field-problem-tone.ts @@ -0,0 +1,16 @@ +import { cn } from "@internal/node-admin"; + +/** + * The tone of a backup field's validation sentence, decided the same way on + * every backup card (ruling 2026-09-30): gold means "nothing typed yet", red + * means "what you typed is wrong". + * + * The two cards once inferred the tone separately, one from the raw value and + * one from its trimmed form, so a whitespace-only field was red on Create and + * gold on Restore. A whitespace-only input is nothing typed, everywhere. + * A problem supplied from outside the form (a server refusal, a failed + * decrypt) is always the hard kind: something the person wrote was wrong. + */ +export function problemTone(value: string, suppliedProblem?: string | null): string { + return cn("text-detail", suppliedProblem || value.trim() !== "" ? "text-destructive" : "text-warning"); +} diff --git a/apps/server/web/src/components/backups/restore-backup-card.tsx b/apps/server/web/src/components/backups/restore-backup-card.tsx index a2d574fa1..f56322f42 100644 --- a/apps/server/web/src/components/backups/restore-backup-card.tsx +++ b/apps/server/web/src/components/backups/restore-backup-card.tsx @@ -1,4 +1,4 @@ -import { Button, cn, Input, Switch } from "@internal/node-admin"; +import { Button, Input, Switch } from "@internal/node-admin"; import { BACKUP_RESTORE_DEFAULTS, BACKUP_RESTORE_MODES, type RestoreMode } from "@internal/subshell-protocol"; import { useStore } from "@tanstack/react-form"; import { LoaderCircle } from "lucide-react"; @@ -19,6 +19,7 @@ import { type FieldProblems, fieldError, makeForm, useSubmitDisabled, useSubmitD import { setRestoreProgressActive } from "@/lib/restore-progress"; import { Card, CardContent, CardHeader, CardTitle } from "./backup-card"; import { BackupError, BackupFacts, BackupProgress, BackupWorkflow } from "./backup-workflow"; +import { problemTone } from "./field-problem-tone"; type InspectionDraft = { file: File | null; path: string; password: string; encrypted: boolean }; function inspectionProblems(draft: InspectionDraft): FieldProblems { @@ -422,11 +423,7 @@ export function RestoreBackupCard({ onBusy }: { onBusy?: (busy: boolean) => void onChange={(event) => field.handleChange(event.target.value)} /> {problem && ( - )} @@ -722,21 +719,34 @@ export function RestoreBackupCard({ onBusy }: { onBusy?: (busy: boolean) => void {item.description}
- {!inspection?.legacyDatabaseOnly && draft.mode === item.value && ( - - {textField("databasePath", "Database path (optional)")} - {textField("dataDir", "Data directory (optional)")} - {textField("configDir", "Configuration directory (optional)")} - {textField("baseUrl", "Control plane URL (optional)")} - {textField("host", "Bind address (optional)")} - {textField("port", "Port (optional)")} - {textField("trustedOrigins", "Trusted origins (optional)")} - - )} ))} + {/* The seven overrides apply to BOTH modes (the request sends + them identically however the mode is set), so they are a + named section below the group rather than a panel under + whichever option happens to be selected — flipping the + radio would otherwise teleport the whole block. */} + {!inspection?.legacyDatabaseOnly && ( + +
+ + Restore overrides + +

+ Leave a field empty to restore to the location or setting recorded in the backup. +

+
+ {textField("databasePath", "Database path (optional)")} + {textField("dataDir", "Data directory (optional)")} + {textField("configDir", "Configuration directory (optional)")} + {textField("baseUrl", "Control plane URL (optional)")} + {textField("host", "Bind address (optional)")} + {textField("port", "Port (optional)")} + {textField("trustedOrigins", "Trusted origins (optional)")} +
+ )} {inspection?.legacyDatabaseOnly && (

This backup contains only the database. It restores into this server using its current @@ -1005,10 +1015,7 @@ export function RestoreBackupCard({ onBusy }: { onBusy?: (busy: boolean) => void

diff --git a/apps/server/web/src/components/fact-list.tsx b/apps/server/web/src/components/fact-list.tsx index 842c1640c..30d05dc6b 100644 --- a/apps/server/web/src/components/fact-list.tsx +++ b/apps/server/web/src/components/fact-list.tsx @@ -1,17 +1,37 @@ -import { Fact } from "@internal/node-admin"; +import { CopyableValue, Fact } from "@internal/node-admin"; import type { ReactNode } from "react"; -import { CopyButton } from "@/components/copy-button"; -/** Facts keep their values readable, including long paths and fingerprints. */ -export function FactList({ rows }: { rows: { label: string; value: ReactNode; mono?: boolean; copyText?: string }[] }) { +/** One labelled fact: a quiet label over a readable value, optionally copied. */ +export interface FactRow { + /** The quiet label above the value; also names the copy button. */ + label: string; + /** The value. Ignored when `copyText` is set, since the copy row shows that text itself. */ + value: ReactNode; + /** Render the value in the mono voice, same size. */ + mono?: boolean; + /** The exact text to copy, shown in full beside its copy affordance. */ + copyText?: string; +} + +/** + * Facts keep their values readable, including long paths and fingerprints. + * + * A copyable row renders through `CopyableValue`, the same affordance the + * status cards and address lists use, rather than composing a bare + * `CopyButton`: HTTP LAN pages have no Clipboard API, and the bare button + * silently did nothing there where the shared row falls back to + * select-and-copy. + */ +export function FactList({ rows }: { rows: FactRow[] }) { return (
{rows.map(({ label, value, mono, copyText }) => ( -
- {value} - {copyText !== undefined && } -
+ {copyText !== undefined ? ( + + ) : ( +
{value}
+ )}
))}
diff --git a/apps/server/web/src/components/networking/__tests__/addresses-card.test.ts b/apps/server/web/src/components/networking/__tests__/addresses-card.test.ts index 7796cee94..b13e26124 100644 --- a/apps/server/web/src/components/networking/__tests__/addresses-card.test.ts +++ b/apps/server/web/src/components/networking/__tests__/addresses-card.test.ts @@ -1,5 +1,5 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { movesThisAppsWindow } from "@/components/networking/addresses-card"; +import { isTouchedDraft, movesThisAppsWindow } from "@/components/networking/addresses-card"; import { resetDesktopShellForTests } from "@/lib/desktop"; /** @@ -53,6 +53,29 @@ afterEach(() => { setUrl(HOME); }); +describe("isTouchedDraft", () => { + test("a plain key compares exactly", () => { + expect(isTouchedDraft("APP_BASE_URL", "http://box:3080", "http://box:3080")).toBe(false); + expect(isTouchedDraft("APP_BASE_URL", "http://box:3081", "http://box:3080")).toBe(true); + }); + + test("an origins retyped the way the field shows them is no change", () => { + // The field seeds from displayValue (comma-separated), so a person who + // edits the box and types back the same list has changed nothing, even + // though the raw strings differ by spaces and commas. + expect(isTouchedDraft("TRUSTED_ORIGINS", "http://a, http://b", "http://a,http://b")).toBe(false); + expect(isTouchedDraft("TRUSTED_ORIGINS", "http://a, http://b,", "http://a,http://b")).toBe(false); + }); + + test("a legacy space-separated stored line compares through its own display form", () => { + // config.env hand-edited into one space-separated line is the shape + // displayValue exists to read. Seeding, editing, and retyping must land + // back on "untouched", or Save (and the restart banner) light for a no-op. + expect(isTouchedDraft("TRUSTED_ORIGINS", "http://a, http://b", "http://a http://b")).toBe(false); + expect(isTouchedDraft("TRUSTED_ORIGINS", "http://a, http://c", "http://a http://b")).toBe(true); + }); +}); + describe("movesThisAppsWindow", () => { test("warns inside Subshell Server, on http, for an https draft", () => { surface(UA_SERVER_APP, HOME); diff --git a/apps/server/web/src/components/networking/addresses-card.tsx b/apps/server/web/src/components/networking/addresses-card.tsx index 838ad5c77..9dc5f8f48 100644 --- a/apps/server/web/src/components/networking/addresses-card.tsx +++ b/apps/server/web/src/components/networking/addresses-card.tsx @@ -195,6 +195,24 @@ function displayValue(key: EditableKey, saved: string): string { : saved; } +/** + * Whether a draft is a real change from what is stored. + * + * Both sides go through the full display-then-wire pipeline: the field was + * SEEDED from {@link displayValue}, which splits on commas AND whitespace, so + * the saved side has to pass through it too. A config.env storing one legacy + * space-separated line would otherwise never compare equal to the + * comma-separated text a person retypes from the field, and Save stayed lit + * (with the restart banner armed) for what is semantically no change. + * + * @param key - the setting being compared + * @param draft - exactly what the field holds now + * @param saved - the stored value, as the server reported it + */ +export function isTouchedDraft(key: EditableKey, draft: string, saved: string): boolean { + return wireValue(key, draft) !== wireValue(key, displayValue(key, saved)); +} + /** * Where this server listens and which addresses a browser may use (spec * 2026-09-12 § 4.2). @@ -211,8 +229,8 @@ export function AddressesCard({ view, restart }: { view: ServerDeployment; resta const [drafts, setDrafts] = useState>>({}); const [confirming, setConfirming] = useState(false); const update = useUpdateServerConfig(); - const touched = (Object.keys(drafts) as EditableKey[]).filter( - (key) => wireValue(key, drafts[key] ?? "") !== wireValue(key, view.settings[key].saved), + const touched = (Object.keys(drafts) as EditableKey[]).filter((key) => + isTouchedDraft(key, drafts[key] ?? "", view.settings[key].saved), ); const needsRestart = touched.some((key) => !LIVE_KEYS.has(key)); const fieldFailure = invalidField(update.error); diff --git a/apps/server/web/src/components/networking/network-plugin-card.tsx b/apps/server/web/src/components/networking/network-plugin-card.tsx index 75df4ebef..13a5ab891 100644 --- a/apps/server/web/src/components/networking/network-plugin-card.tsx +++ b/apps/server/web/src/components/networking/network-plugin-card.tsx @@ -66,7 +66,7 @@ function JoinedFacts({ row, status, compact }: { row: NetworkRow; status: Networ const identity = status.identity; if (!identity && !process) return null; return ( -
+
{identity?.network && {identity.network}} {identity?.hostname && {identity.hostname}} {identity?.version && ( diff --git a/apps/server/web/src/components/nodes/node-key-setup.tsx b/apps/server/web/src/components/nodes/node-key-setup.tsx index 88300070d..767b4addc 100644 --- a/apps/server/web/src/components/nodes/node-key-setup.tsx +++ b/apps/server/web/src/components/nodes/node-key-setup.tsx @@ -341,7 +341,9 @@ export function NodeKeySetup({ { label: "Server address", value: selected, copyText: selected }, { label: "Setup key", - value: keyText ?? "Generate setup key first", + // The pending-state placeholder is an instruction, not a value: + // a body-foreground row would read as a strangely worded key. + value: keyText ?? Generate setup key first, mono: keyText !== null, copyText: keyText ?? undefined, }, diff --git a/apps/server/web/src/components/presets/command-paste-field.tsx b/apps/server/web/src/components/presets/command-paste-field.tsx index 5aa34bbd5..05bb7829a 100644 --- a/apps/server/web/src/components/presets/command-paste-field.tsx +++ b/apps/server/web/src/components/presets/command-paste-field.tsx @@ -131,7 +131,7 @@ export function CommandPasteField({ // (`--allow a --allow b`), so the index is the only key. // biome-ignore lint/suspicious/noArrayIndexKey: see above - {row.value || "No value"} + {row.value || "(empty)"} ))}
diff --git a/apps/server/web/src/components/service/restart-dialog.tsx b/apps/server/web/src/components/service/restart-dialog.tsx index f1f1fa42d..48173693b 100644 --- a/apps/server/web/src/components/service/restart-dialog.tsx +++ b/apps/server/web/src/components/service/restart-dialog.tsx @@ -107,7 +107,7 @@ export function RestartDialog({ ? "Restarting the Docker container closes every running subshell." : view.service.paneSafety === "kills" ? `This server's service definition will close every running subshell. Rewrite it by running ${REINSTALL_COMMAND} on this machine, or restart anyway.` - : `We couldn't determine whether running subshells will survive. Restarting may close them. Rewrite the service definition by running ${REINSTALL_COMMAND} on this machine, or restart anyway.`} + : `We couldn’t determine whether running subshells will survive. Restarting may close them. Rewrite the service definition by running ${REINSTALL_COMMAND} on this machine, or restart anyway.`} )} {enables ? ( diff --git a/apps/server/web/src/components/service/supervision-dialog.tsx b/apps/server/web/src/components/service/supervision-dialog.tsx index 97b1f8c17..e26db621a 100644 --- a/apps/server/web/src/components/service/supervision-dialog.tsx +++ b/apps/server/web/src/components/service/supervision-dialog.tsx @@ -13,13 +13,34 @@ import { import { WarningNotice } from "@/components/ui/notice"; import type { PaneSafety, ServerDeployment } from "@/types/server-deployment"; +/** + * The panes line, shared by {@link consequences} and the dialog. + * + * The dialog drops this line from the list when the switch is lethal, because + * the `WarningNotice` states it louder — the comparison is by the line's own + * text, never by its position in the list. + * + * **Read, not assumed.** This line said "Running subshells keep running" + * unconditionally, and on a definition predating `KillMode=process` the + * opposite was true: removing it takes every live subshell's tmux server + * with it. A dialog that promises the survival of other people's work and + * then destroys it is worse than one that says nothing. + */ +function panesConsequence(paneSafety: PaneSafety): string { + return paneSafety === "keeps" + ? "Running subshells keep running" + : paneSafety === "kills" + ? "Every running subshell will be closed" + : "Whether running subshells survive could not be determined"; +} + /** * What switching to `target` will do, in the order it happens. * * Exported so the words are testable as data, the way `recovery-model.ts` - * treats the assistant's. The two lists end on the same fact — running - * subshells survive either way — because that is the question anyone - * hesitating over this dialog is actually asking. + * treats the assistant's. The two lists end on the same fact — what becomes + * of running subshells — because that is the question anyone hesitating over + * this dialog is actually asking. */ export function consequences( target: SupervisionMode, @@ -28,17 +49,7 @@ export function consequences( paneSafety: PaneSafety = "keeps", ): string[] { const agent = platform === "darwin" ? "launchd agent" : "systemd user service"; - // **Read, not assumed.** This line said "Running subshells keep running" - // unconditionally, and on a definition predating `KillMode=process` the - // opposite was true: removing it takes every live subshell's tmux server - // with it. A dialog that promises the survival of other people's work and - // then destroys it is worse than one that says nothing. - const panes = - paneSafety === "keeps" - ? "Running subshells keep running" - : paneSafety === "kills" - ? "Every running subshell will be closed" - : "Whether running subshells survive could not be determined"; + const panes = panesConsequence(paneSafety); if (target === "app") { return [ `Removes the ${agent}`, @@ -107,6 +118,7 @@ export function SupervisionDialog({ // Only the Service→App direction removes a definition, so only that // direction can be refused on pane safety. const lethal = toApp && view.service.paneSafety !== "keeps"; + const panesLine = panesConsequence(view.service.paneSafety); return ( @@ -122,15 +134,17 @@ export function SupervisionDialog({
    {target && consequences(target, view.platform, autostart, view.service.paneSafety) - .filter((_, index) => !lethal || index !== 3) + // When the switch is lethal the panes line moves into the + // notice below, stated louder rather than dotted among the + // steps. Matched by its own text, never by position: the line + // is shared with `consequences` so the two cannot drift. + .filter((line) => !lethal || line !== panesLine) .map((line) => (
  • • - - {line} - + {line}
  • ))}
@@ -142,11 +156,7 @@ export function SupervisionDialog({ )} {lethal && ( -

- {view.service.paneSafety === "kills" - ? "Every running subshell will be closed" - : "Whether running subshells survive could not be determined"} -

+

{panesLine}

{view.service.paneSafety === "kills" ? "This machine's service definition predates the setting that spares live panes. Running `subshell-server service install` on that machine rewrites it." diff --git a/apps/server/web/src/components/ui/choice-fields.tsx b/apps/server/web/src/components/ui/choice-fields.tsx index c24c03516..bbdc04485 100644 --- a/apps/server/web/src/components/ui/choice-fields.tsx +++ b/apps/server/web/src/components/ui/choice-fields.tsx @@ -1,6 +1,16 @@ import type { ReactNode } from "react"; -/** Keep a choice's controls beside it, with a boundary distinct from its label. */ +/** + * Keep a choice's controls beside it, with a boundary distinct from its label. + * + * The panel lives inside the option's column, which for a non-last option + * means inside the `role="radiogroup"` element: proximity is what the panel + * exists to show, and the two placements cannot both hold for a middle option. + * `aria-labelledby` makes it a named landmark (reachable by landmark + * navigation), and the group's arrow keys move only between the radios, so + * fields stay inside the group element deliberately (docs/design-system.md, + * Dependent forms, 2026-10-17). + */ export function ChoiceFields({ labelledBy, children }: { labelledBy: string; children: ReactNode }) { return (

Date: Sat, 17 Oct 2026 02:17:09 -0700 Subject: [PATCH 3/6] docs: correct the sharing claim and widen the coverage note in the audit The first pass wrote that sharing lost a separate unsaved-changes sentence; it never had one, and the accurate rule is that Save's disabled state carries the pending-change fact. The coverage note now names the tests the review round added (tone split, supervision wording, restore override placement, draft comparison) and the e2e retargeting. Co-Authored-By: Claude Fable 5 --- docs/ux-review-2026-10-17.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/ux-review-2026-10-17.md b/docs/ux-review-2026-10-17.md index e1992384b..26fca303b 100644 --- a/docs/ux-review-2026-10-17.md +++ b/docs/ux-review-2026-10-17.md @@ -12,7 +12,7 @@ components; it is not a claim that every possible product state was exercised. | Read-only facts | Labels and values had similar size and color, and several screens implemented their own pairs. Shared `Fact` now uses smaller muted labels and body-sized foreground values, including monospace values. | Runtime, Status, node details, SSH trust, Networking, clone, enrollment, backup summaries, destination verification, provider removal, command previews | | Long values | Some review values were truncated or could force a wide layout. Facts wrap complete values; machine facts collapse to one column on narrow screens. | Addresses, paths, fingerprints, commands, SSH summaries, node metadata | | Radio-dependent fields | Fields below the whole group made their association unclear. The selected option now contains an inset, bordered field panel immediately below its description, outside its clickable label. | SSH authentication, SSH forwarding, Restore source and mode | -| Save availability | Touched fields and unchanged drafts could enable Save. Save now compares the effective draft with saved data, including reverting edits. Sharing no longer displays a separate unsaved-changes sentence. | Sharing, profile, device name, instance name, providers, prompts, prompt stacks, network plugin settings, server addresses | +| Save availability | Touched fields and unchanged drafts could enable Save. Save now compares the effective draft with saved data, including reverting edits; the disabled Save and its reason carry the pending-change fact, so no separate unsaved-changes sentence is shown. | Sharing, profile, device name, instance name, providers, prompts, prompt stacks, network plugin settings, server addresses | | Notices and validation | Consequence notices and error styling varied. Shared notices distinguish warnings from failures; backup validation distinguishes missing input from an invalid supplied value. | Sharing, restart, update, supervision, destination verification, backup creation and restore, generated API keys | | Review information | Destination identity details were hidden behind a disclosure. Destination and copyable fingerprint are now visible at the trust decision. Profile email is presented as a fact instead of an editable-looking field. | SSH verification, account profile | @@ -46,10 +46,13 @@ The SSH dialog had no horizontal overflow, and Restore exposed its associated region. Runtime and Restore screenshots were visually inspected. Component tests cover the changed radio association, sharing change/revert -behavior, backup validation, stack editing, address presentation, enrollment -facts, and restart wording. Workspace build, type checks, lint, and tests are -the automated verification for the changes; these are distinct from browser -workflow coverage. +behavior, backup validation and its gold/red tone split, stack editing, address +presentation, enrollment facts, restart and supervision consequence wording, +restore override placement across modes, origins-draft comparison, and the +no-unsaved-message posture. The destination-confirmation e2e spec and its docs +screenshot were retargeted at the always-visible fingerprint. Workspace build, +type checks, lint, and tests are the automated verification for the changes; +these are distinct from browser workflow coverage. ## Limits From 9a6b84c0bd7d1be9871cfa107c130efa61798cba Mon Sep 17 00:00:00 2001 From: Theo Gravity Date: Sat, 17 Oct 2026 03:12:37 -0700 Subject: [PATCH 4/6] test: pin Save-availability on the five surfaces the review flagged MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The unchanged-draft rule shipped tested on four surfaces and untested on five. The one that writes to the server needed it most: network-settings-form now proves a reverted field is dropped from the PATCH body (not just from the button), and its boolean and secret branches are exercised too. The profile, device-name, instance-name, and provider surfaces get mount-disabled, type-enabled, revert-deadened tests, so the rule is pinned at all nine. Also the review's NITs: the two reverted-draft tooltips move to the "No X changes to save." wording they now actually cover, the two no-op `{ … }` JSX wrappers left by the removed conditionals are unwrapped in ssh-wizard, and the supervision notice's lead sentence gets its period. Co-Authored-By: Claude Fable 5 --- .../__tests__/device-name-card.test.tsx | 16 ++++ .../__tests__/instance-name-card.test.tsx | 16 ++++ .../__tests__/profile-card.test.tsx | 22 +++++ .../__tests__/supervision-dialog.test.tsx | 4 +- .../auth/__tests__/provider-dialog.test.tsx | 24 ++++++ .../web/src/components/connect/ssh-wizard.tsx | 34 ++++---- .../__tests__/network-settings-form.test.tsx | 81 ++++++++++++++++++- .../components/networking/addresses-card.tsx | 2 +- .../networking/network-settings-form.tsx | 2 +- .../components/service/supervision-dialog.tsx | 5 +- 10 files changed, 181 insertions(+), 25 deletions(-) diff --git a/apps/server/web/src/components/__tests__/device-name-card.test.tsx b/apps/server/web/src/components/__tests__/device-name-card.test.tsx index 2d6efd008..e4369476f 100644 --- a/apps/server/web/src/components/__tests__/device-name-card.test.tsx +++ b/apps/server/web/src/components/__tests__/device-name-card.test.tsx @@ -47,4 +47,20 @@ describe("DeviceNameCard", () => { render(); expect((screen.getByLabelText("Name") as HTMLInputElement).value).toBe("Laptop"); }); + + it("disables Save when the field still holds the stored name", () => { + // The unchanged-draft rule: the button is dead at rest, lights for a real + // edit, and goes dead again when the edit is put back — a keypress is not + // a change. The stored-name path also proves the compare is against what + // was saved, not against a blank. + window.localStorage.setItem(DEVICE_NAME_KEY, "Laptop"); + render(); + const save = () => screen.getByRole("button", { name: "Save" }) as HTMLButtonElement; + expect(save().matches(":disabled, [aria-disabled=true]")).toBe(true); + expect(save().getAttribute("aria-description")).toBe("No device name changes to save."); + fireEvent.change(screen.getByLabelText("Name"), { target: { value: "Kitchen display" } }); + expect(save().matches(":disabled, [aria-disabled=true]")).toBe(false); + fireEvent.change(screen.getByLabelText("Name"), { target: { value: "Laptop" } }); + expect(save().matches(":disabled, [aria-disabled=true]")).toBe(true); + }); }); diff --git a/apps/server/web/src/components/__tests__/instance-name-card.test.tsx b/apps/server/web/src/components/__tests__/instance-name-card.test.tsx index ca1637d19..788f43a78 100644 --- a/apps/server/web/src/components/__tests__/instance-name-card.test.tsx +++ b/apps/server/web/src/components/__tests__/instance-name-card.test.tsx @@ -82,6 +82,22 @@ describe("InstanceNameCard", () => { await waitFor(() => expect((screen.getByLabelText("Name") as HTMLInputElement).value).toBe("theo-desktop")); }); + it("disables Save at rest and on a revert, opens it on a real change", async () => { + // The unchanged-draft rule, on the card that seeds from the server: the + // field opens showing the stored name, so Save starts dead; a genuine + // edit lights it; retyping the stored name kills it again. + stubFetch((s) => s); + renderCard("Prod plane"); + await screen.findByLabelText("Name"); + const save = () => screen.getByRole("button", { name: "Save" }) as HTMLButtonElement; + expect(save().matches(":disabled, [aria-disabled=true]")).toBe(true); + expect(save().getAttribute("aria-description")).toBe("No instance name changes to save."); + fireEvent.change(screen.getByLabelText("Name"), { target: { value: "Homelab" } }); + expect(save().matches(":disabled, [aria-disabled=true]")).toBe(false); + fireEvent.change(screen.getByLabelText("Name"), { target: { value: "Prod plane" } }); + expect(save().matches(":disabled, [aria-disabled=true]")).toBe(true); + }); + it("reports a failed save instead of implying it worked", async () => { const original = globalThis.fetch; restore.push(() => { diff --git a/apps/server/web/src/components/__tests__/profile-card.test.tsx b/apps/server/web/src/components/__tests__/profile-card.test.tsx index 77e937223..cd2db1b5a 100644 --- a/apps/server/web/src/components/__tests__/profile-card.test.tsx +++ b/apps/server/web/src/components/__tests__/profile-card.test.tsx @@ -71,6 +71,28 @@ describe("ProfileCard", () => { expect(await screen.findByText("saved")).toBeDefined(); }); + it("disables Save at rest, opens it on a real edit, and re-deadens it on a revert", async () => { + // The unchanged-draft rule this PR added: Save is dead while the field + // shows the saved name, and a type-then-retype-the-same-name is no change + // either — the draft is compared to the stored value, not to "was a key + // pressed". The reason rides the disabled explanation, as on every card. + let pressed = 0; + renderCard(async () => { + pressed++; + return { error: null }; + }); + const input = (await screen.findByLabelText("Name")) as HTMLInputElement; + const save = () => screen.getByRole("button", { name: "Save" }) as HTMLButtonElement; + expect(save().matches(":disabled, [aria-disabled=true]")).toBe(true); + expect(save().getAttribute("aria-description")).toBe("No profile changes to save."); + fireEvent.change(input, { target: { value: "Thea" } }); + expect(save().matches(":disabled, [aria-disabled=true]")).toBe(false); + fireEvent.change(input, { target: { value: "Old Name" } }); // back to stored + expect(save().matches(":disabled, [aria-disabled=true]")).toBe(true); + expect(save().getAttribute("aria-description")).toBe("No profile changes to save."); + expect(pressed).toBe(0); + }); + it("keeps the draft and reports the error when the save fails", async () => { renderCard(async () => ({ error: { message: "Server said no" } })); const input = (await screen.findByLabelText("Name")) as HTMLInputElement; diff --git a/apps/server/web/src/components/__tests__/supervision-dialog.test.tsx b/apps/server/web/src/components/__tests__/supervision-dialog.test.tsx index cb0aa769e..69c6e26ae 100644 --- a/apps/server/web/src/components/__tests__/supervision-dialog.test.tsx +++ b/apps/server/web/src/components/__tests__/supervision-dialog.test.tsx @@ -137,7 +137,7 @@ describe("SupervisionDialog", () => { onConfirm={noop} />, ); - expect(screen.getAllByText("Every running subshell will be closed")).toHaveLength(1); + expect(screen.getAllByText("Every running subshell will be closed.")).toHaveLength(1); expect(screen.getByText("Quitting the app will stop the server")).toBeTruthy(); expect(screen.getAllByRole("listitem")).toHaveLength(3); }); @@ -154,7 +154,7 @@ describe("SupervisionDialog", () => { onConfirm={noop} />, ); - expect(screen.getAllByText("Whether running subshells survive could not be determined")).toHaveLength(1); + expect(screen.getAllByText("Whether running subshells survive could not be determined.")).toHaveLength(1); expect(screen.getAllByRole("listitem")).toHaveLength(3); }); diff --git a/apps/server/web/src/components/auth/__tests__/provider-dialog.test.tsx b/apps/server/web/src/components/auth/__tests__/provider-dialog.test.tsx index 62ca362a8..854ee7e18 100644 --- a/apps/server/web/src/components/auth/__tests__/provider-dialog.test.tsx +++ b/apps/server/web/src/components/auth/__tests__/provider-dialog.test.tsx @@ -292,6 +292,30 @@ describe("ProviderDialog", () => { } }); + it("edit mode starts unchanged, so Save is dead until something actually differs", async () => { + // The unchanged-draft rule on the surface whose save WRITES provider config: + // the field opens seeded to the stored row, so Save starts dead and says + // why; a real edit lights it; putting the edit back kills it again. The + // compare runs over the wire shape (trimmed name/issuer/clientId, the + // order-insensitive domain list), not over "was a key pressed". + const { restore } = mockFetch({ appBaseUrl: "https://plane.example" }); + try { + renderDialog({ provider: view({ allowedDomains: ["example.test"] }) }); + await settle(); + const save = () => screen.getByRole("button", { name: "Save" }) as HTMLButtonElement; + expect(save().matches(":disabled, [aria-disabled=true]")).toBe(true); + expect(save().getAttribute("aria-description")).toBe("No provider changes to save."); + fireEvent.change(screen.getByLabelText("Name"), { target: { value: "Workspace Google" } }); + expect(save().matches(":disabled, [aria-disabled=true]")).toBe(false); + // Retyping the domain it already had (the list sorts, order is noise). + fireEvent.change(screen.getByLabelText("Name"), { target: { value: "Google" } }); + fireEvent.change(screen.getByLabelText(/Allowed e-mail domains/), { target: { value: "example.test" } }); + expect(save().matches(":disabled, [aria-disabled=true]")).toBe(true); + } finally { + restore(); + } + }); + it("clicking out or pressing Escape keeps the form; a half-typed issuer survives", async () => { // The loss this pins: an outside press discarded the whole dialog with a // half-entered issuer in it (the 2026-09-30 form-dialog ruling, now read diff --git a/apps/server/web/src/components/connect/ssh-wizard.tsx b/apps/server/web/src/components/connect/ssh-wizard.tsx index 4a7a431a9..e975f5c68 100644 --- a/apps/server/web/src/components/connect/ssh-wizard.tsx +++ b/apps/server/web/src/components/connect/ssh-wizard.tsx @@ -190,18 +190,16 @@ export function SshWizard({ /> Use the connecting node’s keys - { - - {machine?.node.name ?? "Choose a node to connect from first"} - - } + + {machine?.node.name ?? "Choose a node to connect from first"} + @@ -325,13 +323,11 @@ export function SshWizard({ /> Enter a password when connecting - { - - {presetEditor - ? "When creating a new SSH subshell with this preset, enter your password in the terminal when SSH asks for it. The preset won’t save your password." - : "Enter your password in the terminal when SSH asks for it. Subshell won’t save it."} - - } + + {presetEditor + ? "When creating a new SSH subshell with this preset, enter your password in the terminal when SSH asks for it. The preset won’t save your password." + : "Enter your password in the terminal when SSH asks for it. Subshell won’t save it."} + diff --git a/apps/server/web/src/components/networking/__tests__/network-settings-form.test.tsx b/apps/server/web/src/components/networking/__tests__/network-settings-form.test.tsx index 6ae20ef89..350a75efe 100644 --- a/apps/server/web/src/components/networking/__tests__/network-settings-form.test.tsx +++ b/apps/server/web/src/components/networking/__tests__/network-settings-form.test.tsx @@ -1,9 +1,15 @@ import { afterEach, describe, expect, it } from "bun:test"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { cleanup, fireEvent, render, screen } from "@testing-library/react"; +import { cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react"; import { NetworkSettingsForm } from "@/components/networking/network-settings-form"; import type { NetworkRow } from "@/types/network"; +const originalFetch = globalThis.fetch; +afterEach(() => { + cleanup(); + globalThis.fetch = originalFetch; +}); + /** * The gating sweep (spec 2026-09-29): Save settings is disabled while a * required non-secret is empty — the SAME rule the card's Connect gate @@ -90,4 +96,77 @@ describe("NetworkSettingsForm gating", () => { fireEvent.change(screen.getByLabelText(/Tailscale port/), { target: { value: "3478" } }); expect(saveButton().matches(":disabled, [aria-disabled=true]")).toBe(false); }); + + it("sends only the keys that still differ from saved, not a reverted one", async () => { + // THE payload change this PR made: the body used to be every touched draft + // (a reverted key rode along); now it is the effective-diff set. A + // comparison bug here would silently write the reverted value back, so it + // is pinned at the wire, not just on the button. + let patched: Record | null = null; + globalThis.fetch = (async (_url: string, init?: RequestInit) => { + patched = JSON.parse(String(init?.body)) as Record; + return Response.json({ ok: true }); + }) as unknown as typeof fetch; + renderForm( + rowWith({ + settingsFields: [ + { key: "controlUrl", label: "Control server URL", type: "string", required: true }, + { key: "noise", label: "Tailscale port", type: "number" }, + ] as unknown as NetworkRow["settingsFields"], + settings: { controlUrl: "https://control.example" }, + }), + ); + const control = screen.getByLabelText(/Control server URL/); + const noise = screen.getByLabelText(/Tailscale port/); + // Change controlUrl, then put it back; change noise and leave it. + fireEvent.change(control, { target: { value: "https://other.example" } }); + fireEvent.change(control, { target: { value: "https://control.example" } }); + fireEvent.change(noise, { target: { value: "3478" } }); + expect(saveButton().matches(":disabled, [aria-disabled=true]")).toBe(false); + fireEvent.click(saveButton()); + await waitFor(() => expect(patched).not.toBeNull()); + // `patched` is only ever assigned from the fetch closure, so TypeScript + // still reads its flow-narrowed type as null; the value is the wire body. + expect(patched as Record | null).toEqual({ noise: "3478" }); + }); + + it("a boolean or secret reverted to its saved state is not a change at all", () => { + renderForm( + rowWith({ + settingsFields: [ + { key: "autoStart", label: "Start on boot", type: "boolean" }, + { key: "token", label: "Tunnel token", type: "secret" }, + ] as unknown as NetworkRow["settingsFields"], + settings: { autoStart: "true", token: { set: true } }, + }), + ); + // Toggling the switch and typing into the secret make it dirty; putting + // both back — the switch to its saved true, the secret cleared to empty — + // returns Save to dead, because neither is a change from what is stored. + fireEvent.click(screen.getByRole("switch", { name: "Start on boot" })); + fireEvent.change(screen.getByLabelText(/Tunnel token/), { target: { value: "typed" } }); + expect(saveButton().matches(":disabled, [aria-disabled=true]")).toBe(false); + fireEvent.click(screen.getByRole("switch", { name: "Start on boot" })); + fireEvent.change(screen.getByLabelText(/Tunnel token/), { target: { value: "" } }); + expect(saveButton().matches(":disabled, [aria-disabled=true]")).toBe(true); + }); + + it("says so when nothing changed, in the reverted case included", () => { + renderForm( + rowWith({ + settingsFields: [ + { key: "noise", label: "Tailscale port", type: "number" }, + ] as unknown as NetworkRow["settingsFields"], + settings: { noise: "2000" }, + }), + ); + // Untouched, and touched-then-reverted, wear the same sentence: Save is + // dead with "No network setting changes to save." both times (the wording + // this PR settled on across the nine surfaces). + expect(saveButton().matches(":disabled, [aria-disabled=true]")).toBe(true); + expect(saveButton().getAttribute("aria-description")).toBe("No network setting changes to save."); + fireEvent.change(screen.getByLabelText(/Tailscale port/), { target: { value: "2000" } }); + expect(saveButton().matches(":disabled, [aria-disabled=true]")).toBe(true); + expect(saveButton().getAttribute("aria-description")).toBe("No network setting changes to save."); + }); }); diff --git a/apps/server/web/src/components/networking/addresses-card.tsx b/apps/server/web/src/components/networking/addresses-card.tsx index 9dc5f8f48..929f32ccb 100644 --- a/apps/server/web/src/components/networking/addresses-card.tsx +++ b/apps/server/web/src/components/networking/addresses-card.tsx @@ -408,7 +408,7 @@ export function AddressesCard({ view, restart }: { view: ServerDeployment; resta ? "Wait for the addresses to save." : invalid ? "Fix the invalid addresses before saving." - : "Change an address before saving." + : "No address changes to save." } onClick={save} > diff --git a/apps/server/web/src/components/networking/network-settings-form.tsx b/apps/server/web/src/components/networking/network-settings-form.tsx index 75d6c6846..8684b7237 100644 --- a/apps/server/web/src/components/networking/network-settings-form.tsx +++ b/apps/server/web/src/components/networking/network-settings-form.tsx @@ -283,7 +283,7 @@ export function NetworkSettingsForm({ ? "Wait for the network action to finish." : missingRequired ? "Complete the required network settings first." - : "Change a setting before saving." + : "No network setting changes to save." } onClick={save} > diff --git a/apps/server/web/src/components/service/supervision-dialog.tsx b/apps/server/web/src/components/service/supervision-dialog.tsx index e26db621a..b84ec5fe7 100644 --- a/apps/server/web/src/components/service/supervision-dialog.tsx +++ b/apps/server/web/src/components/service/supervision-dialog.tsx @@ -156,7 +156,10 @@ export function SupervisionDialog({ )} {lethal && ( -

{panesLine}

+ {/* The line is list-item grammar elsewhere (no terminal punctuation); + this is the one place it is read as prose, so it gets its period + here rather than in every bullet. */} +

{panesLine}.

{view.service.paneSafety === "kills" ? "This machine's service definition predates the setting that spares live panes. Running `subshell-server service install` on that machine rewrites it." From 322578f2badef19e29f0189e8af811aa302f6c43 Mon Sep 17 00:00:00 2001 From: Theo Gravity Date: Sat, 17 Oct 2026 03:39:39 -0700 Subject: [PATCH 5/6] test: close the round-3 coverage gaps and give the docs work its vehicle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The prompt editor's edit mode now has its own pin (create mode can never see the unchanged-draft path, and the test file rendered create only), and the backup card's gold side — blur the empty box, get text-warning — is asserted next to the red side the retarget left alone. The changeset gains "@internal/docs": minor, which is what drives the docs.yml deploy; without it the rewritten destination-confirmation guide and its screenshot would sit unpublished until some later docs change happened to carry a bump. The per-app AGENTS.md line that still described the removed "Verification details" disclosure now says the confirmation shows the fingerprint outright, and two prose nits (colour spelling, an over-length wrapped rule line) went with it. Co-Authored-By: Claude Fable 5 --- .changeset/tidy-dashboard-forms.md | 3 +- apps/server/web/AGENTS.md | 4 +- .../__tests__/backup-settings.test.tsx | 8 +++ .../__tests__/prompt-form-dialog.test.tsx | 54 ++++++++++++++++++- docs/design-system.md | 4 +- docs/ux-review-2026-10-17.md | 2 +- 6 files changed, 67 insertions(+), 8 deletions(-) diff --git a/.changeset/tidy-dashboard-forms.md b/.changeset/tidy-dashboard-forms.md index 2dd74d378..77225b379 100644 --- a/.changeset/tidy-dashboard-forms.md +++ b/.changeset/tidy-dashboard-forms.md @@ -1,6 +1,7 @@ --- "@internal/server": patch "@internal/node": patch +"@internal/docs": minor --- -Make dashboard information easier to scan with consistent labels, readable values, and wrapping for long paths and addresses. Keep conditional fields beneath their selected radio option, disable Save for unchanged drafts, and clarify warnings and validation. Apply the shared fact styling to the node dashboard as well. +Make dashboard information easier to scan with consistent labels, readable values, and wrapping for long paths and addresses. Keep conditional fields beneath their selected radio option, disable Save for unchanged drafts, and clarify warnings and validation. Apply the shared fact styling to the node dashboard as well. On the docs site, the SSH destination-confirmation guide and its screenshot now match the always-visible fingerprint. diff --git a/apps/server/web/AGENTS.md b/apps/server/web/AGENTS.md index 907aa219e..db07bd885 100644 --- a/apps/server/web/AGENTS.md +++ b/apps/server/web/AGENTS.md @@ -440,8 +440,8 @@ Changed identities never use that prompt. Settings → Presets has Agent and SSH tabs; the SSH tab manages saved connection choices, not host keys. Applying a preset clears any local key selection. Saving a local-key preset retains only the authentication choice, never credentials or approval. Recent destinations -stay in the launch suggestions; `/settings/ssh` redirects to `/presets?type=ssh`. Verification details can reveal the public fingerprint without -requiring a user to paste or manage key material. +stay in the launch suggestions; `/settings/ssh` redirects to `/presets?type=ssh`. The confirmation shows the destination's public fingerprint outright +(copyable), with no key material for the user to paste or manage. Old `/connect` links open the same subshell dialog through `/new?kind=ssh`. Failed reads must stay distinct from empty lists, with retry actions. Read `docs/launch-form-picker.md` for the diff --git a/apps/server/web/src/components/__tests__/backup-settings.test.tsx b/apps/server/web/src/components/__tests__/backup-settings.test.tsx index 68bd11075..f02443fed 100644 --- a/apps/server/web/src/components/__tests__/backup-settings.test.tsx +++ b/apps/server/web/src/components/__tests__/backup-settings.test.tsx @@ -167,6 +167,14 @@ describe("Settings backup workflows", () => { expect(submit.matches(":disabled, [aria-disabled=true]")).toBe(true); const password = screen.getByLabelText("Archive password"); const confirm = screen.getByLabelText("Confirm archive password"); + // The gold half of the tone rule: blur the EMPTY box and the sentence is + // "nothing typed yet" (text-warning), not "what you typed is wrong". + fireEvent.focus(password); + fireEvent.blur(password); + expect(screen.getByRole("alert").textContent).toContain("at least 8"); + expect(screen.getByRole("alert").className).toContain("text-warning"); + expect(screen.getByRole("alert").className).not.toContain("text-destructive"); + // The red half: a value that validation refuses. for (const input of [password, confirm]) fireEvent.change(input, { target: { value: "short" } }); fireEvent.blur(password); expect(screen.getByRole("alert").textContent).toContain("at least 8"); diff --git a/apps/server/web/src/components/prompts/__tests__/prompt-form-dialog.test.tsx b/apps/server/web/src/components/prompts/__tests__/prompt-form-dialog.test.tsx index 7f8450ec4..71a548361 100644 --- a/apps/server/web/src/components/prompts/__tests__/prompt-form-dialog.test.tsx +++ b/apps/server/web/src/components/prompts/__tests__/prompt-form-dialog.test.tsx @@ -24,11 +24,24 @@ function mockFetch() { return { posts, restore: () => (globalThis.fetch = realFetch) }; } -function renderDialog(props: { onSaved?: () => void; onClose?: () => void } = {}) { +function renderDialog( + props: { + onSaved?: () => void; + onClose?: () => void; + editingId?: string; + initial?: { description: string; body: string; shared: boolean }; + } = {}, +) { const client = new QueryClient({ defaultOptions: { queries: { retry: false } } }); render( - props.onClose?.()} onSaved={props.onSaved} /> + props.onClose?.()} + onSaved={props.onSaved} + editingId={props.editingId} + initial={props.initial} + /> , ); } @@ -89,3 +102,40 @@ describe("PromptFormDialog gating", () => { await waitFor(() => expect(saved).toBe(true)); }); }); + +describe("PromptFormDialog edit mode", () => { + let restore: (() => void) | undefined; + afterEach(() => { + restore?.(); + restore = undefined; + }); + + it("starts dead, opens on a real edit, and re-deadens when the edit is reverted", () => { + // The unchanged-draft rule on the prompt editor. Create mode cannot see + // this path at all (its fields start empty), so edit mode is pinned here: + // a dialog that opens already valid used to offer Save for a draft that + // differed from the stored row by nothing. + const realFetch = globalThis.fetch; + const puts: Record[] = []; + globalThis.fetch = ((input: string | URL | Request, init?: RequestInit) => { + const url = String(input); + if (url === "/api/prompts/pr1" && (init?.method ?? "GET") === "PUT") { + puts.push(JSON.parse(String(init?.body)) as Record); + return Promise.resolve(new Response(JSON.stringify({ ok: true }))); + } + return realFetch(input as never, init as never); + }) as typeof fetch; + restore = () => { + globalThis.fetch = realFetch; + }; + renderDialog({ editingId: "pr1", initial: { description: "Kickoff", body: "start the task", shared: false } }); + const save = () => screen.getByRole("button", { name: "Save" }) as HTMLButtonElement; + expect(save().matches(":disabled, [aria-disabled=true]")).toBe(true); + expect(save().getAttribute("aria-description")).toBe("No changes to save."); + fireEvent.change(descriptionField(), { target: { value: "Kickoff v2" } }); + expect(save().matches(":disabled, [aria-disabled=true]")).toBe(false); + fireEvent.change(descriptionField(), { target: { value: "Kickoff" } }); + expect(save().matches(":disabled, [aria-disabled=true]")).toBe(true); + expect(puts).toHaveLength(0); + }); +}); diff --git a/docs/design-system.md b/docs/design-system.md index 654c81d66..f57f40f85 100644 --- a/docs/design-system.md +++ b/docs/design-system.md @@ -254,8 +254,8 @@ admitted here. - **Quiet label vs control label**: a read-only data row labels over its value with the label in `muted-foreground` at `detail` size and the value at `body` size in `foreground`, using the shared `Fact` component. Monospace values keep - the same body size. Size and colour together distinguish labels from values. `font-strong` label weight belongs to a control's label and to a - section heading, ONLY. *(A networking card set bold "NetBird FQDN" over its URL + the same body size. Size and colour together distinguish labels from values. `font-strong` + label weight belongs to a control's label and to a section heading, ONLY. *(A networking card set bold "NetBird FQDN" over its URL six pixels above a quiet "Client version" over its: two label grammars in one card, so one row read as a heading and the other as data, and neither was the control the bold claimed it was.)* diff --git a/docs/ux-review-2026-10-17.md b/docs/ux-review-2026-10-17.md index 26fca303b..575d776f6 100644 --- a/docs/ux-review-2026-10-17.md +++ b/docs/ux-review-2026-10-17.md @@ -9,7 +9,7 @@ components; it is not a claim that every possible product state was exercised. | Pattern | Finding and correction | Surfaces | | --- | --- | --- | -| Read-only facts | Labels and values had similar size and color, and several screens implemented their own pairs. Shared `Fact` now uses smaller muted labels and body-sized foreground values, including monospace values. | Runtime, Status, node details, SSH trust, Networking, clone, enrollment, backup summaries, destination verification, provider removal, command previews | +| Read-only facts | Labels and values had similar size and colour, and several screens implemented their own pairs. Shared `Fact` now uses smaller muted labels and body-sized foreground values, including monospace values. | Runtime, Status, node details, SSH trust, Networking, clone, enrollment, backup summaries, destination verification, provider removal, command previews | | Long values | Some review values were truncated or could force a wide layout. Facts wrap complete values; machine facts collapse to one column on narrow screens. | Addresses, paths, fingerprints, commands, SSH summaries, node metadata | | Radio-dependent fields | Fields below the whole group made their association unclear. The selected option now contains an inset, bordered field panel immediately below its description, outside its clickable label. | SSH authentication, SSH forwarding, Restore source and mode | | Save availability | Touched fields and unchanged drafts could enable Save. Save now compares the effective draft with saved data, including reverting edits; the disabled Save and its reason carry the pending-change fact, so no separate unsaved-changes sentence is shown. | Sharing, profile, device name, instance name, providers, prompts, prompt stacks, network plugin settings, server addresses | From 2b4e85f6beae11610887e0a21e396c4e42e8c17c Mon Sep 17 00:00:00 2001 From: Theo Gravity Date: Sat, 17 Oct 2026 03:54:20 -0700 Subject: [PATCH 6/6] test: exercise the prompt editor's edit-mode submit path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The gate was pinned; the wire was not. A real change now has to ride the PUT once, carrying the full replacement draft, before the dialog closes and reports done — the submit half of the edit loop that the create-mode tests could never reach. Co-Authored-By: Claude Fable 5 --- .../__tests__/prompt-form-dialog.test.tsx | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/apps/server/web/src/components/prompts/__tests__/prompt-form-dialog.test.tsx b/apps/server/web/src/components/prompts/__tests__/prompt-form-dialog.test.tsx index 71a548361..e3046e450 100644 --- a/apps/server/web/src/components/prompts/__tests__/prompt-form-dialog.test.tsx +++ b/apps/server/web/src/components/prompts/__tests__/prompt-form-dialog.test.tsx @@ -138,4 +138,41 @@ describe("PromptFormDialog edit mode", () => { expect(save().matches(":disabled, [aria-disabled=true]")).toBe(true); expect(puts).toHaveLength(0); }); + + it("sends the edited draft as a PUT and reports done", async () => { + // The other half of the edit-mode loop: a REAL change lights Save, and the + // press rides the wire once with the full replacement draft (PUT is a + // complete replacement of the fields, so the body must carry all three). + const realFetch = globalThis.fetch; + const puts: { url: string; body: Record }[] = []; + globalThis.fetch = ((input: string | URL | Request, init?: RequestInit) => { + const url = String(input); + if (url === "/api/prompts/pr1" && (init?.method ?? "GET") === "PUT") { + puts.push({ url, body: JSON.parse(String(init?.body)) as Record }); + return Promise.resolve(new Response(JSON.stringify({ ok: true }))); + } + return realFetch(input as never, init as never); + }) as typeof fetch; + let saved = false; + try { + renderDialog({ + editingId: "pr1", + initial: { description: "Kickoff", body: "start the task", shared: false }, + onSaved: () => { + saved = true; + }, + }); + fireEvent.change(bodyField(), { target: { value: "start the task now" } }); + const save = () => screen.getByRole("button", { name: "Save" }) as HTMLButtonElement; + expect(save().matches(":disabled, [aria-disabled=true]")).toBe(false); + fireEvent.click(save()); + await waitFor(() => { + expect(puts).toHaveLength(1); + expect(puts[0]?.body).toEqual({ description: "Kickoff", body: "start the task now", shared: false }); + expect(saved).toBe(true); + }); + } finally { + globalThis.fetch = realFetch; + } + }); });