fix: standardize direct page scroll viewports
This commit is contained in:
23
webui/src/components/PageScrollViewport.tsx
Normal file
23
webui/src/components/PageScrollViewport.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import type { HTMLAttributes, ReactNode } from "react";
|
||||||
|
|
||||||
|
export type PageScrollViewportProps = Omit<
|
||||||
|
HTMLAttributes<HTMLDivElement>,
|
||||||
|
"children"
|
||||||
|
> & {
|
||||||
|
children: ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function PageScrollViewport({
|
||||||
|
children,
|
||||||
|
className = "",
|
||||||
|
...props
|
||||||
|
}: PageScrollViewportProps) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
{...props}
|
||||||
|
className={["page-scroll-viewport", className].filter(Boolean).join(" ")}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import { dispatchPlatformViewChanged } from "../platform/views";
|
|||||||
import { useGuardedNavigate } from "./UnsavedChangesGuard";
|
import { useGuardedNavigate } from "./UnsavedChangesGuard";
|
||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
import Card from "./Card";
|
import Card from "./Card";
|
||||||
|
import PageScrollViewport from "./PageScrollViewport";
|
||||||
|
|
||||||
export default function ViewSurfaceRouteBoundary({
|
export default function ViewSurfaceRouteBoundary({
|
||||||
surfaceId,
|
surfaceId,
|
||||||
@@ -33,26 +34,28 @@ export default function ViewSurfaceRouteBoundary({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="content-pad">
|
<PageScrollViewport>
|
||||||
<Card title="Outside the current view">
|
<div className="content-pad">
|
||||||
<div className="empty-state">
|
<Card title="Outside the current view">
|
||||||
<EyeOff size={24} aria-hidden="true" />
|
<div className="empty-state">
|
||||||
<p>
|
<EyeOff size={24} aria-hidden="true" />
|
||||||
This area is available to your account, but hidden by
|
<p>
|
||||||
{projection?.activeViewName
|
This area is available to your account, but hidden by
|
||||||
? ` the ${projection.activeViewName} view`
|
{projection?.activeViewName
|
||||||
: " the current view"}.
|
? ` the ${projection.activeViewName} view`
|
||||||
</p>
|
: " the current view"}.
|
||||||
<div className="button-row">
|
</p>
|
||||||
{!projection?.locked && runtime && (
|
<div className="button-row">
|
||||||
<Button variant="primary" onClick={() => void exitView()}>
|
{!projection?.locked && runtime && (
|
||||||
Exit view
|
<Button variant="primary" onClick={() => void exitView()}>
|
||||||
</Button>
|
Exit view
|
||||||
)}
|
</Button>
|
||||||
<Button onClick={() => navigate(fallbackPath)}>Back to view</Button>
|
)}
|
||||||
|
<Button onClick={() => navigate(fallbackPath)}>Back to view</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Card>
|
||||||
</Card>
|
</div>
|
||||||
</div>
|
</PageScrollViewport>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
import Card from "../components/Card";
|
import Card from "../components/Card";
|
||||||
|
import PageScrollViewport from "../components/PageScrollViewport";
|
||||||
|
|
||||||
export default function PlaceholderPage({ title }: {title: string;}) {
|
export default function PlaceholderPage({ title }: {title: string;}) {
|
||||||
return (
|
return (
|
||||||
<div className="content-pad">
|
<PageScrollViewport>
|
||||||
<div className="page-heading">
|
<div className="content-pad">
|
||||||
<h1>{title}</h1>
|
<div className="page-heading">
|
||||||
<p>i18n:govoplan-core.this_module_is_prepared_but_not_implemented_yet.6e6449ee</p>
|
<h1>{title}</h1>
|
||||||
|
<p>i18n:govoplan-core.this_module_is_prepared_but_not_implemented_yet.6e6449ee</p>
|
||||||
|
</div>
|
||||||
|
<Card>
|
||||||
|
<p className="muted">i18n:govoplan-core.next_passes_will_add_functionality_here.c13caade</p>
|
||||||
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
<Card>
|
</PageScrollViewport>);
|
||||||
<p className="muted">i18n:govoplan-core.next_passes_will_add_functionality_here.c13caade</p>
|
|
||||||
</Card>
|
|
||||||
</div>);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import Card from "../../components/Card";
|
import Card from "../../components/Card";
|
||||||
import MetricCard from "../../components/MetricCard";
|
import MetricCard from "../../components/MetricCard";
|
||||||
|
import PageScrollViewport from "../../components/PageScrollViewport";
|
||||||
import PageTitle from "../../components/PageTitle";
|
import PageTitle from "../../components/PageTitle";
|
||||||
import { usePlatformModules } from "../../platform/ModuleContext";
|
import { usePlatformModules } from "../../platform/ModuleContext";
|
||||||
|
|
||||||
@@ -7,7 +8,8 @@ export default function DashboardPage() {
|
|||||||
const modules = usePlatformModules();
|
const modules = usePlatformModules();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="content-pad workspace-data-page core-dashboard-page">
|
<PageScrollViewport className="core-dashboard-page">
|
||||||
|
<div className="content-pad workspace-data-page">
|
||||||
<div className="page-heading split workspace-heading">
|
<div className="page-heading split workspace-heading">
|
||||||
<div>
|
<div>
|
||||||
<PageTitle>i18n:govoplan-core.dashboard.d87f47b4</PageTitle>
|
<PageTitle>i18n:govoplan-core.dashboard.d87f47b4</PageTitle>
|
||||||
@@ -37,7 +39,8 @@ export default function DashboardPage() {
|
|||||||
<p className="muted">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.</p>
|
<p className="muted">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.</p>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
</div>);
|
</div>
|
||||||
|
</PageScrollViewport>);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ export { default as MetricCard } from "./components/MetricCard";
|
|||||||
export { default as MessageDisplayPanel } from "./components/MessageDisplayPanel";
|
export { default as MessageDisplayPanel } from "./components/MessageDisplayPanel";
|
||||||
export type { MessageDisplayAttachment, MessageDisplayField } from "./components/MessageDisplayPanel";
|
export type { MessageDisplayAttachment, MessageDisplayField } from "./components/MessageDisplayPanel";
|
||||||
export { default as PageTitle } from "./components/PageTitle";
|
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 PasswordField } from "./components/PasswordField";
|
||||||
export { default as PeoplePicker } from "./components/people/PeoplePicker";
|
export { default as PeoplePicker } from "./components/people/PeoplePicker";
|
||||||
export type { PeoplePickerProps } from "./components/people/PeoplePicker";
|
export type { PeoplePickerProps } from "./components/people/PeoplePicker";
|
||||||
|
|||||||
@@ -68,8 +68,10 @@
|
|||||||
.section-link.active { border-left: 3px solid var(--accent); font-weight: 700; }
|
.section-link.active { border-left: 3px solid var(--accent); font-weight: 700; }
|
||||||
.section-link.subtle { font-size: 13px; }
|
.section-link.subtle { font-size: 13px; }
|
||||||
.workspace-content { min-width: 0; max-width: 100%; min-height: 0; overflow: auto; }
|
.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 .app-content { overflow: auto; }
|
||||||
.ui-no-sticky-section-sidebars .workspace { height: auto; min-height: 100%; }
|
.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 {
|
.ui-no-sticky-section-sidebars .section-sidebar {
|
||||||
height: max-content;
|
height: max-content;
|
||||||
max-height: none;
|
max-height: none;
|
||||||
@@ -83,7 +85,6 @@
|
|||||||
.page-heading.split { display: flex; align-items: center; justify-content: space-between; }
|
.page-heading.split { display: flex; align-items: center; justify-content: space-between; }
|
||||||
.module-entry-page { max-width: none; }
|
.module-entry-page { max-width: none; }
|
||||||
.workspace-data-page .card { margin-bottom: 18px; }
|
.workspace-data-page .card { margin-bottom: 18px; }
|
||||||
.core-dashboard-page { height: 100%; overflow: auto; }
|
|
||||||
.page-heading.workspace-heading {
|
.page-heading.workspace-heading {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user