SupportingPaneScaffold

Functions summary

Unit
@ExperimentalMaterial3AdaptiveApi
@Composable
SupportingPaneScaffold(
    directive: PaneScaffoldDirective,
    scaffoldState: ThreePaneScaffoldState,
    mainPane: @Composable ThreePaneScaffoldPaneScope.() -> Unit,
    supportingPane: @Composable ThreePaneScaffoldPaneScope.() -> Unit,
    modifier: Modifier,
    extraPane: (@Composable ThreePaneScaffoldPaneScope.() -> Unit)?,
    paneExpansionDragHandle: (@Composable ThreePaneScaffoldScope.(PaneExpansionState) -> Unit)?,
    paneExpansionState: PaneExpansionState?
)

A three pane layout that follows the Material guidelines, displaying the provided panes in a canonical supporting pane layout.

Cmn
Unit
@ExperimentalMaterial3AdaptiveApi
@Composable
SupportingPaneScaffold(
    directive: PaneScaffoldDirective,
    value: ThreePaneScaffoldValue,
    mainPane: @Composable ThreePaneScaffoldPaneScope.() -> Unit,
    supportingPane: @Composable ThreePaneScaffoldPaneScope.() -> Unit,
    modifier: Modifier,
    extraPane: (@Composable ThreePaneScaffoldPaneScope.() -> Unit)?,
    paneExpansionDragHandle: (@Composable ThreePaneScaffoldScope.(PaneExpansionState) -> Unit)?,
    paneExpansionState: PaneExpansionState?
)

A three pane layout that follows the Material guidelines, displaying the provided panes in a canonical supporting pane layout.

Cmn

Functions

SupportingPaneScaffold

@ExperimentalMaterial3AdaptiveApi
@Composable
fun SupportingPaneScaffold(
    directive: PaneScaffoldDirective,
    scaffoldState: ThreePaneScaffoldState,
    mainPane: @Composable ThreePaneScaffoldPaneScope.() -> Unit,
    supportingPane: @Composable ThreePaneScaffoldPaneScope.() -> Unit,
    modifier: Modifier = Modifier,
    extraPane: (@Composable ThreePaneScaffoldPaneScope.() -> Unit)? = null,
    paneExpansionDragHandle: (@Composable ThreePaneScaffoldScope.(PaneExpansionState) -> Unit)? = null,
    paneExpansionState: PaneExpansionState? = null
): Unit

A three pane layout that follows the Material guidelines, displaying the provided panes in a canonical supporting pane layout.

This overload takes a ThreePaneScaffoldState describing the current ThreePaneScaffoldValue and any pane transitions or animations in progress.

Here's a basic usage sample, which demonstrates how a layout can change from single pane to dual pane under different window configurations:

import androidx.compose.material3.Scaffold
import androidx.compose.material3.adaptive.layout.AnimatedPane
import androidx.compose.material3.adaptive.layout.PaneExpansionAnchor
import androidx.compose.material3.adaptive.layout.PaneExpansionState
import androidx.compose.material3.adaptive.layout.SupportingPaneScaffold
import androidx.compose.material3.adaptive.layout.rememberPaneExpansionState
import androidx.compose.material3.adaptive.navigation.rememberSupportingPaneScaffoldNavigator
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val coroutineScope = rememberCoroutineScope()
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator<NavItemData>()
val extraItems = listOf("Extra content")
val selectedItem = NavItemData(index = 0, showExtra = true)

SupportingPaneScaffold(
    directive = scaffoldNavigator.scaffoldDirective,
    scaffoldState = scaffoldNavigator.scaffoldState,
    mainPane = {
        AnimatedPane {
            MainPaneContent(
                scaffoldNavigator = scaffoldNavigator,
                hasExtraPane = true,
                coroutineScope = coroutineScope,
            )
        }
    },
    supportingPane = {
        AnimatedPane(modifier = Modifier.preferredWidth(200.dp)) { SupportingPaneContent() }
    },
    extraPane = {
        AnimatedPane {
            ExtraPaneContent(
                extraItems = extraItems,
                selectedItem = selectedItem,
                scaffoldNavigator = scaffoldNavigator,
                coroutineScope = coroutineScope,
            )
        }
    },
    paneExpansionState =
        rememberPaneExpansionState(
            keyProvider = scaffoldNavigator.scaffoldValue,
            anchors = PaneExpansionAnchors,
        ),
    paneExpansionDragHandle = { state -> PaneExpansionDragHandleSample(state) },
)

