Skip to content

feat(ws7): generic top-bar menus from data + AI menu entries as contributions - #1652

Merged
rbuergi merged 3 commits into
mainfrom
feat/ws7-ai-menu-contributions
Aug 16, 2026
Merged

rbuergi merged 3 commits into
mainfrom
feat/ws7-ai-menu-contributions

Conversation

@rbuergi

@rbuergi rbuergi commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Slice 3 of #1645, generalized per the maintainer's direction: any top-bar menu can be injected as data, not just entries into the compiled menus.

The generic mechanism

  • UiContribution gains Href (overrides the derived area URL — catalog-style absolute links), Tooltip/TooltipKey, and a reserved TopBar context: a contribution there declares a whole NEW top-bar dropdown. Its Area names the menu's own context key; Label/Icon/Order/Tooltip style the button; its entries are ordinary contributions targeting that key. The closed gate vocabulary applies to the declaration itself — an AdminOnly menu disappears wholesale for non-admins, and a menu with no visible entries renders nothing.
  • The menu renderer's context list unions the contexts declared by data (render-time snapshot via UiContributionCatalog.Current), so $Menu:{key} slots exist for data-declared menus. LayoutAreaView pumps the TopBar stream and subscribes each declared key the first time it appears (registered on the area stream, same teardown as the fixed menus). PortalLayoutBase renders one dropdown per declaration after the compiled menus, hidden while empty (the GitHub-menu pattern), with string icons (emoji/svg) sized to match the Fluent buttons.
  • No new wire shape anywhere: a menu declaration IS a projected menu item; entries ride the existing per-context aggregation, which was already contribution-aware.

The AI menu migration

