Skip to main content
The TecNM Control Escolar app uses Jetpack Compose to build its UI with reusable, composable components. This page documents the shared components used across multiple screens.

BottomBar Component

The BottomBar component provides the main navigation interface using Material 3’s NavigationBar.
BottmBar.kt
package com.example.appcontrolescolar.ui.components

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.AccountCircle
import androidx.compose.material.icons.outlined.Home
import androidx.compose.material.icons.outlined.LocationOn
import androidx.compose.material.icons.outlined.DateRange
import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.navigation.NavHostController
import androidx.navigation.compose.currentBackStackEntryAsState
import com.example.appcontrolescolar.navigation.AppScreens

@Composable
fun BottomBar(navController: NavHostController) {
    val items = listOf(
        AppScreens.Home,
        AppScreens.Schedule,
        AppScreens.Map,
        AppScreens.Profile
    )

    val labels = listOf("Inicio", "Horario", "Mapa", "Perfil")
    val icons = listOf(
        Icons.Outlined.Home,
        Icons.Outlined.DateRange,
        Icons.Outlined.LocationOn,
        Icons.Outlined.AccountCircle
    )

    val navBackStackEntry = navController.currentBackStackEntryAsState()
    val currentRoute = navBackStackEntry.value?.destination?.route

    NavigationBar {
        items.forEachIndexed { index, screen ->
            NavigationBarItem(
                selected = currentRoute == screen.route,
                onClick = {
                    navController.navigate(screen.route) {
                        popUpTo(navController.graph.startDestinationId)
                        launchSingleTop = true
                    }
                },
                icon = {
                    Icon(
                        imageVector = icons[index],
                        contentDescription = labels[index]
                    )
                },
                label = {
                    Text(labels[index])
                }
            )
        }
    }
}

Component Structure

The BottomBar consists of four main elements:
1

Items Definition

Defines the list of navigation destinations using AppScreens objects
2

Labels and Icons

Parallel lists for Spanish labels and Material Icons
3

Route Detection

Observes the current navigation route to highlight the active item
4

Navigation Items

Renders each NavigationBarItem with selection state and click handling
IndexScreenLabelIconDescription
0HomeInicioHomeReturns to the home screen
1ScheduleHorarioDateRangeShows the class schedule
2MapMapaLocationOnDisplays campus map
3ProfilePerfilAccountCircleShows student profile

Props

navController
NavHostController
required
The navigation controller used to handle screen transitions and observe the current route

Key Features

Active State Highlighting

The current screen is automatically highlighted based on the navigation route

Material 3 Design

Uses Material Design 3 NavigationBar for modern, adaptive styling

Outlined Icons

Uses outlined icon variants for a clean, professional look

Smart Navigation

Prevents back stack buildup with popUpTo and launchSingleTop

Component Composition Patterns

The app follows modern Compose patterns for building UI:

Stateless Components

Components like BottomBar are stateless - they receive all necessary data through parameters:
@Composable
fun BottomBar(navController: NavHostController) {
    // Component logic uses navController but doesn't own it
}

State Hoisting

State is hoisted to the appropriate level in the composition hierarchy:
@Composable
fun AppNavigation() {
    // NavController is created here and passed down
    val navController = rememberNavController()
    
    Scaffold(
        bottomBar = {
            BottomBar(navController) // State passed down
        }
    ) { /* ... */ }
}

Composition over Inheritance

Compose favors composition over inheritance. Components are built by composing smaller functions:
NavigationBar {  // Container
    items.forEachIndexed { index, screen ->
        NavigationBarItem(  // Child component
            icon = { Icon(...) },  // Nested composable
            label = { Text(...) }  // Nested composable
        )
    }
}

Material 3 Components Used

The app leverages Material 3 components from androidx.compose.material3:
Vector icon component that uses Material Icons from androidx.compose.material.icons.
Text component that automatically uses theme typography styles.
Layout structure used in AppNavigation to organize the bottom bar and content.

Icon Resources

The app uses Material Icons Extended for a comprehensive icon set:
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.*
Ensure the Material Icons Extended dependency is added to build.gradle:
implementation("androidx.compose.material:material-icons-extended")

Icon Variants

The app uses outlined icon variants for consistency:
  • Icons.Outlined.Home
  • Icons.Outlined.DateRange
  • Icons.Outlined.LocationOn
  • Icons.Outlined.AccountCircle

Screen Components

Individual screens are implemented as top-level composables in the ui/screens/ package:
@Composable
fun HomeScreen() {
    // Screen implementation
}

@Composable
fun ScheduleScreen() {
    // Screen implementation
}

@Composable
fun MapScreen() {
    // Screen implementation
}

@Composable
fun ProfileScreen() {
    // Screen implementation
}

Screen Implementation

Each screen is a self-contained composable that uses FakeData to display content. Screens are stateless and will receive data through ViewModels in future updates.

Best Practices

Single Responsibility

Each component has a clear, single purpose

Reusability

Components are designed to be reusable across screens

Accessibility

All interactive elements include content descriptions

Theme Consistency

Components use theme colors and typography

Future Components

Planned reusable components for future development:
  • ClassCard: Card component for displaying class sessions
  • BuildingCard: Card component for campus buildings
  • ProfileInfoRow: Row component for profile information
  • QRScanner: Camera composable for QR code scanning
  • LoadingIndicator: Consistent loading state component
  • ErrorView: Standard error state display