By default there isn't a drag handle rendered so users aren't able to drag to change the pane split. Providing a drag handle like the above sample shows will enable the functionality. We suggest developers to use the vertical drag handle implementation provided by the Material3 component library here to have default theming/styling support. You can integrate the component as the following sample shows:

import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.material3.LocalMinimumInteractiveComponentSize
import androidx.compose.material3.VerticalDragHandle
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier

val interactionSource = remember { MutableInteractionSource() }
VerticalDragHandle(
    modifier =
        Modifier.paneExpansionDraggable(
            state,
            LocalMinimumInteractiveComponentSize.current,
            interactionSource,
        ),
    interactionSource = interactionSource,
)

Note that if there's no drag handle, you can still modify paneExpansionState directly to apply pane expansion.

Parameters
directive: PaneScaffoldDirective

The top-level directives about how the scaffold should arrange its panes.

scaffoldState: ThreePaneScaffoldState

The current state of the scaffold, containing information about the adapted value of each pane of the scaffold and the transitions/animations in progress.

mainPane: @Composable ThreePaneScaffoldPaneScope.() -> Unit

the main pane of the scaffold, which is supposed to hold the major content of an app, for example, the editing screen of a doc app. See SupportingPaneScaffoldRole.Main. Note that we suggest you to use AnimatedPane as the root layout of panes, which supports default pane behaviors like enter/exit transitions.

supportingPane: @Composable ThreePaneScaffoldPaneScope.() -> Unit

the supporting pane of the scaffold, which is supposed to hold the support content of an app, for example, the comment list of a doc app. See SupportingPaneScaffoldRole.Supporting. Note that we suggest you to use AnimatedPane as the root layout of panes, which supports default pane behaviors like enter/exit transitions.

modifier: Modifier = Modifier

Modifier of the scaffold layout.

extraPane: (@Composable ThreePaneScaffoldPaneScope.() -> Unit)? = null

the extra pane of the scaffold, which is supposed to hold any additional content besides the main and the supporting panes, for example, a styling panel in a doc app. See SupportingPaneScaffoldRole.Extra. Note that we suggest you to use AnimatedPane as the root layout of panes, which supports default pane behaviors like enter/exit transitions.

paneExpansionDragHandle: (@Composable ThreePaneScaffoldScope.(PaneExpansionState) -> Unit)? = null

the pane expansion drag handle to allow users to drag to change pane expansion state, null by default.

paneExpansionState: PaneExpansionState? = null

the state object of pane expansion; when no value is provided but paneExpansionDragHandle is not null, a default implementation will be created for the drag handle to use.

SupportingPaneScaffold

@ExperimentalMaterial3AdaptiveApi
@Composable
fun SupportingPaneScaffold(
    directive: PaneScaffoldDirective,
    value: ThreePaneScaffoldValue,
    mainPane: @Composable ThreePaneScaffoldPaneScope.() -> Unit,
    supportingPane: @Composable ThreePaneScaffoldPaneScope.() -> Unit,
    modifier: Modifier = Modifier,
    extraPane: (@Composable ThreePaneScaffoldPaneScope.() -> Unit)? = null,
    paneExpansionDragHandle: (@Composable ThreePaneScaffoldScope.(PaneExpansionState) -> Unit)? = null,
    paneExpansionState: PaneExpansionState? = null
): Unit

A three pane layout that follows the Material guidelines, displaying the provided panes in a canonical supporting pane layout.

This overload takes a ThreePaneScaffoldValue describing the adapted value of each pane within the scaffold.

Here's a basic usage sample, which demonstrates how a layout can change from single pane to dual pane under different window configurations:

