NutrientToolbarScaffold

fun NutrientToolbarScaffold(coordinator: ToolbarCoordinator, modifier: Modifier = Modifier, contextualToolbarSize: Dp = NutrientContextualToolbarDefaults.toolbarSize(LocalContext.current), verticalMargin: Dp = NutrientContextualToolbarDefaults.VerticalMargin, horizontalMargin: Dp = NutrientContextualToolbarDefaults.HorizontalMargin, topWindowInset: Dp = 0.dp, bottomWindowInset: Dp = 0.dp, leftWindowInset: Dp = 0.dp, rightWindowInset: Dp = 0.dp, dragTargetColor: Color = NutrientContextualToolbarDefaults.dragTargetColor(LocalContext.current), dragListener: NutrientContextualToolbarDragListener? = null, onEffectivePositionChanged: (ToolbarPosition?) -> Unit? = null, mainToolbar: @Composable () -> Unit? = null, contextualToolbar: @Composable ContextualToolbarSlotScope.() -> Unit? = null, content: @Composable () -> Unit)

Single-tree placement scaffold for the Nutrient toolbars — the Compose replacement for the View ToolbarCoordinatorLayout (Phase 4 §1, closes P0-4's overlay z-order bug class).

Owns:

  • Placement: the main toolbar in the top slot; the contextual bar docked Top, Start, or End per the coordinator's ToolbarCoordinator.contextualToolbar state. Start/End are logical and RTL-safe (Compose alignment resolves them through LocalLayoutDirection).

  • Fit correction: a side dock the window can't fit vertically renders in the top slot instead (the View forcedPosition contract). Render-only — the coordinator state and the persisted dock preference keep the user's choice, so the side dock returns when the window grows again.

  • Drag chrome: while the bar's handle is dragged, the possible dock slots paint as placeholders with proximity-weighted alpha, fading over NutrientContextualToolbarDefaults.DropZoneFadeMillis (the View dispatchDraw chrome). The bar itself resolves the drop and re-docks; the scaffold only paints.

  • Content inset: LocalToolbarContentInset tells the content slot how far it must stay below the top slot; the scaffold never pads content itself (the document view decides how to consume the inset, mirroring the View contract).

Parameters

mainToolbar

The main toolbar slot, or null when the host renders no main toolbar. Its visibility follows ToolbarCoordinator.frame.

contextualToolbar

The contextual toolbar slot, or null. The slot receives the effective dock position (post fit-correction) so the bar can pick its orientation, and the scaffold's drag listener, which must be passed to NutrientContextualToolbar so the drop-zone chrome tracks the drag.

dragListener

Optional host listener notified of handle drags (analytics); the scaffold forwards every event.

onEffectivePositionChanged

Optional host hook reporting where the contextual bar actually renders (null while none is shown). Differs from the coordinator state exactly when the fit correction forces a side dock to ToolbarPosition.Top — hosts that answer geometry questions outside the composition (content insets, toolbar-on-top policies) must key them on this rendered dock, not the requested one.

topWindowInset

The status-bar strip above the top slot (the View windowInsets.top). The scaffold owns this placement inset: a top-docked contextual bar sits below it, the content inset and vertical-fit math account for it, and the top drop-zone placeholder extends up through it. The bars themselves only handle their own background painting (the main toolbar additionally self-insets via its frame's ToolbarInsets, which is why the scaffold does not pad the main slot).

leftWindowInset

The physical-left window inset (the View windowInsets.left — a landscape side nav bar or display cutout). Contextual slots and drop zones clear it; the main slot stays unpadded (its frame ToolbarInsets are the main toolbar's own channel).

rightWindowInset

The physical-right counterpart of leftWindowInset.

content

The document content underneath the toolbars.