What are surface observers?
Surface observers are widgets that watch a specific surface slot and react to active item changes. They provide a simple, reactive way to build custom UI that responds to Presentum state without the overhead of popup-specific features. ThePresentumActiveSurfaceItemObserverMixin handles all the complexity of:
- Subscribing to surface state - Automatically observes the correct slot
- Tracking active item changes - Detects when items activate or deactivate
- Managing lifecycle - Cleans up observers when widget disposes
- Handling initial state - Optionally processes the initial active item
Basic usage
Here’s a minimal surface observer:Required implementations
You must implement two members:Understanding state transitions
TheonActiveItemChanged callback receives both current and previous items, enabling you to handle all state transitions:
Item activation (previous: null, current: Item)
Item activation (previous: null, current: Item)
A new item became active on an empty surface:
Item deactivation (previous: Item, current: null)
Item deactivation (previous: Item, current: null)
The active item became inactive:
Item replacement (previous: Item1, current: Item2)
Item replacement (previous: Item1, current: Item2)
The active item was replaced by another:
Production example: Update snackbar
This observer shows a snackbar when app updates are available:This observer doesn’t need popup-specific features like duplicate detection or conflict resolution - it simply shows/hides a snackbar based on state.
When NOT to use surface observers
Examples of incorrect usage:- Triggering API calls when surface state changes
- Starting/stopping timers based on state
- Logging or analytics
- BLoC/Provider integration
Optional configuration
Handle initial state
Control whether to process the initial active item ininitState:
false if you only want to react to changes, not the initial state.
Access current active item
You can access the current active item at any time:Access the observer
For advanced use cases, you can access the underlying observer:When to use surface observers
UsePresentumActiveSurfaceItemObserverMixin only when you need to render UI based on surface state:
Snackbars & Banners
Show/hide snackbars, banners, toasts, or badges based on surface state
Visual Overlays
Display non-modal overlays or floating UI elements
UI Animations
Trigger widget animations tied to surface state changes
Dynamic Widgets
Render or update widgets based on active items
build() method returns actual UI or your widget manages visible elements.
Best practices
Use pattern matching for clarity
Use pattern matching for clarity
Leverage Dart 3 pattern matching to make state transitions explicit:
Clean up resources in dispose
Clean up resources in dispose
Always cancel timers, subscriptions, or animations:
Handle all transition cases
Handle all transition cases
Consider all possible state transitions:
Keep onActiveItemChanged lightweight
Keep onActiveItemChanged lightweight
Avoid heavy computation in the callback. Use
scheduleMicrotask or Future for async work:Next steps
Popup hosts
Learn about popup surface management with dialogs
Surfaces
Understand surfaces and slots
Production examples
Explore the complete example app