diff --git a/web/messages/de.json b/web/messages/de.json
index 353ecfe..a2ffc91 100644
--- a/web/messages/de.json
+++ b/web/messages/de.json
@@ -4,6 +4,7 @@
"app_tagline": "Verwaltungskonsole",
"nav_dashboard": "Übersicht",
"nav_host": "Host",
+ "nav_displays": "Virtuelle Anzeigen",
"nav_clients": "Gekoppelte Geräte",
"nav_pairing": "Kopplung",
"nav_library": "Bibliothek",
@@ -49,6 +50,7 @@
"gpu_env_note": "PUNKTFUNK_RENDER_ADAPTER={value} bindet die GPU im Automatikmodus.",
"host_displays": "Virtuelle Displays",
"host_displays_help": "Wie virtuelle Displays erstellt, aktiv gehalten und angeordnet werden. Wähle eine Voreinstellung oder „Benutzerdefiniert“, um Optionen direkt zu setzen. Eine Änderung gilt ab der nächsten Sitzung.",
+ "display_config_title": "Konfiguration",
"display_preset": "Voreinstellung",
"display_preset_custom": "Benutzerdefiniert",
"display_preset_default": "Standard",
diff --git a/web/messages/en.json b/web/messages/en.json
index f7b1442..0db8281 100644
--- a/web/messages/en.json
+++ b/web/messages/en.json
@@ -4,6 +4,7 @@
"app_tagline": "management console",
"nav_dashboard": "Dashboard",
"nav_host": "Host",
+ "nav_displays": "Virtual displays",
"nav_clients": "Paired clients",
"nav_pairing": "Pairing",
"nav_library": "Library",
@@ -49,6 +50,7 @@
"gpu_env_note": "PUNKTFUNK_RENDER_ADAPTER={value} pins the GPU while in automatic mode.",
"host_displays": "Virtual displays",
"host_displays_help": "How virtual displays are created, kept alive, and arranged. Pick a preset, or choose Custom to set options directly. A change applies to the next session.",
+ "display_config_title": "Configuration",
"display_preset": "Preset",
"display_preset_custom": "Custom",
"display_preset_default": "Default",
diff --git a/web/src/components/app-shell.tsx b/web/src/components/app-shell.tsx
index 546733b..4499f5f 100644
--- a/web/src/components/app-shell.tsx
+++ b/web/src/components/app-shell.tsx
@@ -4,6 +4,7 @@ import {
GaugeCircle,
KeyRound,
LibraryBig,
+ MonitorPlay,
ScrollText,
Server,
Settings,
@@ -21,6 +22,7 @@ const MLink = motion(Link);
const NAV = [
{ to: "/", icon: Activity, label: () => m.nav_dashboard() },
{ to: "/host", icon: Server, label: () => m.nav_host() },
+ { to: "/displays", icon: MonitorPlay, label: () => m.nav_displays() },
{ to: "/library", icon: LibraryBig, label: () => m.nav_library() },
{ to: "/stats", icon: GaugeCircle, label: () => m.nav_stats() },
{ to: "/logs", icon: ScrollText, label: () => m.nav_logs() },
diff --git a/web/src/routes/displays.tsx b/web/src/routes/displays.tsx
new file mode 100644
index 0000000..959d331
--- /dev/null
+++ b/web/src/routes/displays.tsx
@@ -0,0 +1,4 @@
+import { createFileRoute } from "@tanstack/react-router";
+import { SectionDisplays } from "@/sections/Displays";
+
+export const Route = createFileRoute("/displays")({ component: SectionDisplays });
diff --git a/web/src/sections/Host/DisplayCard.tsx b/web/src/sections/Displays/DisplayCard.tsx
similarity index 91%
rename from web/src/sections/Host/DisplayCard.tsx
rename to web/src/sections/Displays/DisplayCard.tsx
index 35e034a..cf99afa 100644
--- a/web/src/sections/Host/DisplayCard.tsx
+++ b/web/src/sections/Displays/DisplayCard.tsx
@@ -60,27 +60,36 @@ export const DisplaySection: FC = () => {
);
return (
- {m.host_displays_help()}
{m.host_displays_help()}
+{summary}
} + {summary && ( +{summary}
+ )} {fields && ( -{m.display_none_live()}
) : ( diff --git a/web/src/sections/Displays/index.tsx b/web/src/sections/Displays/index.tsx new file mode 100644 index 0000000..b707a95 --- /dev/null +++ b/web/src/sections/Displays/index.tsx @@ -0,0 +1,22 @@ +import Section from "@unom/ui/section"; +import type { FC } from "react"; +import { useLocale } from "@/lib/i18n"; +import { m } from "@/paraglide/messages"; +import { DisplaySection } from "./DisplayCard"; + +/** + * The **Virtual displays** page (design/display-management.md): the host's virtual-display policy + * (presets + every axis) plus the live-display list + multi-monitor arrangement. Its own nav + * section — the config surface is large enough to warrant the room, and it kept the Host page busy. + */ +export const SectionDisplays: FC = () => { + useLocale(); + return ( +