diff --git a/CHANGELOG.md b/CHANGELOG.md index 396b6f8..15791b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ the configuration; each release says how to upgrade. - Portal: form controls follow the same pill language — text inputs, selects and checkboxes on the filter screens (Dashboard, Downloaded, Analytics, Alerts), the chart range and alert severity as pill switches, and the Feed and Audit filters as chips. +- Portal: forms (users, login, profile, settings, Node configuration, the Node dialogs) use the + same fields, and every action button is rounded to match. ### Fixed - Portal: the language selector no longer spills out of the sidebar; it sits on its own row diff --git a/portal/src/components/AddNodeModal.tsx b/portal/src/components/AddNodeModal.tsx index cb036c9..282aad9 100644 --- a/portal/src/components/AddNodeModal.tsx +++ b/portal/src/components/AddNodeModal.tsx @@ -69,13 +69,13 @@ export function AddNodeModal({ onClose, onLogout }: { onClose: () => void; onLog placeholder={t("health.addNodeModal.namePlaceholder")} autoFocus autoComplete="off" - className="mt-1 w-full rounded-lg border border-slate-700 bg-slate-950 px-3 py-2 text-sm text-white outline-none focus:border-emerald-500" + className="sg-field mt-1 w-full" /> {err &&

{err}

} @@ -104,7 +104,7 @@ export function AddNodeModal({ onClose, onLogout }: { onClose: () => void; onLog @@ -120,7 +120,7 @@ export function AddNodeModal({ onClose, onLogout }: { onClose: () => void; onLog @@ -142,7 +142,7 @@ export function AddNodeModal({ onClose, onLogout }: { onClose: () => void; onLog diff --git a/portal/src/components/Layout.tsx b/portal/src/components/Layout.tsx index 16b9870..75bb73c 100644 --- a/portal/src/components/Layout.tsx +++ b/portal/src/components/Layout.tsx @@ -190,7 +190,7 @@ export function Layout({ diff --git a/portal/src/components/MigratePicker.tsx b/portal/src/components/MigratePicker.tsx index 4db2f1d..10b24bb 100644 --- a/portal/src/components/MigratePicker.tsx +++ b/portal/src/components/MigratePicker.tsx @@ -112,7 +112,7 @@ export function MigratePicker({ diff --git a/portal/src/components/NodeCard.tsx b/portal/src/components/NodeCard.tsx index 01fd795..0863473 100644 --- a/portal/src/components/NodeCard.tsx +++ b/portal/src/components/NodeCard.tsx @@ -143,7 +143,7 @@ export function NodeCard({ onClick={onRename} disabled={busy} title={t("health.nodeCard.actions.renameTitle")} - className="rounded-lg border border-slate-700 px-2.5 py-1 text-xs text-slate-300 transition hover:bg-slate-800 disabled:opacity-40" + className="rounded-full border border-slate-700 px-2.5 py-1 text-xs text-slate-300 transition hover:bg-slate-800 disabled:opacity-40" > {t("health.nodeCard.actions.rename")} @@ -151,7 +151,7 @@ export function NodeCard({ onClick={onDrain} disabled={busy || torrents.length === 0} title={t("health.nodeCard.actions.drainTitle")} - className="rounded-lg border border-slate-700 px-2.5 py-1 text-xs text-blue-400 transition hover:bg-slate-800 disabled:opacity-40" + className="rounded-full border border-slate-700 px-2.5 py-1 text-xs text-blue-400 transition hover:bg-slate-800 disabled:opacity-40" > {t("health.nodeCard.actions.drain")} @@ -159,7 +159,7 @@ export function NodeCard({ onClick={onRestartEngine} disabled={busy || running.size > 0} title={t("health.nodeCard.actions.restartEngineTitle")} - className="inline-flex items-center gap-1.5 rounded-lg border border-slate-700 px-2.5 py-1 text-xs text-amber-400 transition hover:bg-slate-800 disabled:opacity-40" + className="inline-flex items-center gap-1.5 rounded-full border border-slate-700 px-2.5 py-1 text-xs text-amber-400 transition hover:bg-slate-800 disabled:opacity-40" > {running.has(n.id) ? : "⟳"} {t("health.nodeCard.actions.restartEngine")} @@ -167,7 +167,7 @@ export function NodeCard({ onClick={onDelete} disabled={busy} title={t("health.nodeCard.actions.removeTitle")} - className="rounded-lg border border-slate-700 px-2.5 py-1 text-xs text-red-400 transition hover:bg-slate-800 disabled:opacity-40" + className="rounded-full border border-slate-700 px-2.5 py-1 text-xs text-red-400 transition hover:bg-slate-800 disabled:opacity-40" > {t("health.nodeCard.actions.remove")} diff --git a/portal/src/components/NodeConfigPanel.tsx b/portal/src/components/NodeConfigPanel.tsx index 7846549..0d029bf 100644 --- a/portal/src/components/NodeConfigPanel.tsx +++ b/portal/src/components/NodeConfigPanel.tsx @@ -19,8 +19,8 @@ const REFRESH_MS = 10_000; // /nodes/{id}/settings/{key}. Dedicated function so the test can check which permission is requested. export const canWriteNodeConfig = (can: (perm: string) => boolean): boolean => can("nodes:write"); -const inputCls = - "rounded-lg border border-slate-700 bg-slate-950/60 px-2.5 py-1 text-sm text-slate-100 outline-none transition focus:border-emerald-500 disabled:opacity-50"; +// Form-control base classes (#22): sg-field, plus sg-select on the lists. +const inputCls = "sg-field"; const TONE: Record<"ok" | "warn" | "muted", string> = { ok: "bg-emerald-500/15 text-emerald-300 ring-emerald-500/30", @@ -78,7 +78,7 @@ function ValueInput({ const t = useT(); if (item.type === "bool") { return ( - onChange(e.target.value)} disabled={disabled} className={`w-32 ${inputCls} sg-select`}> @@ -86,7 +86,7 @@ function ValueInput({ } if (item.options && item.options.length > 0) { return ( - onChange(e.target.value)} disabled={disabled} className={`w-32 ${inputCls} sg-select`}> {item.options.map((o) => (