El cambio más visible al adaptar una app para pantallas grandes es la navegación. La regla de Material3 es clara: la navegación va donde hay espacio, y en el eje donde no compite con el contenido.

# Compact (< 600dp de ancho) — teléfono portrait:
# → BottomNavigationBar: navegación en la parte inferior
# → Máximo 5 destinos, solo íconos o ícono + etiqueta corta

# Medium (600-840dp) — tablet portrait, teléfono landscape:
# → NavigationRail: barra lateral estrecha izquierda
# → Ícono + etiqueta, puede tener FAB encima

# Expanded (> 840dp) — tablet landscape, ChromeOS ventana grande:
# → NavigationDrawer permanente: panel lateral fijo con texto completo
# → El contenido se desplaza a la derecha del drawer

BottomNavigationBar — Compact

@Composable
fun NavegacionCompact(
    destinoActual: Destino,
    onNavegar: (Destino) -> Unit
) {
    NavigationBar {
        destinos.forEach { destino ->
            NavigationBarItem(
                selected = destinoActual == destino,
                onClick = { onNavegar(destino) },
                icon = { Icon(destino.icono, contentDescription = destino.label) },
                label = { Text(destino.label) }
            )
        }
    }
}
@Composable
fun NavegacionMedium(
    destinoActual: Destino,
    onNavegar: (Destino) -> Unit,
    contenido: @Composable () -> Unit
) {
    Row(modifier = Modifier.fillMaxSize()) {
        NavigationRail(
            header = {
                // FAB opcional en la parte superior del rail
                FloatingActionButton(onClick = { /* acción principal */ }) {
                    Icon(Icons.Default.Add, "Nuevo")
                }
            }
        ) {
            // Spacer para empujar los items al centro verticalmente
            Spacer(modifier = Modifier.weight(1f))
            destinos.forEach { destino ->
                NavigationRailItem(
                    selected = destinoActual == destino,
                    onClick = { onNavegar(destino) },
                    icon = { Icon(destino.icono, contentDescription = destino.label) },
                    label = { Text(destino.label) }
                )
            }
            Spacer(modifier = Modifier.weight(1f))
        }
        // El contenido ocupa el espacio restante
        Box(modifier = Modifier.weight(1f)) {
            contenido()
        }
    }
}
@Composable
fun NavegacionExpanded(
    destinoActual: Destino,
    onNavegar: (Destino) -> Unit,
    contenido: @Composable () -> Unit
) {
    PermanentNavigationDrawer(
        drawerContent = {
            PermanentDrawerSheet(modifier = Modifier.width(240.dp)) {
                // Header del drawer — logo o nombre de la app
                Text(
                    "Mi App",
                    style = MaterialTheme.typography.titleLarge,
                    modifier = Modifier.padding(16.dp)
                )
                Spacer(modifier = Modifier.height(8.dp))
                destinos.forEach { destino ->
                    NavigationDrawerItem(
                        icon = { Icon(destino.icono, contentDescription = null) },
                        label = { Text(destino.label) },
                        selected = destinoActual == destino,
                        onClick = { onNavegar(destino) },
                        modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
                    )
                }
            }
        }
    ) {
        contenido()
    }
}

AdaptiveNavigationSuite — el todo en uno

Material3 incluye NavigationSuiteScaffold que elige automáticamente el tipo de navegación según el WindowSizeClass. En la mayoría de los casos no necesitás el código manual de arriba:

// implementation("androidx.compose.material3.adaptive:adaptive-navigation-suite:1.0.0")

@Composable
fun AppConNavegacionAdaptativa() {
    var destinoActual by remember { mutableStateOf(Destino.INICIO) }

    NavigationSuiteScaffold(
        navigationSuiteItems = {
            destinos.forEach { destino ->
                item(
                    icon = { Icon(destino.icono, contentDescription = destino.label) },
                    label = { Text(destino.label) },
                    selected = destinoActual == destino,
                    onClick = { destinoActual = destino }
                )
            }
        }
    ) {
        // Contenido de la pantalla activa
        when (destinoActual) {
            Destino.INICIO -> PantallaInicio()
            Destino.BUSCAR -> PantallaBuscar()
            Destino.PERFIL -> PantallaPerfil()
        }
    }
}
// NavigationSuiteScaffold elige automáticamente:
// → NavigationBar en Compact
// → NavigationRail en Medium
// → NavigationDrawer en Expanded
// Sin ningún when() manual

Adaptar el contenido — más allá de la navegación

// Adaptar la cuadrícula según el ancho disponible:
@Composable
fun GridAdaptativa(productos: List<Producto>) {
    val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
    val columnas = when (windowSizeClass.windowWidthSizeClass) {
        WindowWidthSizeClass.COMPACT  -> 2
        WindowWidthSizeClass.MEDIUM   -> 3
        else                          -> 4
    }

    LazyVerticalGrid(
        columns = GridCells.Fixed(columnas),
        contentPadding = PaddingValues(16.dp),
        horizontalArrangement = Arrangement.spacedBy(12.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        items(productos, key = { it.id }) { producto ->
            ProductoCard(producto)
        }
    }
}

// Adaptar el padding y márgenes:
@Composable
fun ContenidoConMargenesAdaptativos(content: @Composable () -> Unit) {
    val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
    val padding = when (windowSizeClass.windowWidthSizeClass) {
        WindowWidthSizeClass.COMPACT  -> PaddingValues(horizontal = 16.dp)
        WindowWidthSizeClass.MEDIUM   -> PaddingValues(horizontal = 24.dp)
        else                          -> PaddingValues(horizontal = 32.dp)
    }
    Box(modifier = Modifier.padding(padding)) { content() }
}

Orientación y cambios de configuración

// AndroidManifest.xml — permitir todas las orientaciones en tablets:
// Por default, muchas apps fuerzan portrait
// <activity
//     android:screenOrientation="unspecified"  ← dejar que el sistema decida
//     android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout">

// En Compose: el estado sobrevive a rotaciones si está en el ViewModel
// No hacer nada especial — Compose recompone con el nuevo WindowSizeClass automáticamente

// Lo que SÍ hay que verificar manualmente:
// → Que no haya texto cortado en landscape
// → Que los diálogos no sean más grandes que la pantalla en portrait
// → Que los BottomSheets no bloqueen contenido importante en landscape