fix(ui): centralize contextual help and navigation presentation

Verified with the coordinated workspace changes by devkit full run
2026-09-08T225814-186389-0000-3e3ed7cd (all seven phases passed).
This shared UI pass does not mark the individual module reviews complete.
This commit is contained in:
2026-09-09 02:03:55 +02:00
parent c101ee1974
commit 492ab7711a
8 changed files with 34 additions and 26 deletions
@@ -8,7 +8,7 @@ const page = readFileSync(pagePath, "utf8");
const styles = readFileSync(stylesPath, "utf8");
assert.match(page, /SelectionList,[\s\S]*SelectionListItem,[\s\S]*from "@govoplan\/core-webui"/);
assert.match(page, /<SelectionList label="i18n:govoplan-notifications\.notifications" className="notifications-selection-list">/);
assert.match(page, /<SelectionList\b(?=[^>]*\bvariant="navigation")(?=[^>]*\blabel="i18n:govoplan-notifications\.notifications")(?=[^>]*\bclassName="notifications-selection-list")[^>]*>/);
assert.match(page, /<SelectionListItem[\s\S]*selected=\{selected\?\.id === notification\.id\}/);
assert.match(page, /className=\{`notifications-list-item \$\{notification\.read_at \? "is-read" : ""\}`\}/);
assert.doesNotMatch(page, /<button[\s\S]{0,160}notifications-list-item/);
@@ -8,6 +8,7 @@ import {
CountBadge,
DismissibleAlert,
DocumentationHelpLink,
TextWithHelp,
MultiSelectFilter,
SelectionList,
SelectionListItem,
@@ -288,11 +289,11 @@ export default function NotificationCenterPage({ settings, auth }: { settings: A
scope="detail-pane"
variant="detail"
className="notifications-topbar"
contextActions={<div className="notifications-title-line">
<Bell size={18} />
title={<span className="notifications-title-line">
<Bell size={18} aria-hidden="true" />
<strong>{selected?.subject || selected?.event_kind || "i18n:govoplan-notifications.surface.center"}</strong>
</div>}
helpAction={<DocumentationHelpLink reference={NOTIFICATIONS_DOCUMENTATION} />}
</span>}
titleHelp={<DocumentationHelpLink reference={NOTIFICATIONS_DOCUMENTATION} />}
primaryActions={<div className="notifications-actions">
<Button onClick={() => void markSelected("read")} disabled={Boolean(markReadDisabledReason)} disabledReason={markReadDisabledReason}>
<Check size={16} /> i18n:govoplan-notifications.mark_read
@@ -389,8 +390,9 @@ function NotificationDetails({ notification }: { notification: NotificationMessa
<section className="notifications-attempts">
<ActionToolbar surface="section-header" className="notifications-section-heading">
<h2>i18n:govoplan-notifications.delivery_attempts</h2>
<DocumentationHelpLink reference={NOTIFICATIONS_DELIVERY_DOCUMENTATION} />
<TextWithHelp as="div" help={<DocumentationHelpLink reference={NOTIFICATIONS_DELIVERY_DOCUMENTATION} />}>
<h2>i18n:govoplan-notifications.delivery_attempts</h2>
</TextWithHelp>
</ActionToolbar>
{notification.attempts.length === 0 ? <p className="muted">i18n:govoplan-notifications.no_delivery_attempt</p> : null}
{notification.attempts.map((attempt) => (
@@ -183,9 +183,6 @@ export default function NotificationSettingsPanel({ settings, auth }: { settings
return (
<ContentGrid columns={2} collapseAt="workspace" className="notifications-settings-panel">
<div className="notifications-settings-documentation">
<DocumentationHelpLink reference={NOTIFICATIONS_DOCUMENTATION} />
</div>
{!canWrite ? (
<ActionBlockerHint
tone="info"
@@ -200,7 +197,7 @@ export default function NotificationSettingsPanel({ settings, auth }: { settings
documentation={NOTIFICATIONS_DOCUMENTATION}
/>
) : null}
<Card title="i18n:govoplan-notifications.notifications">
<Card title="i18n:govoplan-notifications.notifications" titleHelp={<DocumentationHelpLink reference={NOTIFICATIONS_DOCUMENTATION} />}>
<FormGrid columns={1} collapseAt="standard" className="">
<ToggleSwitch
label="i18n:govoplan-notifications.unread_badge"
@@ -230,9 +227,9 @@ export default function NotificationSettingsPanel({ settings, auth }: { settings
{message ? <DismissibleAlert tone={messageTone} resetKey={message} floating>{message}</DismissibleAlert> : null}
</FormGrid>
</Card>
<Card title="i18n:govoplan-notifications.delivery">
<Card title="i18n:govoplan-notifications.delivery" titleHelp={<DocumentationHelpLink reference={NOTIFICATIONS_DELIVERY_DOCUMENTATION} />}>
<FormGrid columns={1} collapseAt="standard" className="">
<DocumentationHelpLink reference={NOTIFICATIONS_DELIVERY_DOCUMENTATION} />
<div className="notifications-settings-inline-title">
<Mail size={16} />
<strong>i18n:govoplan-notifications.email_notifications</strong>
@@ -2,7 +2,6 @@ import { MetricGrid } from "@govoplan/core-webui";
import { Link } from "react-router";
import {
DismissibleAlert,
DocumentationHelpLink,
LoadingFrame,
MetricCard,
adminErrorMessage,
@@ -11,7 +10,6 @@ import {
type DashboardWidgetConfiguration,
useSharedNotificationSummary
} from "@govoplan/core-webui";
import { NOTIFICATIONS_DOCUMENTATION } from "./interfacePatterns";
export default function NotificationSummaryWidget({
settings,
@@ -66,7 +64,6 @@ export default function NotificationSummaryWidget({
)}
</MetricGrid>
<div className="notifications-widget-actions">
<DocumentationHelpLink reference={NOTIFICATIONS_DOCUMENTATION} />
{showCenterLink && (
<Link className="btn btn-secondary" to="/notifications">
i18n:govoplan-notifications.open_center
+2
View File
@@ -5,6 +5,7 @@ import type {
SettingsSectionsUiCapability
} from "@govoplan/core-webui";
import NotificationSummaryWidget from "./features/notifications/NotificationSummaryWidget";
import { NOTIFICATIONS_DOCUMENTATION } from "./features/notifications/interfacePatterns";
import { generatedTranslations } from "./i18n/generatedTranslations";
import "./styles/notifications.css";
@@ -19,6 +20,7 @@ const notificationDashboardWidgets: DashboardWidgetsUiCapability = {
id: "notifications.summary",
surfaceId: "notifications.widget.summary",
title: "i18n:govoplan-notifications.surface.center",
documentation: NOTIFICATIONS_DOCUMENTATION,
description: "i18n:govoplan-notifications.widget_description",
moduleId: "notifications",
category: "i18n:govoplan-notifications.communication",
+1 -7
View File
@@ -89,7 +89,7 @@
}
.notifications-title-line {
min-width: 160px;
min-width: 0;
}
.notifications-title-line strong {
@@ -169,16 +169,10 @@
align-items: start;
}
.notifications-settings-documentation,
.notifications-settings-panel > .action-blocker-hint {
grid-column: 1 / -1;
}
.notifications-settings-documentation {
display: flex;
justify-content: flex-end;
}
.notifications-settings-inline-title {
display: flex;
align-items: center;