Skip to main content

What are outlets?

Outlets are widgets that render presentations. They watch a specific surface and rebuild when the active item changes. Outlets contain zero business logic. They just render what the engine tells them to show.
Think of outlets as β€œslots” in your UI where presentations appear. The engine controls what goes in the slot.

Basic outlet

The simplest outlet uses PresentumOutlet:
When no item is active for the surface, the outlet renders SizedBox.shrink() by default.

Custom placeholder

Provide a custom widget when nothing is shown:

Composition outlets

PresentumOutlet$Composition gives you access to both active and queued items:
Composition outlets are useful for showing β€œnext up” indicators or carousels.

Multi-surface composition

Combine items from multiple surfaces:

Cross-presentum composition with animations

PresentumOutlet$Composition2 supports combining items from different Presentum instances (cross-universe composition), allowing seamless coordination between multiple presentation systems with smooth animated transitions.

Production example

Here’s a real-world outlet that combines campaigns and feature flags, showing the highest-priority item with smooth fade and size transitions:

How it works

  1. Cross-universe composition: Combines items from two separate Presentum instances:
    • Campaign presentations (CampaignPresentumItem)
    • Feature flag presentations (FeatureItem)
  2. Priority resolution: The resolver merges both lists and sorts by priority, selecting only the highest-priority item to display
  3. Animated transitions: FadeSizeTransitionSwitcher provides smooth animations when:
    • A campaign is dismissed and a feature banner appears
    • A feature is disabled and a campaign takes its place
    • Items change priority dynamically

Smooth transition widget

The FadeSizeTransitionSwitcher combines fade and size animations:

Key benefits

Seamless coordination

Multiple Presentum instances can compete for the same UI slot without conflicts. The outlet handles priority resolution automatically.

Smooth transitions

When one banner is dismissed, the next highest-priority item smoothly animates in with fade and size transitions.

Declarative priority

Priority logic is centralized in the resolver. Guards don’t need to know about other presentation types.

Type-safe composition

Despite combining different item types, the outlet remains type-safe with pattern matching.
Use unique ValueKeys for each widget variant to ensure AnimatedSwitcher correctly animates between different content types.
See full production example β†’ For dialogs and overlays, use a popup host that watches a surface and shows dialogs:
See production popup host ->
Use the PresentumPopupSurfaceStateMixin for automatic dialog lifecycle management. It handles showing, dismissing, and queueing popups automatically.

Accessing Presentum

Inside outlets, access the Presentum instance via context:

Inherited widgets

InheritedPresentumItem

Outlets automatically wrap builders with InheritedPresentumItem, giving child widgets access to the current item:
Access the item in descendants:
If you create custom observer widgets (not using PresentumOutlet), wrap descendants with InheritedPresentumItem so they can access the item:
Alternatively, pass the item down manually if you prefer explicit props.

Outlet patterns

Conditional rendering

With animations

Async loading

Best practices

Don’t check eligibility, fetch data, or make decisions in outlets. That belongs in guards.Bad:
Good:
Outlets rebuild when state changes. Keep builders fast and simple.
When you have complex widget hierarchies, use the inherited item instead of prop drilling:

Common patterns

Card outlet with actions

Next steps

Building outlets guide

Step-by-step outlet creation

Popup hosts

Advanced dialog management

Auto-tracking

Automatic impression tracking

Production example

See real popup host