ModalWideNavigationRail

Material design modal wide navigation rail.

Common
@Composable
fun ModalWideNavigationRail(
    modifier: Modifier = Modifier,
    state: WideNavigationRailState = rememberWideNavigationRailState(),
    hideOnCollapse: Boolean = false,
    collapsedShape: Shape = WideNavigationRailDefaults.modalCollapsedShape,
    expandedShape: Shape = WideNavigationRailDefaults.modalExpandedShape,
    colors: WideNavigationRailColors = WideNavigationRailDefaults.colors(),
    header: @Composable (() -> Unit)? = null,
    expandedHeaderTopPadding: Dp = 0.dp,
    windowInsets: WindowInsets = WideNavigationRailDefaults.windowInsets,
    arrangement: Arrangement.Vertical = WideNavigationRailDefaults.arrangement,
    expandedProperties: ModalWideNavigationRailProperties =
        WideNavigationRailDefaults.ModalExpandedProperties,
    contentPadding: PaddingValues = WideNavigationRailDefaults.ContentPadding,
    content: @Composable () -> Unit,
)

Parameters

modifier the Modifier to be applied to this wide navigation rail
state the WideNavigationRailState of this wide navigation rail
hideOnCollapse whether this wide navigation rail should slide offscreen when it collapses and be hidden, or stay on screen as a collapsed wide navigation rail (default)
collapsedShape the shape of this wide navigation rail's container when it's collapsed
expandedShape the shape of this wide navigation rail's container when it's expanded
colors WideNavigationRailColors that will be used to resolve the colors used for this wide navigation rail. See WideNavigationRailDefaults.colors
header optional header that may hold a FloatingActionButton or a logo
expandedHeaderTopPadding the padding to be applied to the top of the rail. It's usually needed in order to align the content of the rail between the collapsed and expanded animation
windowInsets a window insets of the wide navigation rail
arrangement the Arrangement.Vertical of this wide navigation rail
expandedProperties ModalWideNavigationRailProperties for further customization of the expanded modal wide navigation rail's window behavior
contentPadding the spacing values to apply internally between the container and the content
content the content of this modal wide navigation rail, usually WideNavigationRailItems
Common
Deprecated Deprecated in favor of function with contentPadding parameter
@Composable
fun ModalWideNavigationRail(
    modifier: Modifier = Modifier,
    state: WideNavigationRailState = rememberWideNavigationRailState(),
    hideOnCollapse: Boolean = false,
    collapsedShape: Shape = WideNavigationRailDefaults.modalCollapsedShape,
    expandedShape: Shape = WideNavigationRailDefaults.modalExpandedShape,
    colors: WideNavigationRailColors = WideNavigationRailDefaults.colors(),
    header: @Composable (() -> Unit)? = null,
    expandedHeaderTopPadding: Dp = 0.dp,
    windowInsets: WindowInsets = WideNavigationRailDefaults.windowInsets,
    arrangement: Arrangement.Vertical = WideNavigationRailDefaults.arrangement,
    expandedProperties: ModalWideNavigationRailProperties =
        WideNavigationRailDefaults.ModalExpandedProperties,
    content: @Composable () -> Unit,
)

Parameters

modifier the Modifier to be applied to this wide navigation rail
state the WideNavigationRailState of this wide navigation rail
hideOnCollapse whether this wide navigation rail should slide offscreen when it collapses and be hidden, or stay on screen as a collapsed wide navigation rail (default)
collapsedShape the shape of this wide navigation rail's container when it's collapsed
expandedShape the shape of this wide navigation rail's container when it's expanded
colors WideNavigationRailColors that will be used to resolve the colors used for this wide navigation rail. See WideNavigationRailDefaults.colors
header optional header that may hold a FloatingActionButton or a logo
expandedHeaderTopPadding the padding to be applied to the top of the rail. It's usually needed in order to align the content of the rail between the collapsed and expanded animation
windowInsets a window insets of the wide navigation rail
arrangement the Arrangement.Vertical of this wide navigation rail
expandedProperties ModalWideNavigationRailProperties for further customization of the expanded modal wide navigation rail's window behavior
content the content of this modal wide navigation rail, usually WideNavigationRailItems

Code Examples

DismissibleModalWideNavigationRailSample