The six navigation entries (Threads / Models / Tiers / Providers / Agents / Skills) become seeded UiContribution nodes (AiMenuContributions, Admin/UiContribution/*) — pure links, so they ride the same lane a plugin's AI-menu entry arrives through. Only the imperative New thread click-action sentinel stays compiled (AiMenuItems): its destination resolves from the circuit's viewer identity at click time — behavior, which the closed vocabulary deliberately cannot express. The side panel's three entries (new-chat/history/fullscreen) are likewise behavior sentinels and stay compiled; plugins can already contribute SidePanel-context entries through the generic lane.

No visible change for users: the AI menu renders identically (labels, icons, order, tooltips, localization keys all pre-existing — no i18n catalog change, no react mirror change). Anonymous viewers never saw these menus (the block is inside AuthorizeView), so the contribution permission floor changes nothing.

Verification

  • MeshWeaver.Graph, MeshWeaver.Blazor.Portal, Memex.Portal.Shared, Memex.Portal.Monolith build clean -c Release -warnaserror.
  • MeshWeaver.Graph.Test 1162/1162 (new pins: Href override + tooltip carry-through; TopBar declaration projects only in the TopBar context and honors AdminOnly), Memex.Portal.Shared.Test 361/361 (AiMenuNewThreadTest repointed: single compiled entry, seeds all Href-navigating + localized, uniqueness spans both lists).

No What's New entry: platform capability for plugin authors; the rendered UI is unchanged (same precedent as #1646/#1648).

🤖 Generated with Claude Code

…ibutions

Slice 3 of design #1645, generalized per maintainer direction: ANY top-bar
menu can now be injected as data, not just entries into compiled menus.

- UiContribution gains Href (overrides the derived area URL — catalog-style
  links), Tooltip/TooltipKey, and the TopBar context: a contribution there
  declares a whole NEW top-bar dropdown — its Area names the menu's context
  key, Label/Icon/Order/Tooltip style the button, entries are ordinary
  contributions targeting that key, and the closed gate vocabulary applies
  to the declaration (an AdminOnly menu disappears wholesale).
- The menu renderer's context list now unions the contexts declared by
  data (snapshot per render via UiContributionCatalog.Current), so
  $Menu:{key} slots exist for data-declared menus; LayoutAreaView pumps
  the TopBar stream and subscribes each declared key as it appears;
  PortalLayoutBase renders one dropdown per declaration after the compiled
  menus, hidden while it has no visible entries (the GitHub pattern).
- The AI menu's six navigation entries (Threads/Models/Tiers/Providers/
  Agents/Skills) migrate to seeded UiContribution nodes
  (AiMenuContributions); only the imperative "New thread" click-action
  sentinel stays compiled — behavior, which the closed vocabulary
  deliberately cannot express.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 16, 2026 07:42
The UiExtensibility page gains the composition-first section: the closed
field vocabulary (contexts incl. TopBar, Href/Tooltip, grouping, gates),
the security boundary, settings-tab and top-bar-menu semantics, and the
seeding pattern; the seams table points menus/settings/top-bar at the
data lane first. DocumentationLinkIntegrityTest green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the WS7 UiContribution mechanism to allow data-declared top-bar dropdown menus (via a reserved TopBar context), and migrates the AI menu’s pure navigation entries to seeded UiContribution nodes so plugins and platform content share the same contribution lane.

Changes:

  • Add UiContribution.Href + tooltip fields and project them into NodeMenuItemDefinition (with Href overriding derived area URLs).
  • Introduce TopBar as a reserved contribution context to declare new top-bar dropdowns, and wire the portal to subscribe/render them dynamically.
  • Move AI menu navigation entries (Threads/Models/Tiers/Providers/Agents/Skills) to seeded UiContribution nodes; keep only the imperative “New thread” entry compiled.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
test/MeshWeaver.Graph.Test/UiContributionProjectionTest.cs Adds projection tests for Href override, tooltip carry-through, and TopBar declarations.
test/Memex.Portal.Shared.Test/AiMenuNewThreadTest.cs Updates AI menu tests for the split between the compiled sentinel and seeded navigation contributions.
src/MeshWeaver.Graph/Configuration/UiContributionProjection.cs Projects Href/tooltips into NodeMenuItemDefinition and supports explicit navigation links.
src/MeshWeaver.Graph/Configuration/UiContributionNodeType.cs Extends UiContribution with TopBar context and new Href/tooltip fields.
src/MeshWeaver.Graph/Configuration/UiContributionCatalog.cs Adds a synchronous Current snapshot for render-time context enumeration.
src/MeshWeaver.Graph/Configuration/NodeMenuItemsExtensions.cs Unions menu contexts declared by UiContribution data (including TopBar-declared menu keys).
src/MeshWeaver.Blazor/Components/LayoutAreaView.razor.cs Subscribes to TopBar declarations and dynamically subscribes each declared menu key’s entry stream.
src/MeshWeaver.Blazor.Portal/Layout/PortalLayoutBase.razor.css Styles contributed top-bar menu icons (emoji/img) to match Fluent sizing/contrast.
src/MeshWeaver.Blazor.Portal/Layout/PortalLayoutBase.razor.cs Tracks and renders contributed top-bar menus and their per-key subscriptions.
src/MeshWeaver.Blazor.Portal/Layout/PortalLayoutBase.razor Renders one top-bar dropdown per declaration, hidden when its entry list is empty.
memex/Memex.Portal.Shared/MemexConfiguration.cs Removes compiled AI navigation items; wires AddAiMenuContributions().
memex/Memex.Portal.Shared/AiMenuContributions.cs Adds seeded UiContribution nodes for AI menu navigation entries.
Suppressed comments (1)

src/MeshWeaver.Graph/Configuration/UiContributionNodeType.cs:79

  • The Context documentation lists AiMenu, but the actual AI-menu context value used elsewhere is "AI" (see NodeMenuItemsExtensions.AiMenuContext). Also, now that TopBar is a reserved context, it should be included in this summary so plugin authors don’t discover it only by reading other docs.
    /// <summary>
    /// Which menu the entry contributes to: <c>Node</c>, <c>Mesh</c>, <c>Settings</c>,
    /// <c>AiMenu</c> or <c>SidePanel</c>. Unset ⇒ <c>Node</c>.
    /// </summary>

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/MeshWeaver.Graph/Configuration/UiContributionProjection.cs
@github-actions

github-actions Bot commented Aug 16, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 0)

913 tests   912 ✅  11m 20s ⏱️
 10 suites    1 💤
 10 files      0 ❌

Results for commit a153f37.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 16, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 5)

1 367 tests   1 366 ✅  6m 5s ⏱️
   11 suites      1 💤
   11 files        0 ❌

Results for commit a153f37.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 16, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 4)

1 541 tests   1 535 ✅  7m 27s ⏱️
   11 suites      6 💤
   11 files        0 ❌

Results for commit a153f37.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 16, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 3)

   11 files     11 suites   5m 54s ⏱️
2 194 tests 2 003 ✅ 191 💤 0 ❌
2 553 runs  2 362 ✅ 191 💤 0 ❌

Results for commit a153f37.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 16, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 2)

2 366 tests   2 362 ✅  7m 55s ⏱️
   11 suites      4 💤
   11 files        0 ❌

Results for commit a153f37.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 16, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 1)

2 178 tests   2 075 ✅  6m 54s ⏱️
   11 suites    103 💤
   11 files        0 ❌

Results for commit a153f37.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 16, 2026 •

Copy link
Copy Markdown
Contributor

Test Results

    65 files      65 suites   45m 38s ⏱️
10 559 tests 10 253 ✅ 306 💤 0 ❌
10 918 runs  10 612 ✅ 306 💤 0 ❌

Results for commit a153f37.

♻️ This comment has been updated with latest results.

Href is mesh data reaching NavigationManager: schemes (javascript:,
https:) and protocol-relative //host forms are an XSS/phishing surface
the closed vocabulary must not open. The compiled gate accepts only
single-slash-rooted paths; anything else falls back to the derived area
URL. Pinned with a 4-case theory; external links stay a compiled concern
until an explicit allowlist vocabulary exists.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants