Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 5 additions & 5 deletions portal/src/components/AddNodeModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 && <p className="mt-3 rounded-lg bg-red-500/10 px-3 py-2 text-xs text-red-400">{err}</p>}
<button
type="submit"
disabled={busy}
className="mt-4 w-full rounded-lg bg-emerald-600 px-3 py-2 text-sm font-medium text-white transition hover:bg-emerald-500 disabled:opacity-50"
className="mt-4 w-full rounded-full bg-emerald-600 px-3 py-2 text-sm font-medium text-white transition hover:bg-emerald-500 disabled:opacity-50"
>
{busy ? t("health.addNodeModal.generating") : t("health.addNodeModal.generateBtn")}
</button>
Expand Down Expand Up @@ -104,7 +104,7 @@ export function AddNodeModal({ onClose, onLogout }: { onClose: () => void; onLog
</code>
<button
onClick={() => copy(cmd, "cmd")}
className="shrink-0 rounded-lg border border-slate-700 px-2.5 py-2 text-xs text-white transition hover:bg-slate-800"
className="shrink-0 rounded-full border border-slate-700 px-2.5 py-2 text-xs text-white transition hover:bg-slate-800"
>
{copied === "cmd" ? t("health.addNodeModal.copiedCheck") : t("health.addNodeModal.copy")}
</button>
Expand All @@ -120,7 +120,7 @@ export function AddNodeModal({ onClose, onLogout }: { onClose: () => void; onLog
</code>
<button
onClick={() => copy(tok.token, "token")}
className="shrink-0 rounded-lg border border-slate-700 px-2.5 py-2 text-xs text-white transition hover:bg-slate-800"
className="shrink-0 rounded-full border border-slate-700 px-2.5 py-2 text-xs text-white transition hover:bg-slate-800"
>
{copied === "token" ? "✓" : t("health.addNodeModal.copy")}
</button>
Expand All @@ -142,7 +142,7 @@ export function AddNodeModal({ onClose, onLogout }: { onClose: () => void; onLog

<button
onClick={onClose}
className="mt-4 w-full rounded-lg px-3 py-2 text-xs text-slate-400 transition hover:bg-slate-800"
className="mt-4 w-full rounded-full px-3 py-2 text-xs text-slate-400 transition hover:bg-slate-800"
>
{t("common.close")}
</button>
Expand Down
2 changes: 1 addition & 1 deletion portal/src/components/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ export function Layout({
<button
onClick={() => setOpen(true)}
aria-label={t("nav.openMenu")}
className="rounded-lg border border-slate-700 px-3 py-1.5 text-slate-300"
className="rounded-full border border-slate-700 px-3 py-1.5 text-slate-300"
>
☰
</button>
Expand Down
2 changes: 1 addition & 1 deletion portal/src/components/MigratePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export function MigratePicker({
</div>
<button
onClick={onClose}
className="mt-4 w-full rounded-lg px-3 py-2 text-xs text-slate-400 transition hover:bg-slate-800"
className="mt-4 w-full rounded-full px-3 py-2 text-xs text-slate-400 transition hover:bg-slate-800"
>
{t("common.cancel")}
</button>
Expand Down
8 changes: 4 additions & 4 deletions portal/src/components/NodeCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,31 +143,31 @@ 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")}
</button>
<button
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")}
</button>
<button
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) ? <Spinner /> : "⟳"} {t("health.nodeCard.actions.restartEngine")}
</button>
<button
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")}
</button>
Expand Down
16 changes: 8 additions & 8 deletions portal/src/components/NodeConfigPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -78,15 +78,15 @@ function ValueInput({
const t = useT();
if (item.type === "bool") {
return (
<select value={value} onChange={(e) => onChange(e.target.value)} disabled={disabled} className={`w-32 ${inputCls}`}>
<select value={value} onChange={(e) => onChange(e.target.value)} disabled={disabled} className={`w-32 ${inputCls} sg-select`}>
<option value="true">{t("nodes.nodeConfigPanel.boolOn")}</option>
<option value="false">{t("nodes.nodeConfigPanel.boolOff")}</option>
</select>
);
}
if (item.options && item.options.length > 0) {
return (
<select value={value} onChange={(e) => onChange(e.target.value)} disabled={disabled} className={`w-32 ${inputCls}`}>
<select value={value} onChange={(e) => onChange(e.target.value)} disabled={disabled} className={`w-32 ${inputCls} sg-select`}>
{item.options.map((o) => (
<option key={o} value={o}>
{o}
Expand Down Expand Up @@ -186,14 +186,14 @@ function ConfigRow({
<button
onClick={save}
disabled={busy}
className="rounded-lg bg-emerald-600 px-2.5 py-1 text-xs font-medium text-white transition hover:bg-emerald-500 disabled:opacity-40"
className="rounded-full bg-emerald-600 px-2.5 py-1 text-xs font-medium text-white transition hover:bg-emerald-500 disabled:opacity-40"
>
{t("common.save")}
</button>
<button
onClick={() => setEditing(false)}
disabled={busy}
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("common.cancel")}
</button>
Expand All @@ -208,7 +208,7 @@ function ConfigRow({
? t("nodes.nodeConfigPanel.editTitleNode")
: t("nodes.nodeConfigPanel.editTitleCluster")
}
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"
>
{item.source === "node" ? t("nodes.nodeConfigPanel.actionEdit") : t("nodes.nodeConfigPanel.actionOverride")}
</button>
Expand All @@ -217,7 +217,7 @@ function ConfigRow({
onClick={reset}
disabled={busy}
title={t("nodes.nodeConfigPanel.resetTitle")}
className="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="rounded-full border border-slate-700 px-2.5 py-1 text-xs text-amber-400 transition hover:bg-slate-800 disabled:opacity-40"
>
{t("nodes.nodeConfigPanel.actionReset")}
</button>
Expand Down
6 changes: 3 additions & 3 deletions portal/src/components/RenameNodeModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,21 +71,21 @@ export function RenameNodeModal({
placeholder={node.hostname}
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 && <p className="mt-3 rounded-lg bg-red-500/10 px-3 py-2 text-xs text-red-400">{err}</p>}
<div className="mt-4 flex gap-2">
<button
type="button"
onClick={onClose}
className="flex-1 rounded-lg px-3 py-2 text-xs text-slate-400 transition hover:bg-slate-800"
className="flex-1 rounded-full px-3 py-2 text-xs text-slate-400 transition hover:bg-slate-800"
>
{t("common.cancel")}
</button>
<button
type="submit"
disabled={busy}
className="flex-1 rounded-lg bg-emerald-600 px-3 py-2 text-sm font-medium text-white transition hover:bg-emerald-500 disabled:opacity-50"
className="flex-1 rounded-full bg-emerald-600 px-3 py-2 text-sm font-medium text-white transition hover:bg-emerald-500 disabled:opacity-50"
>
{busy ? t("common.saving") : t("common.save")}
</button>
Expand Down
8 changes: 4 additions & 4 deletions portal/src/components/TrackerProfileEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ export function TrackerProfileEditor({
<button
onClick={() => removeRow(axis, r.key)}
title={t("trackers.trackerProfileEditor.rows.removeTitle")}
className="shrink-0 rounded px-1.5 py-1 text-xs text-slate-500 hover:bg-slate-800 hover:text-red-400"
className="shrink-0 rounded-full px-1.5 py-1 text-xs text-slate-500 hover:bg-slate-800 hover:text-red-400"
>
✕
</button>
Expand All @@ -343,7 +343,7 @@ export function TrackerProfileEditor({
<button
onClick={save}
disabled={saving || !dirty}
className="rounded-lg bg-emerald-600 px-4 py-1.5 text-sm font-medium text-white transition hover:bg-emerald-500 disabled:opacity-40"
className="rounded-full bg-emerald-600 px-4 py-1.5 text-sm font-medium text-white transition hover:bg-emerald-500 disabled:opacity-40"
>
{saving ? t("common.saving") : t("trackers.trackerProfileEditor.actions.save")}
</button>
Expand Down Expand Up @@ -400,7 +400,7 @@ export function TrackerProfileEditor({
onClick={discover}
disabled={discovering || dirty}
title={dirty ? t("trackers.trackerProfileEditor.discovery.dirtyTitle") : undefined}
className="rounded-lg bg-sky-700 px-4 py-1.5 text-sm font-medium text-white transition hover:bg-sky-600 disabled:opacity-40"
className="rounded-full bg-sky-700 px-4 py-1.5 text-sm font-medium text-white transition hover:bg-sky-600 disabled:opacity-40"
>
{discovering ? t("trackers.trackerProfileEditor.discovery.scanning") : t("trackers.trackerProfileEditor.discovery.button")}
</button>
Expand Down Expand Up @@ -548,7 +548,7 @@ function Proposal({
<button
onClick={onApply}
disabled={applying || count === 0}
className="rounded-lg bg-emerald-600 px-4 py-1.5 text-sm font-medium text-white transition hover:bg-emerald-500 disabled:opacity-40"
className="rounded-full bg-emerald-600 px-4 py-1.5 text-sm font-medium text-white transition hover:bg-emerald-500 disabled:opacity-40"
>
{applying ? t("trackers.trackerProfileEditor.proposal.applying") : t("trackers.trackerProfileEditor.proposal.applyButton", { count })}
</button>
Expand Down
2 changes: 1 addition & 1 deletion portal/src/components/TrackerProfileExchange.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ export function ImportPreviewView({
<button
onClick={onApply}
disabled={applying || !changes}
className="rounded-lg bg-emerald-600 px-4 py-1.5 text-sm font-medium text-white transition hover:bg-emerald-500 disabled:opacity-40"
className="rounded-full bg-emerald-600 px-4 py-1.5 text-sm font-medium text-white transition hover:bg-emerald-500 disabled:opacity-40"
>
{applying ? t("trackers.trackerProfileExchange.applying") : t("trackers.trackerProfileExchange.apply")}
</button>
Expand Down
10 changes: 5 additions & 5 deletions portal/src/components/TrackersPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,29 +168,29 @@ export function TrackersPanel({ can, onLogout }: { can: (perm: string) => boolea
<button
onClick={() => setProfileOpen(profileOpen === tracker.id ? null : tracker.id)}
title={t("trackers.trackersPanel.tooltips.profileButton")}
className="rounded px-2 py-1 text-xs text-slate-400 transition hover:bg-slate-800 hover:text-sky-300"
className="rounded-full px-2 py-1 text-xs text-slate-400 transition hover:bg-slate-800 hover:text-sky-300"
>
{profileOpen === tracker.id ? t("trackers.trackersPanel.actions.profileOpen") : t("trackers.trackersPanel.actions.profileClosed")}
</button>
)}
<button
onClick={() => startEdit(tracker)}
className="rounded px-2 py-1 text-xs text-slate-400 transition hover:bg-slate-800 hover:text-sky-300"
className="rounded-full px-2 py-1 text-xs text-slate-400 transition hover:bg-slate-800 hover:text-sky-300"
>
{t("trackers.trackersPanel.actions.edit")}
</button>
{!tracker.is_default && (
<button
onClick={() => makeDefault(tracker.id)}
className="rounded px-2 py-1 text-xs text-slate-400 transition hover:bg-slate-800 hover:text-emerald-400"
className="rounded-full px-2 py-1 text-xs text-slate-400 transition hover:bg-slate-800 hover:text-emerald-400"
>
{t("trackers.trackersPanel.actions.makeDefault")}
</button>
)}
<button
onClick={() => remove(tracker.id, tracker.name)}
title={t("trackers.trackersPanel.actions.removeTitle")}
className="rounded px-2 py-1 text-xs text-slate-400 transition hover:bg-slate-800 hover:text-red-400"
className="rounded-full px-2 py-1 text-xs text-slate-400 transition hover:bg-slate-800 hover:text-red-400"
>
🗑
</button>
Expand Down Expand Up @@ -290,7 +290,7 @@ export function TrackersPanel({ can, onLogout }: { can: (perm: string) => boolea
<button
onClick={submit}
disabled={busy}
className="rounded-lg bg-emerald-600 px-4 py-2 text-sm font-medium text-white transition hover:bg-emerald-500 disabled:opacity-50"
className="rounded-full bg-emerald-600 px-4 py-2 text-sm font-medium text-white transition hover:bg-emerald-500 disabled:opacity-50"
>
{busy ? t("common.saving") : editing ? t("trackers.trackersPanel.actions.saveChanges") : t("trackers.trackersPanel.actions.addTracker")}
</button>
Expand Down
2 changes: 1 addition & 1 deletion portal/src/components/torrents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export function ActionBtn({
onClick={onClick}
disabled={disabled}
title={title}
className={`rounded px-2 py-1 text-xs hover:bg-slate-800 disabled:opacity-40 ${TONES[tone] ?? TONES.slate}`}
className={`rounded-full px-2 py-1 text-xs hover:bg-slate-800 disabled:opacity-40 ${TONES[tone] ?? TONES.slate}`}
>
{children}
</button>
Expand Down
Loading
Loading