# Bottom sheet

> A surface anchored to the bottom edge for secondary content and actions.

- Category: Containment
- API status: Stable
- Compose APIs: `ModalBottomSheet`, `BottomSheetScaffold`, `rememberModalBottomSheetState`, `BottomSheetDefaults`
- Interactive page: https://m3e.ljzapps.app/#components/bottom-sheet

## When to use

A modal bottom sheet blocks the screen behind a scrim and is dismissed by swiping down, tapping the scrim or pressing Escape. A standard bottom sheet lives beside the content and stays visible while the user keeps working.

On wide windows prefer a side sheet or a dialog, because a full width bottom sheet reads poorly.

## Playground

The interactive page has a playground with live property controls for this component and generated code.

## Examples

### Modal

Open it and drag or tap outside to close.

```kotlin
var open by rememberSaveable { mutableStateOf(false) }
val sheetState = rememberModalBottomSheetState()

Button(onClick = { open = true }) { Text("Share options") }

if (open) {
    ModalBottomSheet(
        onDismissRequest = { open = false },
        sheetState = sheetState,
        dragHandle = { BottomSheetDefaults.DragHandle() },
    ) {
        Column(Modifier.padding(bottom = 32.dp)) {
            listOf("Copy link", "Send as message", "Save to files").forEach { label ->
                ListItem(headlineContent = { Text(label) })
            }
        }
    }
}
```

### Standard

Drag the handle up. The content stays interactive.

```kotlin
Box(Modifier.fillMaxWidth().height(380.dp)) {
    BottomSheetScaffold(
        sheetPeekHeight = 96.dp,
        sheetContent = {
            Column(Modifier.fillMaxWidth().padding(bottom = 24.dp)) {
                Text("Now playing", Modifier.padding(horizontal = 24.dp, vertical = 8.dp))
                listOf("Queue", "Lyrics", "Related").forEach { label ->
                    ListItem(headlineContent = { Text(label) })
                }
            }
        },
    ) {
        Box(Modifier.fillMaxWidth().padding(24.dp)) { Text("Content behind the sheet") }
    }
}
```

## Parameters

| Name | Type | Default | Description |
|---|---|---|---|
| `onDismissRequest` | `() -> Unit` |  | Called when the sheet should close. |
| `sheetState` | `SheetState` | `rememberModalBottomSheetState()` | Controls expansion. skipPartiallyExpanded jumps straight to full height. |
| `dragHandle` | `@Composable (() -> Unit)?` | `DragHandle()` | Set to null to hide the handle. |
| `sheetMaxWidth` | `Dp` | `BottomSheetDefaults.SheetMaxWidth` | Limits the width on large windows. |

## Guidelines

Do:
- Use for short lists of actions or supporting detail.
- Provide a visible close path.

Don't:
- Do not place primary content only in a sheet.
- Do not stack sheets.

## Accessibility

- The drag handle has actions for expand and collapse, so the sheet works without gestures.
- A modal sheet traps focus and returns it to the trigger on close.

## Related components

- [Dialog](https://m3e.ljzapps.app/docs/components/dialog.md)
- [List](https://m3e.ljzapps.app/docs/components/list.md)
- [Floating toolbar](https://m3e.ljzapps.app/docs/components/floating-toolbar.md)
