Adopt shared WebUI structural primitives

This commit is contained in:
2026-08-18 13:17:32 +02:00
parent 3800ad4662
commit e7ee0b8017
2 changed files with 13 additions and 56 deletions
+11 -11
View File
@@ -21,12 +21,15 @@ import { DialogForm, ActionToolbar,
Dialog, Dialog,
DismissibleAlert, DismissibleAlert,
DocumentationHelpLink, DocumentationHelpLink,
FilterBar,
FormField, FormField,
i18nMessage, i18nMessage,
LoadingIndicator, LoadingIndicator,
PageScrollViewport, PageScrollViewport,
StatePanel,
StatusBadge, StatusBadge,
useTemporalDataContext, useTemporalDataContext,
WorkspaceFrame,
type DataGridColumn, type DataGridColumn,
type PlatformRouteContext type PlatformRouteContext
} from "@govoplan/core-webui"; } from "@govoplan/core-webui";
@@ -232,8 +235,8 @@ export default function RecordsPage({ settings, auth }: PlatformRouteContext) {
return ( return (
<main className="records-page" data-help-context-id="records.workspace"> <main className="records-page" data-help-context-id="records.workspace">
<div className="records-shell"> <WorkspaceFrame className="records-shell" label="Records workspace" interfaceId="records.workspace" helpContextId="records.workspace" helpModuleId="records">
<ActionToolbar className="records-toolbar"> <ActionToolbar surface="panel-header" className="records-toolbar">
<Button <Button
type="button" type="button"
variant="primary" variant="primary"
@@ -254,7 +257,7 @@ export default function RecordsPage({ settings, auth }: PlatformRouteContext) {
Catalog Catalog
</Button> </Button>
)} )}
<form className="records-search" onSubmit={submitSearch}> <FilterBar as="form" surface="control" wrap="never" width="compact" className="records-search" onSubmit={submitSearch}>
<Search size={17} aria-hidden="true" /> <Search size={17} aria-hidden="true" />
<input <input
value={query} value={query}
@@ -262,7 +265,7 @@ export default function RecordsPage({ settings, auth }: PlatformRouteContext) {
aria-label="Search records" aria-label="Search records"
placeholder="Search records" placeholder="Search records"
/> />
</form> </FilterBar>
<span className="records-result-count"> <span className="records-result-count">
{i18nMessage("i18n:govoplan-records.record_count", { value0: total })} {i18nMessage("i18n:govoplan-records.record_count", { value0: total })}
</span> </span>
@@ -319,7 +322,7 @@ export default function RecordsPage({ settings, auth }: PlatformRouteContext) {
</button> </button>
))} ))}
{!loading && catalog.file_plan.length === 0 && ( {!loading && catalog.file_plan.length === 0 && (
<p className="records-empty-note">No file-plan nodes are configured.</p> <StatePanel size="inline" description="No file-plan nodes are configured." />
)} )}
</PageScrollViewport> </PageScrollViewport>
</aside> </aside>
@@ -360,10 +363,7 @@ export default function RecordsPage({ settings, auth }: PlatformRouteContext) {
{detailLoading && <LoadingIndicator label="Loading record" />} {detailLoading && <LoadingIndicator label="Loading record" />}
{detailError && <DismissibleAlert tone="danger" resetKey={detailError}>{detailError}</DismissibleAlert>} {detailError && <DismissibleAlert tone="danger" resetKey={detailError}>{detailError}</DismissibleAlert>}
{!detailLoading && !detailError && !detail && ( {!detailLoading && !detailError && !detail && (
<div className="records-detail-empty"> <StatePanel size="fill" icon={<Archive size={28} />} title="Records" description="Select a record to inspect its contents and chronology." />
<Archive size={28} aria-hidden="true" />
<p>Select a record to inspect its contents and chronology.</p>
</div>
)} )}
{!detailLoading && detail && ( {!detailLoading && detail && (
<RecordDetailPanel <RecordDetailPanel
@@ -381,7 +381,7 @@ export default function RecordsPage({ settings, auth }: PlatformRouteContext) {
)} )}
</section> </section>
</div> </div>
</div> </WorkspaceFrame>
<RecordDialog <RecordDialog
open={createOpen} open={createOpen}
@@ -508,7 +508,7 @@ function RecordDetailPanel({
<span>{detail.items.length}</span> <span>{detail.items.length}</span>
</div> </div>
{detail.items.length === 0 ? ( {detail.items.length === 0 ? (
<p className="records-empty-note">No items have been filed in this temporal view.</p> <StatePanel size="inline" description="No items have been filed in this temporal view." />
) : ( ) : (
<div className="records-item-list"> <div className="records-item-list">
{detail.items.map((item) => ( {detail.items.map((item) => (
+2 -45
View File
@@ -1,40 +1,14 @@
.records-page, .records-page {
.records-shell {
height: 100%; height: 100%;
min-height: 0; min-height: 0;
overflow: hidden; overflow: hidden;
} }
.records-shell {
display: flex;
flex-direction: column;
background: var(--panel);
}
.records-toolbar {
display: flex;
align-items: center;
gap: 10px;
min-height: 58px;
padding: 9px 14px;
border-bottom: var(--border-line-dark);
background: var(--panel-header);
}
.records-search { .records-search {
display: flex; flex: 1 1 420px;
align-items: center;
gap: 8px;
width: min(420px, 100%);
margin-left: 8px; margin-left: 8px;
} }
.records-search input {
min-width: 130px;
height: 36px;
flex: 1;
}
.records-result-count { .records-result-count {
margin-left: auto; margin-left: auto;
color: var(--muted); color: var(--muted);
@@ -205,17 +179,6 @@
padding: 18px 20px 32px; padding: 18px 20px 32px;
} }
.records-detail-empty {
display: grid;
place-items: center;
align-content: center;
gap: 10px;
height: 100%;
color: var(--muted);
padding: 30px;
text-align: center;
}
.records-detail-header, .records-detail-header,
.records-detail-actions, .records-detail-actions,
.records-section-heading { .records-section-heading {
@@ -529,12 +492,6 @@
font-weight: 700; font-weight: 700;
} }
.records-empty-note {
margin: 12px;
color: var(--muted);
font-size: var(--font-size-sm);
}
.records-dialog { .records-dialog {
width: min(760px, calc(100vw - 32px)); width: min(760px, calc(100vw - 32px));
} }