From 53e947935ac135469d8d65ea1299b07501e41b8a Mon Sep 17 00:00:00 2001 From: Albrecht Degering Date: Tue, 28 Jul 2026 22:50:11 +0200 Subject: [PATCH] fix: standardize direct page scroll viewports --- webui/src/components/PageScrollViewport.tsx | 23 ++++++++++ .../components/ViewSurfaceRouteBoundary.tsx | 43 ++++++++++--------- webui/src/features/PlaceholderPage.tsx | 21 +++++---- .../src/features/dashboard/DashboardPage.tsx | 7 ++- webui/src/index.ts | 2 + webui/src/styles/layout.css | 3 +- 6 files changed, 67 insertions(+), 32 deletions(-) create mode 100644 webui/src/components/PageScrollViewport.tsx diff --git a/webui/src/components/PageScrollViewport.tsx b/webui/src/components/PageScrollViewport.tsx new file mode 100644 index 0000000..8d242ef --- /dev/null +++ b/webui/src/components/PageScrollViewport.tsx @@ -0,0 +1,23 @@ +import type { HTMLAttributes, ReactNode } from "react"; + +export type PageScrollViewportProps = Omit< + HTMLAttributes, + "children" +> & { + children: ReactNode; +}; + +export default function PageScrollViewport({ + children, + className = "", + ...props +}: PageScrollViewportProps) { + return ( +
+ {children} +
+ ); +} diff --git a/webui/src/components/ViewSurfaceRouteBoundary.tsx b/webui/src/components/ViewSurfaceRouteBoundary.tsx index 43a0588..1abb7da 100644 --- a/webui/src/components/ViewSurfaceRouteBoundary.tsx +++ b/webui/src/components/ViewSurfaceRouteBoundary.tsx @@ -6,6 +6,7 @@ import { dispatchPlatformViewChanged } from "../platform/views"; import { useGuardedNavigate } from "./UnsavedChangesGuard"; import Button from "./Button"; import Card from "./Card"; +import PageScrollViewport from "./PageScrollViewport"; export default function ViewSurfaceRouteBoundary({ surfaceId, @@ -33,26 +34,28 @@ export default function ViewSurfaceRouteBoundary({ } return ( -
- -
-
+ ); } diff --git a/webui/src/features/PlaceholderPage.tsx b/webui/src/features/PlaceholderPage.tsx index 0ecd066..92e99a9 100644 --- a/webui/src/features/PlaceholderPage.tsx +++ b/webui/src/features/PlaceholderPage.tsx @@ -1,15 +1,18 @@ import Card from "../components/Card"; +import PageScrollViewport from "../components/PageScrollViewport"; export default function PlaceholderPage({ title }: {title: string;}) { return ( -
-
-

{title}

-

i18n:govoplan-core.this_module_is_prepared_but_not_implemented_yet.6e6449ee

+ +
+
+

{title}

+

i18n:govoplan-core.this_module_is_prepared_but_not_implemented_yet.6e6449ee

+
+ +

i18n:govoplan-core.next_passes_will_add_functionality_here.c13caade

+
- -

i18n:govoplan-core.next_passes_will_add_functionality_here.c13caade

-
-
); + ); -} \ No newline at end of file +} diff --git a/webui/src/features/dashboard/DashboardPage.tsx b/webui/src/features/dashboard/DashboardPage.tsx index 7b870d4..86456bf 100644 --- a/webui/src/features/dashboard/DashboardPage.tsx +++ b/webui/src/features/dashboard/DashboardPage.tsx @@ -1,5 +1,6 @@ import Card from "../../components/Card"; import MetricCard from "../../components/MetricCard"; +import PageScrollViewport from "../../components/PageScrollViewport"; import PageTitle from "../../components/PageTitle"; import { usePlatformModules } from "../../platform/ModuleContext"; @@ -7,7 +8,8 @@ export default function DashboardPage() { const modules = usePlatformModules(); return ( -
+ +
i18n:govoplan-core.dashboard.d87f47b4 @@ -37,7 +39,8 @@ export default function DashboardPage() {

This minimal core home is only shown while no dashboard WebUI module is available. Feature modules own their pages and can expose dashboard widgets once the dashboard module is installed.

-
); +
+
); } diff --git a/webui/src/index.ts b/webui/src/index.ts index 3839f06..50b7976 100644 --- a/webui/src/index.ts +++ b/webui/src/index.ts @@ -95,6 +95,8 @@ export { default as MetricCard } from "./components/MetricCard"; export { default as MessageDisplayPanel } from "./components/MessageDisplayPanel"; export type { MessageDisplayAttachment, MessageDisplayField } from "./components/MessageDisplayPanel"; export { default as PageTitle } from "./components/PageTitle"; +export { default as PageScrollViewport } from "./components/PageScrollViewport"; +export type { PageScrollViewportProps } from "./components/PageScrollViewport"; export { default as PasswordField } from "./components/PasswordField"; export { default as PeoplePicker } from "./components/people/PeoplePicker"; export type { PeoplePickerProps } from "./components/people/PeoplePicker"; diff --git a/webui/src/styles/layout.css b/webui/src/styles/layout.css index fa8f561..764bf31 100644 --- a/webui/src/styles/layout.css +++ b/webui/src/styles/layout.css @@ -68,8 +68,10 @@ .section-link.active { border-left: 3px solid var(--accent); font-weight: 700; } .section-link.subtle { font-size: 13px; } .workspace-content { min-width: 0; max-width: 100%; min-height: 0; overflow: auto; } +.page-scroll-viewport { width: 100%; height: 100%; min-width: 0; min-height: 0; overflow: auto; } .ui-no-sticky-section-sidebars .app-content { overflow: auto; } .ui-no-sticky-section-sidebars .workspace { height: auto; min-height: 100%; } +.ui-no-sticky-section-sidebars .page-scroll-viewport { height: auto; min-height: 100%; overflow: visible; } .ui-no-sticky-section-sidebars .section-sidebar { height: max-content; max-height: none; @@ -83,7 +85,6 @@ .page-heading.split { display: flex; align-items: center; justify-content: space-between; } .module-entry-page { max-width: none; } .workspace-data-page .card { margin-bottom: 18px; } -.core-dashboard-page { height: 100%; overflow: auto; } .page-heading.workspace-heading { position: sticky; top: 0;