Adopt shared WebUI structural primitives

This commit is contained in:
2026-08-18 13:17:32 +02:00
parent 1a7b9fbf16
commit 5bae5bbc3e
3 changed files with 42 additions and 61 deletions
+7 -4
View File
@@ -38,11 +38,14 @@ units, relations, functions, settings, and their mutation consequences.
## State And Accessibility Evidence ## State And Accessibility Evidence
The module uses Core page, subnavigation, grid, tree, card, dialog, loading, The module uses Core `WorkspaceLayout` and `PageLayout` for both the standalone
alert, status, blocker, field-help, and disabled-action controls. Stable table workspace and embedded administration contribution, plus shared subnavigation,
grid, tree, card, dialog, loading, alert, status, blocker, field-help, and
disabled-action controls. Pane width, content inset, headings, route actions,
notices, scrolling, and responsive navigation are therefore Core-owned rather
than repeated in Organizations CSS. Stable table
action slots remain keyboard reachable; dialogs retain shared focus containment action slots remain keyboard reachable; dialogs retain shared focus containment
and return. Responsive behavior stays owned by the existing workspace and admin and return. Labels and accessible properties use the English/German module
shell CSS. Labels and accessible properties use the English/German module
catalogue, and API errors are bounded to the current tenant operation. catalogue, and API errors are bounded to the current tenant operation.
The manifest contributes stable help contexts for the workspace, sections, The manifest contributes stable help contexts for the workspace, sections,
@@ -8,14 +8,13 @@ import { FormLayout, ActionToolbar,
Card, Card,
DataGrid, DataGrid,
Dialog, Dialog,
DismissibleAlert,
DocumentationHelpLink, DocumentationHelpLink,
ExplorerTree, ExplorerTree,
FormField, FormField,
IconButton, IconButton,
LoadingFrame, LoadingFrame,
ModuleSubnav, ModuleSubnav,
PageTitle, PageLayout,
StatusBadge, StatusBadge,
TableActionGroup, TableActionGroup,
ToggleSwitch, ToggleSwitch,
@@ -26,6 +25,7 @@ import { FormLayout, ActionToolbar,
useUnsavedDraftGuard, useUnsavedDraftGuard,
usePlatformUiCapabilities, usePlatformUiCapabilities,
useViewSurfaces, useViewSurfaces,
WorkspaceLayout,
type ApiSettings, type ApiSettings,
type AuthInfo, type AuthInfo,
type DataGridColumn, type DataGridColumn,
@@ -998,13 +998,12 @@ export default function OrganizationsPage({
: undefined; : undefined;
const content = ( const content = (
<div className={`${mode === "workspace" ? "content-pad " : ""}organizations-page ${mode === "admin" ? "organizations-admin-page" : ""}`.trim()}> <>
<div className="page-heading split organizations-heading"> <PageLayout
<div> title={title}
<PageTitle loading={loading}>{title}</PageTitle> description={description}
<p>{description}</p> actions={(
</div> <>
<ActionToolbar className="organizations-toolbar">
<DocumentationHelpLink reference={ORGANIZATIONS_DOCUMENTATION} /> <DocumentationHelpLink reference={ORGANIZATIONS_DOCUMENTATION} />
<Button <Button
type="button" type="button"
@@ -1015,11 +1014,15 @@ export default function OrganizationsPage({
> >
<RefreshCw size={16} aria-hidden="true" /> i18n:govoplan-organizations.reload.cce71553 <RefreshCw size={16} aria-hidden="true" /> i18n:govoplan-organizations.reload.cce71553
</Button> </Button>
</ActionToolbar> </>
</div> )}
mode={mode === "workspace" ? "workspace" : "embedded"}
{error && <DismissibleAlert tone="danger" resetKey={error} floating>{error}</DismissibleAlert>} headerLoading={loading}
{success && !error && <DismissibleAlert tone="success" resetKey={success} floating>{success}</DismissibleAlert>} error={error}
success={error ? "" : success}
className={`organizations-page ${mode === "admin" ? "organizations-admin-page" : ""}`.trim()}
headerClassName="organizations-heading"
>
{!canWriteActive && ( {!canWriteActive && (
<ActionBlockerHint <ActionBlockerHint
reason={{ reason={{
@@ -1044,23 +1047,30 @@ export default function OrganizationsPage({
{active === "relations" && renderRelationsSection()} {active === "relations" && renderRelationsSection()}
{active === "functions" && renderFunctionsSection()} {active === "functions" && renderFunctionsSection()}
</LoadingFrame> </LoadingFrame>
</PageLayout>
{renderEditorDialog()} {renderEditorDialog()}
</div> </>
); );
if (mode === "admin") return content; if (mode === "admin") return content;
return ( return (
<div className="workspace organizations-workspace"> <WorkspaceLayout
<ModuleSubnav className="organizations-workspace"
active={active} primarySize="wide"
groups={visibleSectionGroups} primary={(
onSelect={(section) => requestDiscard(() => setActive(section))} <ModuleSubnav
/> active={active}
<main className="workspace-content"> groups={visibleSectionGroups}
{content} onSelect={(section) => requestDiscard(() => setActive(section))}
</main> />
</div> )}
primaryLabel="i18n:govoplan-organizations.organization_model.5945c48a"
contentLabel={title}
documentationType={mode === "admin" ? "admin" : "user"}
>
{content}
</WorkspaceLayout>
); );
function renderModelSection() { function renderModelSection() {
-32
View File
@@ -1,30 +1,3 @@
.organizations-workspace {
grid-template-columns: 230px minmax(0, 1fr);
background: var(--bg);
}
.organizations-page {
display: grid;
gap: 18px;
width: 100%;
}
.organizations-admin-page {
max-width: 100%;
}
.organizations-heading {
margin-bottom: 4px;
}
.organizations-toolbar {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 12px;
flex-wrap: wrap;
}
.organizations-check-list { .organizations-check-list {
display: grid; display: grid;
gap: 10px; gap: 10px;
@@ -67,11 +40,6 @@
color: var(--muted); color: var(--muted);
} }
@media (max-width: 900px) {
.organizations-workspace {
grid-template-columns: 1fr;
}
}
.organization-upgrade-toolbar { .organization-upgrade-toolbar {
display: grid; display: grid;
grid-template-columns: minmax(16rem, 1fr) auto; grid-template-columns: minmax(16rem, 1fr) auto;