import androidx.compose.material3.Scaffold
import androidx.compose.material3.adaptive.layout.AnimatedPane
import androidx.compose.material3.adaptive.layout.PaneExpansionAnchor
import androidx.compose.material3.adaptive.layout.PaneExpansionState
import androidx.compose.material3.adaptive.layout.SupportingPaneScaffold
import androidx.compose.material3.adaptive.layout.rememberPaneExpansionState
import androidx.compose.material3.adaptive.navigation.rememberSupportingPaneScaffoldNavigator
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val coroutineScope = rememberCoroutineScope()
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator<NavItemData>()
val extraItems = listOf("Extra content")
val selectedItem = NavItemData(index = 0, showExtra = true)

SupportingPaneScaffold(
    directive = scaffoldNavigator.scaffoldDirective,
    scaffoldState = scaffoldNavigator.scaffoldState,
    mainPane = {
        AnimatedPane {
            MainPaneContent(
                scaffoldNavigator = scaffoldNavigator,
                hasExtraPane = true,
                coroutineScope = coroutineScope,
            )
        }
    },
    supportingPane = {
        AnimatedPane(modifier = Modifier.preferredWidth(200.dp)) { SupportingPaneContent() }
    },
    extraPane = {
        AnimatedPane {
            ExtraPaneContent(
                extraItems = extraItems,
                selectedItem = selectedItem,
                scaffoldNavigator = scaffoldNavigator,
                coroutineScope = coroutineScope,
            )
        }
    },
    paneExpansionState =
        rememberPaneExpansionState(
            keyProvider = scaffoldNavigator.scaffoldValue,
            anchors = PaneExpansionAnchors,
        ),
    paneExpansionDragHandle = { state -> PaneExpansionDragHandleSample(state) },
)

By default there isn't a drag handle rendered so users aren't able to drag to change the pane split. Providing a drag handle like the above sample shows will enable the functionality. We suggest developers to use the vertical drag handle implementation provided by the Material3 component library here to have default theming/styling support. You can integrate the component as the following sample shows:

import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.material3.LocalMinimumInteractiveComponentSize
import androidx.compose.material3.VerticalDragHandle
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier

val interactionSource = remember { MutableInteractionSource() }
VerticalDragHandle(
    modifier =
        Modifier.paneExpansionDraggable(
            state,
            LocalMinimumInteractiveComponentSize.current,
            interactionSource,
        ),
    interactionSource = interactionSource,
)

Note that if there's no drag handle, you can still modify paneExpansionState directly to apply pane expansion.

Parameters
directive: PaneScaffoldDirective

The top-level directives about how the scaffold should arrange its panes.

value: ThreePaneScaffoldValue

The current adapted value of the scaffold, which indicates how each pane of the scaffold is adapted.

mainPane: @Composable ThreePaneScaffoldPaneScope.() -> Unit

the main pane of the scaffold, which is supposed to hold the major content of an app, for example, the editing screen of a doc app. See SupportingPaneScaffoldRole.Main. Note that we suggest you to use AnimatedPane as the root layout of panes, which supports default pane behaviors like enter/exit transitions.

supportingPane: @Composable ThreePaneScaffoldPaneScope.() -> Unit

the supporting pane of the scaffold, which is supposed to hold the support content of an app, for example, the comment list of a doc app. See SupportingPaneScaffoldRole.Supporting. Note that we suggest you to use AnimatedPane as the root layout of panes, which supports default pane behaviors like enter/exit transitions.

modifier: Modifier = Modifier

Modifier of the scaffold layout.

extraPane: (@Composable ThreePaneScaffoldPaneScope.() -> Unit)? = null

the extra pane of the scaffold, which is supposed to hold any additional content besides the main and the supporting panes, for example, a styling panel in a doc app. See SupportingPaneScaffoldRole.Extra. Note that we suggest you to use AnimatedPane as the root layout of panes, which supports default pane behaviors like enter/exit transitions.

paneExpansionDragHandle: (@Composable ThreePaneScaffoldScope.(PaneExpansionState) -> Unit)? = null

the pane expansion drag handle to allow users to drag to change pane expansion state, null by default.

paneExpansionState: PaneExpansionState? = null

the state object of pane expansion; when no value is provided but paneExpansionDragHandle is not null, a default implementation will be created for the drag handle to use.