@Preview
@Composable
fun DismissibleModalWideNavigationRailSample() {
    var selectedItem by remember { mutableIntStateOf(0) }
    val items = listOf("Home", "Search", "Settings")
    val selectedIcons = listOf(Icons.Filled.Home, Icons.Filled.Favorite, Icons.Filled.Star)
    val unselectedIcons =
        listOf(Icons.Outlined.Home, Icons.Outlined.FavoriteBorder, Icons.Outlined.StarBorder)
    val state = rememberWideNavigationRailState()
    val scope = rememberCoroutineScope()
    Row(Modifier.fillMaxSize()) {
        ModalWideNavigationRail(state = state, hideOnCollapse = true) {
            items.forEachIndexed { index, item ->
                WideNavigationRailItem(
                    railExpanded = true,
                    icon = {
                        Icon(
                            if (selectedItem == index) selectedIcons[index]
                            else unselectedIcons[index],
                            contentDescription = null,
                        )
                    },
                    label = { Text(item) },
                    selected = selectedItem == index,
                    onClick = {
                        selectedItem = index
                        scope.launch { state.collapse() }
                    },
                )
            }
        }
        Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
            val currentPage = items.get(selectedItem)
            Button(onClick = { scope.launch { state.expand() } }, Modifier.padding(32.dp)) {
                Text(text = "$currentPage Page\nOpen modal rail", textAlign = TextAlign.Center)
            }
        }
    }
}

ModalWideNavigationRailSample

@OptIn(ExperimentalMaterial3Api::class)
@Preview
@Composable
fun ModalWideNavigationRailSample() {
    var selectedItem by remember { mutableIntStateOf(0) }
    val items = listOf("Home", "Search", "Settings")
    val selectedIcons = listOf(Icons.Filled.Home, Icons.Filled.Favorite, Icons.Filled.Star)
    val unselectedIcons =
        listOf(Icons.Outlined.Home, Icons.Outlined.FavoriteBorder, Icons.Outlined.StarBorder)
    val state = rememberWideNavigationRailState()
    val scope = rememberCoroutineScope()
    val headerDescription =
        if (state.targetValue == WideNavigationRailValue.Expanded) {
            "Collapse rail"
        } else {
            "Expand rail"
        }
    Row(Modifier.fillMaxWidth()) {
        ModalWideNavigationRail(
            state = state,
            // Note: the value of expandedHeaderTopPadding depends on the layout of your screen in
            // order to achieve the best alignment.
            expandedHeaderTopPadding = 64.dp,
            header = {
                // Header icon button should have a tooltip.
                TooltipBox(
                    positionProvider =
                        TooltipDefaults.rememberTooltipPositionProvider(
                            TooltipAnchorPosition.Above
                        ),
                    tooltip = { PlainTooltip { Text(headerDescription) } },
                    state = rememberTooltipState(),
                ) {
                    IconButton(
                        modifier =
                            Modifier.padding(start = 24.dp).semantics {
                                // The button must announce the expanded or collapsed state of the
                                // rail for accessibility.
                                stateDescription =
                                    if (state.currentValue == WideNavigationRailValue.Expanded) {
                                        "Expanded"
                                    } else {
                                        "Collapsed"
                                    }
                            },
                        onClick = {
                            scope.launch {
                                if (state.targetValue == WideNavigationRailValue.Expanded)
                                    state.collapse()
                                else state.expand()
                            }
                        },
                    ) {
                        if (state.targetValue == WideNavigationRailValue.Expanded) {
                            Icon(Icons.AutoMirrored.Filled.MenuOpen, headerDescription)
                        } else {
                            Icon(Icons.Filled.Menu, headerDescription)
                        }
                    }
                }
            },
        ) {
            items.forEachIndexed { index, item ->
                WideNavigationRailItem(
                    railExpanded = state.targetValue == WideNavigationRailValue.Expanded,
                    icon = {
                        Icon(
                            if (selectedItem == index) selectedIcons[index]
                            else unselectedIcons[index],
                            contentDescription = item,
                        )
                    },
                    label = { Text(item) },
                    selected = selectedItem == index,
                    onClick = { selectedItem = index },
                )
            }
        }
        val textString =
            if (state.currentValue == WideNavigationRailValue.Expanded) {
                "Expanded"
            } else {
                "Collapsed"
            }
        Column {
            Text(modifier = Modifier.padding(16.dp), text = "The rail is $textString.")
            Text(
                modifier = Modifier.padding(16.dp),
                text =
                    "Note: This demo is best shown in portrait mode, as landscape mode" +
                        " may result in a compact height in certain devices. For any" +
                        " compact screen dimensions, use a Navigation Bar instead.",
            )
        }
    }
}