Contributions
A NavBar needs its entries from wherever they are declared - a dozen features scattered across a dozen modules, each adding the one link it owns. A slot on its own is the wrong tool for this: a slot is one parent placing one block of content into one region, not many children contributing into a shared collection. contribute to is the many-to-one counterpart.
Syntax
Section titled “Syntax”Slots live on the application’s layout and on every screen template and dialog template, and any of them can declare it accepts contributions under a name:
layout <Name> <slot-name> contributes <ContributionPoint> <slot-name>module <Name> screen template <TemplateName> <slot-name> contributes <ContributionPoint> <slot-name>Anything anywhere in the module/feature tree contributes to it, without knowing or caring who is listening:
contribute to <ContributionPoint> navigate to <Screen> [by <param>] label "<text>" order <number><slot-name> contributes <ContributionPoint>- marks a slot as the target for contributions under that name. A slot withoutcontributesbehaves exactly as it always has.contribute to <ContributionPoint>- one contributed item. Declared directly on amodule(alongsidescreen template,dialog template,formandfeature) or on afeatureat any nesting depth.navigate,labelandorderare all optional.labelaccepts an unquoted$strings.<key>token in place of a literal - see Internationalization.
Example
Section titled “Example”module Invoicing screen template AppShell navbar contributes Navigation main
feature InvoiceManagement slice StateView InvoiceList screen InvoiceList
contribute to Navigation navigate to InvoiceList label "Invoices" order 10How a contribution resolves
Section titled “How a contribution resolves”A contribution attaches to the nearest enclosing structure that declares a matching contribution point, walking outward the same way a bare name already resolves elsewhere in the document - just through the module/feature containment tree rather than by declaration scope. Concretely: a contribution first looks for a contributes <ContributionPoint> slot among its own module’s templates. A module with its own matching slot stops contributions inside it from bubbling any further - that module owns the point. Only when the module has no matching slot does the search continue outward, across every other module in the document, and finally to the application’s own layouts, which belong to no module and are the outermost shell of all.
This gives three real tiers of nesting: application-wide (the layout declares the point, so every module in the document contributes into the one shell - the natural home of Navigation), cross-module (a contribution resolves to some other module’s template because its own module has none that matches) and module-level (a module’s own template claims every contribution inside it, however deeply nested in that module’s features). A fourth tier - a feature declaring its own sub-shell that only its own slices contribute to - would need a template scoped to a feature rather than a module, which does not exist yet.
Unresolved and ambiguous contribution points are warnings, the same as every other reference in the document: a name may still resolve to something outside the document, and the point is that the gap stays visible.
module Payments contribute to Navigation navigate to InvoiceListIf Payments has no template of its own, and two other modules each declare a contributes Navigation slot, the contribution is ambiguous - both are equally near, and nothing in the document says which one it means.
Route arguments
Section titled “Route arguments”navigate to <Screen> by <param> is not string interpolation. It reuses the exact typed navigate binding a screen’s action and on row-click already use, checked by the compiler the same way any other bare name is. Turning that into a URL, a query string, or a native deep link is a rendering concern the widget consuming the contribution point owns - not something the language decides.
Navigation is the mechanism’s first user, not the whole of it - a widget declares whatever contribution point name and shape it needs, and contribute to <Name> opens a property bag shaped by that name. This version of the mechanism ships with navigate, label and order; ordering by a group beyond a flat list, and an explicit override for the rare case where nearest-enclosing is not the contribution point a contributor means, are intentionally left for a later iteration.