Every node has a Settings layout area at /{nodePath}/Settings. It renders a two-pane Splitter: a navigation menu on the left and the selected tab's content on the right. The tab is selected by the area id — /{nodePath}/Settings/{tabId} — so each tab is directly linkable.
The page is assembled from contributed tabs, not hard-coded. Any node type (or feature) registers tabs through a provider, and the page evaluates them reactively, filters by permission, and renders them sorted by order.
Anatomy
┌─ Settings ─────────────────────────────────────────────┐
│ ┌───────────────┐ ║ ┌─────────────────────────────┐ │
│ │ 🔎 Search… │ ║ │ │ │
│ ├───────────────┤ ║ │ selected tab content │ │
│ │ Metadata │ ║ │ (scrolls independently) │ │
│ │ ▸ Management │ ║ │ │ │
│ │ ▸ Security │ ║ │ │ │
│ │ Appearance │ ║ │ │ │
│ └───────────────┘ ║ └─────────────────────────────┘ │
│ menu pane ↑ draggable / collapsible divider │
└─────────────────────────────────────────────────────────┘
- Two panes scroll independently. The menu and the content each have their own scroll context; a long content tab never pushes the menu off-screen, and vice-versa.
- The divider is draggable and the menu pane collapses (it is marked
Collapsible), so the content can take the full width when the menu is not needed. - A search box is pinned at the top of the menu pane and filters the tabs live as you type.
Scrolling note. The panes scroll via a flex chain (
flex: 1 1 auto; min-height: 0), notheight: 100%. A splitter pane's height comes from flex stretch, which is indefinite for percentage resolution — so a childheight: 100%collapses to content height and is then clipped by the pane'soverflow: hidden, leaving nothing to scroll. See Splitter → Scrolling Panes.
Searching settings
The search box matches a query, case-insensitively, against three things per tab:
- the tab Label (e.g. "Appearance"),
- the tab Group (e.g. "Security"), and
- the tab Keywords — terms describing the fields inside the section.
Keywords are what make the box search content, not just section names. Typing dark mode, roles, icon, or version surfaces the section that contains that setting even when the word never appears in the tab's title. Only the menu list re-renders as you type — the search box itself is a separate, static area, so it keeps focus.
The default tabs ship with keywords:
| Tab | A few of its keywords |
|---|---|
| Metadata | name, description, category, icon, order, namespace, version, timestamps |
| Node Types | types, definitions, schema, data model |
| Files | documents, uploads, attachments, collections |
| Access Control | permissions, roles, assignments, sharing, grant, deny |
| Groups | members, membership, teams |
| Effective Access | permissions, test, who can, audit |
| Appearance | theme, color, dark mode, light mode, style |
Registering a tab
Contribute a tab from a node type's hub configuration with AddSettingsMenuItems. Pass Keywords so the section is reachable by the fields it contains, not just its label.
config.AddSettingsMenuItems(
new SettingsMenuItemDefinition(
Id: "Notifications", // → /{node}/Settings/Notifications
Label: "Notifications",
ContentBuilder: BuildNotificationsTab, // (host, stack, node) => UiControl
Group: "Communication", // optional NavGroup heading
Icon: FluentIcons.Alert(),
Order: 250,
RequiredPermission: Permission.Update, // hidden unless the viewer has it
Keywords: ["email", "digest", "frequency", "mute", "channels"]));
The ContentBuilder receives the LayoutAreaHost, a pre-classed content StackControl (already wired for internal scrolling), and the node, and returns the tab's content. Build it from the standard controls and the framework editors — see Layout Areas.
A provider may also yield tabs reactively (e.g. an admin-only tab that appears once a live permission check resolves) by registering a SettingsMenuItemProvider that returns IObservable<IReadOnlyList<SettingsMenuItemDefinition>>.
SettingsMenuItemDefinition reference
| Parameter | Purpose |
|---|---|
Id |
Tab identifier; the area id in /{node}/Settings/{Id}. |
Label |
Display text in the menu (matched by search). |
ContentBuilder |
(host, stack, node) => UiControl — builds the tab content. |
Group |
Optional NavGroup heading (matched by search). |
Icon / GroupIcon |
Menu icon / group-header icon. |
Order |
Sort order; groups order by their minimum item order. |
RequiredPermission |
Tab is hidden unless the viewer holds this permission. |
Keywords |
Extra search terms for the fields inside the tab. Null = match by label/group only. |
See Also
- Splitter — the resizable/collapsible two-pane container, and the scrolling-panes pattern
- Layout Areas — building the content a tab renders
- Node Menu Items — the sibling pattern for context-menu contributions
- Data Model View — the Mermaid + JSON view used on the Node Types tab and a node type's
$Modelarea