feat(web): responsive page padding and stacking page headers

This commit is contained in:
mrhid6
2026-07-27 22:42:22 +01:00
parent 60af88525c
commit e8c75e974d
21 changed files with 35 additions and 35 deletions
+1 -1
View File
@@ -49,7 +49,7 @@ export default function AuditPage() {
});
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
<div className="mb-6">
<h1 className="text-2xl font-bold text-text-primary">Audit Log</h1>
<p className="mt-1 text-sm text-text-secondary">
+2 -2
View File
@@ -227,7 +227,7 @@ export default function KeyDetailPage() {
if (error || !key) {
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
<div className="rounded-lg border border-danger/30 bg-danger/10 p-4 text-danger">
Key not found or failed to load.
</div>
@@ -239,7 +239,7 @@ export default function KeyDetailPage() {
const assignedServerIds = activeAssignments.map((a) => a.server_id);
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
{showAssign && (
<AssignModal
keyId={keyId}
+2 -2
View File
@@ -106,10 +106,10 @@ export default function KeysPage() {
});
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
{showUpload && <UploadKeyModal onClose={() => setShowUpload(false)} />}
<div className="mb-6 flex items-center justify-between">
<div className="mb-6 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-text-primary">SSH Keys</h1>
<p className="mt-1 text-sm text-text-secondary">
+2 -2
View File
@@ -37,14 +37,14 @@ export default function EditMonitorPage() {
if (!monitor) {
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
<div className="rounded-lg border border-danger/30 bg-danger/10 p-4 text-danger">Monitor not found.</div>
</div>
);
}
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
<Link href={`/monitors/${monitorId}`} className="text-sm text-text-secondary hover:text-text-primary">
{monitor.name}
</Link>
+2 -2
View File
@@ -86,7 +86,7 @@ export default function MonitorDetailPage() {
if (!monitor) {
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
<div className="rounded-lg border border-danger/30 bg-danger/10 p-4 text-danger">Monitor not found.</div>
</div>
);
@@ -96,7 +96,7 @@ export default function MonitorDetailPage() {
const last24 = all.slice(-24);
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
<div className="mb-6 flex items-start justify-between">
<div>
<Link href="/monitors" className="text-sm text-text-secondary hover:text-text-primary">
+1 -1
View File
@@ -20,7 +20,7 @@ export default function NewMonitorPage() {
});
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
<Link href="/monitors" className="text-sm text-text-secondary hover:text-text-primary">
Monitors
</Link>
+2 -2
View File
@@ -31,8 +31,8 @@ export default function MonitorsPage() {
});
return (
<div className="p-8">
<div className="mb-6 flex items-center justify-between">
<div className="p-4 sm:p-6 lg:p-8">
<div className="mb-6 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-text-primary">Monitors</h1>
<p className="mt-1 text-sm text-text-secondary">Service uptime and latency checks.</p>
+2 -2
View File
@@ -241,14 +241,14 @@ export default function SecretGroupPage() {
});
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
{showYaml && <YamlModal group={group} onClose={() => setShowYaml(false)} />}
<Link href="/secrets" className="mb-4 inline-flex items-center gap-1 text-sm text-text-secondary hover:text-text-primary">
Back to secrets
</Link>
<div className="mb-6 flex items-center justify-between">
<div className="mb-6 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="font-mono text-2xl font-bold text-text-primary">{group}</h1>
<p className="mt-1 text-sm text-text-secondary">
+2 -2
View File
@@ -99,10 +99,10 @@ export default function SecretsPage() {
});
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
{showNew && <NewGroupModal onClose={() => setShowNew(false)} />}
<div className="mb-6 flex items-center justify-between">
<div className="mb-6 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-text-primary">Secrets</h1>
<p className="mt-1 text-sm text-text-secondary">
+1 -1
View File
@@ -158,7 +158,7 @@ export default function ServerConsolePage() {
if (!server) {
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
<div className="rounded-lg border border-danger/30 bg-danger/10 p-4 text-danger">Server not found or failed to load.</div>
</div>
);
+2 -2
View File
@@ -372,14 +372,14 @@ export default function ServerDetailPage() {
if (error || !server) {
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
<div className="rounded-lg border border-danger/30 bg-danger/10 p-4 text-danger">Server not found or failed to load.</div>
</div>
);
}
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
{showGenerateModal && <GenerateKeyModal onClose={() => setShowGenerateModal(false)} onSubmit={(opts) => generateKey(opts)} isPending={isGenerating} />}
{showUpdatesModal && server.available_updates && (
<UpdatesModal updates={server.available_updates} onClose={() => setShowUpdatesModal(false)} onApply={() => applyUpdates()} isApplying={isApplying} applySuccess={applySuccess} />
+1 -1
View File
@@ -25,7 +25,7 @@ export default function NewServerPage() {
};
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
<div className="mb-6">
<h1 className="text-2xl font-bold text-text-primary">Add Server</h1>
<p className="mt-1 text-sm text-text-secondary">
+2 -2
View File
@@ -71,8 +71,8 @@ export default function ServersPage() {
const latestVersion = latestVersionData?.version;
return (
<div className="p-8">
<div className="mb-6 flex items-center justify-between">
<div className="p-4 sm:p-6 lg:p-8">
<div className="mb-6 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-text-primary">Servers</h1>
<p className="mt-1 text-sm text-text-secondary">
+2 -2
View File
@@ -237,7 +237,7 @@ export default function LicensePage() {
if (!license) {
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
<Card className="max-w-lg">
<h1 className="text-base font-bold text-text-primary">Licence unavailable</h1>
<p className="mt-1 text-sm text-text-secondary">The licence state could not be read. Reload the page, and check the server logs if it keeps failing.</p>
@@ -253,7 +253,7 @@ export default function LicensePage() {
const hqUrl = process.env.NEXT_PUBLIC_HQ_URL ?? "";
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
<div className="mx-auto max-w-5xl space-y-10">
<div>
<h1 className="text-2xl font-extrabold tracking-[-0.03em] text-text-primary">Licence</h1>
@@ -149,8 +149,8 @@ export default function NotificationSettingsPage() {
const { data: channels, isLoading } = useQuery({ queryKey: ["channels"], queryFn: () => api.listChannels() });
return (
<div className="p-8">
<div className="mb-6 flex items-center justify-between">
<div className="p-4 sm:p-6 lg:p-8">
<div className="mb-6 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<Link href="/monitors" className="text-sm text-text-secondary hover:text-text-primary">
Monitors
+2 -2
View File
@@ -160,7 +160,7 @@ export default function SettingsPage() {
if (!isAdmin) {
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
<Card className="max-w-lg">
<h1 className="text-base font-bold text-text-primary">You don&apos;t have access</h1>
<p className="mt-1 text-sm text-text-secondary">Settings are available to owners and admins only. Ask an administrator if you need access.</p>
@@ -178,7 +178,7 @@ export default function SettingsPage() {
}
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
<div className="mb-8">
<h1 className="text-2xl font-extrabold tracking-[-0.03em] text-text-primary">Settings</h1>
<p className="mt-1 text-sm text-text-secondary">
+1 -1
View File
@@ -91,7 +91,7 @@ export default function StepsPage() {
};
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
<div className="mb-6 flex items-center gap-3">
<div>
<h1 className="text-xl font-semibold text-text-primary">Steps</h1>
+1 -1
View File
@@ -130,7 +130,7 @@ export default function WorkflowBuilder() {
}, [lastSaved]);
if (!wf) {
return <div className="p-8 text-text-secondary">Loading</div>;
return <div className="p-4 text-text-secondary sm:p-6 lg:p-8">Loading</div>;
}
const libById = (sid?: string) => (sid ? library?.find((l) => l.step_id === sid) : undefined);
@@ -326,7 +326,7 @@ export default function RunDetail() {
};
if (isLoading || !run) {
return <div className="p-8 text-text-secondary">Loading</div>;
return <div className="p-4 text-text-secondary sm:p-6 lg:p-8">Loading</div>;
}
const totalSteps = run.server_runs.reduce((n, s) => n + s.steps.length, 0);
@@ -340,7 +340,7 @@ export default function RunDetail() {
const ago = fmtDuration(now - startMs);
return (
<div className="mx-auto max-w-[1180px] p-8 pb-16">
<div className="mx-auto max-w-[1180px] p-4 pb-16 sm:p-6 lg:p-8">
{/* identity bar */}
<div className="flex flex-wrap items-start justify-between gap-6">
<div>
+1 -1
View File
@@ -22,7 +22,7 @@ export default function WorkflowRunsPage() {
const { data: runs, isLoading, error } = useQuery({ queryKey: ["runs", id], queryFn: () => api.listRuns(id) });
return (
<div className="p-8">
<div className="p-4 sm:p-6 lg:p-8">
<div className="mb-6">
<Link href={`/workflows/${id}`} className="text-sm text-text-secondary hover:text-text-primary">
Back to builder
+2 -2
View File
@@ -28,8 +28,8 @@ export default function WorkflowsPage() {
});
return (
<div className="p-8">
<div className="mb-6 flex items-center justify-between">
<div className="p-4 sm:p-6 lg:p-8">
<div className="mb-6 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-text-primary">Workflows</h1>
<p className="mt-1 text-sm text-text-secondary">