@@ -169,6 +170,6 @@ export default function Page() {
>
)}
-
+
);
}
diff --git a/web/mail-search/app/page.tsx b/web/mail-search/app/page.tsx
index 7ffb91df..8e7f2641 100644
--- a/web/mail-search/app/page.tsx
+++ b/web/mail-search/app/page.tsx
@@ -2,7 +2,7 @@
import { useState, useEffect, useCallback, useRef, type FormEvent } from "react";
import Link from "next/link";
-import { TextField, useToast } from "@nexarch/shl";
+import { TextField, useToast, PageContainer } from "@nexarch/shl";
import { search, facets, ApiError, type SearchHit, type AppliedFilter, type FacetsResponse } from "../lib/api";
import { splitHighlighted } from "../lib/highlight";
import { HIGHLIGHT_BG_LIGHT, HIGHLIGHT_FG_LIGHT } from "../lib/highlightColors";
@@ -185,7 +185,7 @@ export default function SearchPage() {
}, [hits, focusedIndex, focusResult, archiveFocused]);
return (
-
+
Mail-Suche
Tastenkürzel: / Suche fokussieren, j/k nächste/vorherige Nachricht,{" "}
@@ -255,6 +255,6 @@ export default function SearchPage() {
))}
)}
-
+
);
}
diff --git a/web/pdf-viewer/app/page.tsx b/web/pdf-viewer/app/page.tsx
index 077576ac..8fd4bd2f 100644
--- a/web/pdf-viewer/app/page.tsx
+++ b/web/pdf-viewer/app/page.tsx
@@ -1,14 +1,14 @@
"use client";
-import { useI18n } from "@nexarch/shl";
+import { useI18n, PageContainer } from "@nexarch/shl";
import "../lib/messages";
export default function IndexPage() {
const { t } = useI18n();
return (
-
+
{t("pdf.index.title", "NEXARCH Dokumentbetrachter")}
{t("pdf.index.hint", "Diese Anwendung wird über /viewer/ aufgerufen.")}
-
+
);
}
diff --git a/web/routing-rules/app/page.tsx b/web/routing-rules/app/page.tsx
index 27e1620b..22a44181 100644
--- a/web/routing-rules/app/page.tsx
+++ b/web/routing-rules/app/page.tsx
@@ -2,7 +2,7 @@
import { Suspense } from "react";
import { useSearchParams } from "next/navigation";
-import { TextField } from "@nexarch/shl";
+import { TextField, PageContainer } from "@nexarch/shl";
import { RuleEditor } from "./RuleEditor";
function RulesPage() {
@@ -10,7 +10,7 @@ function RulesPage() {
const userId = params.get("user") ?? "";
return (
-
+
Routing-Regel-Editor
{userId === "" ? (
)}
-
+
);
}
diff --git a/web/shl/components/PageContainer.tsx b/web/shl/components/PageContainer.tsx
new file mode 100644
index 00000000..9a4592ae
--- /dev/null
+++ b/web/shl/components/PageContainer.tsx
@@ -0,0 +1,17 @@
+import type { CSSProperties, ReactNode } from "react";
+
+export interface PageContainerProps {
+ maxWidth?: CSSProperties["maxWidth"];
+ margin?: CSSProperties["margin"];
+ padding?: CSSProperties["padding"];
+ children: ReactNode;
+}
+
+// Ersetzt den in 17 Seiten unabhaengig kopierten
+// `
`-Container (Fable-Review
+// auf Code-Dopplung). margin/padding bleiben als Props einstellbar, da
+// die kopierten Varianten sich darin unterschieden (z. B. "0 auto" vs.
+// "40px auto", "24px" vs. "2rem 1rem").
+export function PageContainer({ maxWidth = 960, margin = "0 auto", padding = 24, children }: PageContainerProps) {
+ return {children};
+}
diff --git a/web/shl/index.ts b/web/shl/index.ts
index f1e46790..46791370 100644
--- a/web/shl/index.ts
+++ b/web/shl/index.ts
@@ -17,6 +17,9 @@ export type { ShellProps, ModuleLink } from "./components/Shell";
export { ModuleNavShell, MODULE_REGISTRY, resolveModuleHref } from "./components/ModuleNavShell";
export type { ModuleNavShellProps, ModuleRegistryEntry } from "./components/ModuleNavShell";
+export { PageContainer } from "./components/PageContainer";
+export type { PageContainerProps } from "./components/PageContainer";
+
export { Dialog } from "./components/Dialog";
export type { DialogProps } from "./components/Dialog";
diff --git a/web/status-page/app/page.tsx b/web/status-page/app/page.tsx
index 47c0fcb9..c921a452 100644
--- a/web/status-page/app/page.tsx
+++ b/web/status-page/app/page.tsx
@@ -2,6 +2,7 @@
import { useEffect, useState } from "react";
import { fetchOverview, fetchHistory, type ModuleStatus, type HistoryEntry } from "@/lib/api";
+import { PageContainer } from "@nexarch/shl";
const POLL_INTERVAL_MS = 5000;
@@ -56,7 +57,7 @@ export default function Page() {
const anyDown = modules.some((m) => m.status === "down");
return (
-
+
Systemstatus
{error && (
@@ -120,6 +121,6 @@ export default function Page() {
)}
-
+
);
}
diff --git a/web/tenant-admin/app/page.tsx b/web/tenant-admin/app/page.tsx
index c1191acd..15593ce6 100644
--- a/web/tenant-admin/app/page.tsx
+++ b/web/tenant-admin/app/page.tsx
@@ -1,6 +1,7 @@
"use client";
import { useState } from "react";
+import { PageContainer } from "@nexarch/shl";
import {
fetchTenants,
fetchTenantDetail,
@@ -97,7 +98,7 @@ export default function Page() {
}
return (
-
+
Mandantenverwaltung
@@ -222,6 +223,6 @@ export default function Page() {
)}
-
+
);
}
diff --git a/web/workflow-approvals/app/page.tsx b/web/workflow-approvals/app/page.tsx
index 28acbeaf..a877db0b 100644
--- a/web/workflow-approvals/app/page.tsx
+++ b/web/workflow-approvals/app/page.tsx
@@ -2,7 +2,7 @@
import { Suspense } from "react";
import { useSearchParams } from "next/navigation";
-import { TextField } from "@nexarch/shl";
+import { TextField, PageContainer } from "@nexarch/shl";
import { ApprovalList } from "./ApprovalList";
function ApprovalsPage() {
@@ -10,7 +10,7 @@ function ApprovalsPage() {
const userId = params.get("user") ?? "";
return (
-
+
Meine Freigaben
{userId === "" ? (
)}
-
+
);
}
diff --git a/web/workflow-cases/app/page.tsx b/web/workflow-cases/app/page.tsx
index 4fffe95b..c9c5ae78 100644
--- a/web/workflow-cases/app/page.tsx
+++ b/web/workflow-cases/app/page.tsx
@@ -2,7 +2,7 @@
import { Suspense, useState } from "react";
import { useSearchParams } from "next/navigation";
-import { TextField } from "@nexarch/shl";
+import { TextField, PageContainer } from "@nexarch/shl";
import { CaseOverview } from "./CaseOverview";
import { ReminderKanban } from "./ReminderKanban";
@@ -14,7 +14,7 @@ function CasesPage() {
const [tab, setTab] = useState("cases");
return (
-
+
Akten & Wiedervorlagen
{userId === "" ? (
: }
>
)}
-
+
);
}
diff --git a/web/workflow-tasks/app/page.tsx b/web/workflow-tasks/app/page.tsx
index b398cbdb..c8e706dc 100644
--- a/web/workflow-tasks/app/page.tsx
+++ b/web/workflow-tasks/app/page.tsx
@@ -2,7 +2,7 @@
import { Suspense } from "react";
import { useSearchParams } from "next/navigation";
-import { TextField } from "@nexarch/shl";
+import { TextField, PageContainer } from "@nexarch/shl";
import { TaskBoard } from "./TaskBoard";
function TasksPage() {
@@ -11,7 +11,7 @@ function TasksPage() {
const tenantSlug = params.get("tenant") ?? "";
return (
-
+
Aufgaben
{userId === "" || tenantSlug === "" ? (
)}
-
+
);
}