# Docked and full-screen search

> Two ways to show search results: in a dropdown under the field or on a full-screen surface.

- Category: Navigation
- API status: Expressive
- Compose APIs: `DockedSearchBar`, `SearchBar`, `ExpandedFullScreenSearchBar`, `SearchBarDefaults.InputField`
- Interactive page: https://m3e.ljzapps.app/#components/full-screen-search

## When to use

Use the docked search bar on large windows, where a dropdown under the field is easy to reach. Use the full-screen expanded search on compact windows, where it gives the results the whole screen.

Both share the same input field. Choose by window size class.

## Examples

### Docked

Results appear below the field.

```kotlin
var query by rememberSaveable { mutableStateOf("") }
var expanded by rememberSaveable { mutableStateOf(false) }
val cities = listOf("Berlin", "Bergen", "Barcelona", "Boston", "Brussels")

Box(Modifier.fillMaxWidth().height(320.dp), contentAlignment = Alignment.TopCenter) {
    DockedSearchBar(
        inputField = {
            SearchBarDefaults.InputField(
                query = query,
                onQueryChange = { query = it },
                onSearch = { expanded = false },
                expanded = expanded,
                onExpandedChange = { expanded = it },
                placeholder = { Text("Search cities") },
                leadingIcon = { Icon(Icons.Rounded.Search, contentDescription = null) },
            )
        },
        expanded = expanded,
        onExpandedChange = { expanded = it },
    ) {
        cities.filter { it.contains(query, ignoreCase = true) }.forEach { city ->
            ListItem(headlineContent = { Text(city) })
        }
    }
}
```

### Full screen

The expanded bar covers the window.

```kotlin
val searchBarState = rememberSearchBarState()
val textFieldState = rememberTextFieldState()
val scope = rememberCoroutineScope()
val inputField = @Composable {
    SearchBarDefaults.InputField(
        textFieldState = textFieldState,
        searchBarState = searchBarState,
        onSearch = { scope.launch { searchBarState.animateToCollapsed() } },
        placeholder = { Text("Search the library") },
        leadingIcon = { Icon(Icons.Rounded.Search, contentDescription = null) },
    )
}

Box(Modifier.fillMaxWidth().height(120.dp), contentAlignment = Alignment.TopCenter) {
    SearchBar(state = searchBarState, inputField = inputField)
    ExpandedFullScreenSearchBar(state = searchBarState, inputField = inputField) {
        listOf("Albums", "Artists", "Playlists").forEach { label ->
            ListItem(headlineContent = { Text(label) })
        }
    }
}
```

## Parameters

| Name | Type | Default | Description |
|---|---|---|---|
| `state` | `SearchBarState` |  | Full screen variant. Animates between Collapsed and Expanded. |
| `expanded / onExpandedChange` | `Boolean / (Boolean) -> Unit` |  | Docked variant state. |
| `inputField` | `@Composable () -> Unit` |  | SearchBarDefaults.InputField. |
| `content` | `@Composable ColumnScope.() -> Unit` |  | Suggestions or results. |

## Guidelines

Do:
- Show recent searches.
- Keep the field visible while results are shown.

Don't:
- Do not use the docked variant on compact windows.
- Do not search on every keystroke without a delay.

## Accessibility

- Escape collapses the expanded bar. Announce the number of results.

## Related components

- [Search](https://m3e.ljzapps.app/docs/components/search.md)
- [Top app bar](https://m3e.ljzapps.app/docs/components/top-app-bar.md)
- [Text field](https://m3e.ljzapps.app/docs/components/text-field.md)
