or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-components.mdicons.mdindex.mdinput-components.mdios-integration.mdnavigation.mdtheming.md

navigation.mddocs/

0

# Navigation Components

1

2

Material Design navigation components that integrate seamlessly with iOS navigation patterns and UIKit, providing consistent Material styling while respecting iOS platform conventions.

3

4

## Capabilities

5

6

### Scaffold

7

8

Material design layout structure that provides slots for common screen elements with iOS-specific adaptations.

9

10

```kotlin { .api }

11

/**

12

* Material Design layout structure providing a framework for common Material Design components

13

* Integrates with iOS navigation patterns and safe area handling

14

* @param modifier Modifier to be applied to this Scaffold

15

* @param scaffoldState State of this scaffold containing the DrawerState and SnackbarHostState

16

* @param topBar Top app bar of the screen, typically a TopAppBar

17

* @param bottomBar Bottom bar of the screen, typically a BottomNavigation

18

* @param snackbarHost Component to host Snackbars

19

* @param floatingActionButton Main action button, typically a FloatingActionButton

20

* @param floatingActionButtonPosition Position of the FAB on the screen

21

* @param isFloatingActionButtonDocked Whether the FAB should dock with the bottom bar

22

* @param drawerContent Content of the Drawer sheet that can be pulled from the left side

23

* @param drawerGesturesEnabled Whether or not drawer can be interacted with via gestures

24

* @param drawerShape Shape of the drawer sheet

25

* @param drawerElevation Elevation of the drawer sheet

26

* @param drawerBackgroundColor Background color of the drawer sheet

27

* @param drawerContentColor Color of the content inside the drawer sheet

28

* @param drawerScrimColor Color of the scrim that obscures content when the drawer is open

29

* @param backgroundColor Background color of the scaffold body

30

* @param contentColor Preferred content color provided by scaffold to its children

31

* @param content Content of the screen

32

*/

33

@Composable

34

fun Scaffold(

35

modifier: Modifier = Modifier,

36

scaffoldState: ScaffoldState = rememberScaffoldState(),

37

topBar: @Composable () -> Unit = {},

38

bottomBar: @Composable () -> Unit = {},

39

snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) },

40

floatingActionButton: @Composable () -> Unit = {},

41

floatingActionButtonPosition: FabPosition = FabPosition.End,

42

isFloatingActionButtonDocked: Boolean = false,

43

drawerContent: @Composable (ColumnScope.() -> Unit)? = null,

44

drawerGesturesEnabled: Boolean = true,

45

drawerShape: Shape = MaterialTheme.shapes.large,

46

drawerElevation: Dp = DrawerDefaults.Elevation,

47

drawerBackgroundColor: Color = MaterialTheme.colors.surface,

48

drawerContentColor: Color = contentColorFor(drawerBackgroundColor),

49

drawerScrimColor: Color = DrawerDefaults.scrimColor,

50

backgroundColor: Color = MaterialTheme.colors.background,

51

contentColor: Color = contentColorFor(backgroundColor),

52

content: @Composable (PaddingValues) -> Unit

53

)

54

```

55

56

**Usage Examples:**

57

58

```kotlin

59

// Basic scaffold with iOS-style navigation

60

Scaffold(

61

topBar = {

62

TopAppBar(

63

title = { Text("My App") },

64

navigationIcon = {

65

IconButton(onClick = { /* handle back */ }) {

66

Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back")

67

}

68

}

69

)

70

},

71

floatingActionButton = {

72

FloatingActionButton(

73

onClick = { /* add action */ }

74

) {

75

Icon(Icons.Default.Add, contentDescription = "Add")

76

}

77

}

78

) { paddingValues ->

79

LazyColumn(

80

modifier = Modifier.padding(paddingValues),

81

contentPadding = PaddingValues(16.dp)

82

) {

83

items(items) { item ->

84

// List content

85

}

86

}

87

}

88

89

// Scaffold with drawer (iOS-style sidebar)

90

val scaffoldState = rememberScaffoldState()

91

val scope = rememberCoroutineScope()

92

93

Scaffold(

94

scaffoldState = scaffoldState,

95

topBar = {

96

TopAppBar(

97

title = { Text("With Drawer") },

98

navigationIcon = {

99

IconButton(

100

onClick = {

101

scope.launch {

102

scaffoldState.drawerState.open()

103

}

104

}

105

) {

106

Icon(Icons.Default.Menu, contentDescription = "Menu")

107

}

108

}

109

)

110

},

111

drawerContent = {

112

DrawerContent()

113

}

114

) { paddingValues ->

115

// Main content

116

}

117

118

// Scaffold with bottom navigation

119

Scaffold(

120

bottomBar = {

121

BottomNavigation {

122

val navItems = listOf("Home", "Search", "Profile")

123

navItems.forEachIndexed { index, item ->

124

BottomNavigationItem(

125

icon = { Icon(getIconForTab(index), contentDescription = null) },

126

label = { Text(item) },

127

selected = selectedTab == index,

128

onClick = { selectedTab = index }

129

)

130

}

131

}

132

}

133

) { paddingValues ->

134

// Content for each tab

135

}

136

```

137

138

### TopAppBar

139

140

Material app bar for screen headers with iOS navigation integration and safe area handling.

141

142

```kotlin { .api }

143

/**

144

* Material Design top app bar with iOS-style navigation integration

145

* @param title The title to be displayed in the center of the TopAppBar

146

* @param modifier Modifier to be applied to this TopAppBar

147

* @param navigationIcon The navigation icon displayed at the start of the TopAppBar

148

* @param actions The actions displayed at the end of the TopAppBar

149

* @param backgroundColor The background color for the TopAppBar

150

* @param contentColor The preferred content color provided by this TopAppBar to its children

151

* @param elevation The elevation of this TopAppBar

152

*/

153

@Composable

154

fun TopAppBar(

155

title: @Composable () -> Unit,

156

modifier: Modifier = Modifier,

157

navigationIcon: @Composable (() -> Unit)? = null,

158

actions: @Composable RowScope.() -> Unit = {},

159

backgroundColor: Color = MaterialTheme.colors.primarySurface,

160

contentColor: Color = contentColorFor(backgroundColor),

161

elevation: Dp = AppBarDefaults.TopAppBarElevation

162

)

163

```

164

165

**Usage Examples:**

166

167

```kotlin

168

// Basic top app bar

169

TopAppBar(

170

title = { Text("Screen Title") }

171

)

172

173

// Top app bar with navigation and actions

174

TopAppBar(

175

title = { Text("Messages") },

176

navigationIcon = {

177

IconButton(onClick = { /* navigate back */ }) {

178

Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back")

179

}

180

},

181

actions = {

182

IconButton(onClick = { /* search */ }) {

183

Icon(Icons.Default.Search, contentDescription = "Search")

184

}

185

IconButton(onClick = { /* more options */ }) {

186

Icon(Icons.Default.MoreVert, contentDescription = "More")

187

}

188

}

189

)

190

191

// Custom styled top app bar (iOS-style)

192

TopAppBar(

193

title = {

194

Text(

195

"Custom Title",

196

style = MaterialTheme.typography.h6.copy(fontWeight = FontWeight.Medium)

197

)

198

},

199

backgroundColor = Color.Transparent,

200

contentColor = MaterialTheme.colors.onBackground,

201

elevation = 0.dp

202

)

203

```

204

205

### TopAppBar Defaults and Customization

206

207

TopAppBar defaults and styling configurations for consistent Material Design appearance with iOS adaptations.

208

209

```kotlin { .api }

210

object TopAppBarDefaults {

211

/**

212

* Creates TopAppBarColors with Material 3 theming for iOS optimization

213

*/

214

@Composable

215

fun centerAlignedTopAppBarColors(

216

containerColor: Color = MaterialTheme.colorScheme.surface,

217

scrolledContainerColor: Color = MaterialTheme.colorScheme.applyTonalElevation(

218

backgroundColor = containerColor,

219

elevation = 3.dp

220

),

221

navigationIconContentColor: Color = MaterialTheme.colorScheme.onSurface,

222

titleContentColor: Color = MaterialTheme.colorScheme.onSurface,

223

actionIconContentColor: Color = MaterialTheme.colorScheme.onSurfaceVariant

224

): TopAppBarColors

225

226

/**

227

* Creates TopAppBarColors for medium-sized top app bars

228

*/

229

@Composable

230

fun mediumTopAppBarColors(

231

containerColor: Color = MaterialTheme.colorScheme.surface,

232

scrolledContainerColor: Color = MaterialTheme.colorScheme.applyTonalElevation(

233

backgroundColor = containerColor,

234

elevation = 3.dp

235

),

236

navigationIconContentColor: Color = MaterialTheme.colorScheme.onSurface,

237

titleContentColor: Color = MaterialTheme.colorScheme.onSurface,

238

actionIconContentColor: Color = MaterialTheme.colorScheme.onSurfaceVariant

239

): TopAppBarColors

240

241

/**

242

* Creates TopAppBarScrollBehavior for iOS-style scroll behavior

243

*/

244

@Composable

245

fun pinnedScrollBehavior(

246

state: TopAppBarState = rememberTopAppBarState(),

247

canScroll: () -> Boolean = { true }

248

): TopAppBarScrollBehavior

249

250

@Composable

251

fun enterAlwaysScrollBehavior(

252

state: TopAppBarState = rememberTopAppBarState(),

253

canScroll: () -> Boolean = { true },

254

snapAnimationSpec: AnimationSpec<Float>? = spring(stiffness = Spring.StiffnessMediumLow),

255

flingAnimationSpec: DecayAnimationSpec<Float>? = rememberSplineBasedDecay()

256

): TopAppBarScrollBehavior

257

}

258

259

interface TopAppBarColors {

260

@Composable

261

fun containerColor(scrollFraction: Float): State<Color>

262

@Composable

263

fun navigationIconContentColor(): State<Color>

264

@Composable

265

fun titleContentColor(): State<Color>

266

@Composable

267

fun actionIconContentColor(): State<Color>

268

}

269

270

interface TopAppBarScrollBehavior {

271

val state: TopAppBarState

272

val isPinned: Boolean

273

val snapAnimationSpec: AnimationSpec<Float>?

274

val flingAnimationSpec: DecayAnimationSpec<Float>?

275

val nestedScrollConnection: NestedScrollConnection

276

}

277

278

@Stable

279

class TopAppBarState(

280

heightOffsetLimit: Float,

281

initialHeightOffset: Float = 0f,

282

initialContentOffset: Float = 0f

283

) {

284

val heightOffset: Float

285

val contentOffset: Float

286

val overlappedFraction: Float

287

}

288

289

@Composable

290

fun rememberTopAppBarState(

291

initialHeightOffsetLimit: Float = -Float.MAX_VALUE,

292

initialHeightOffset: Float = 0f,

293

initialContentOffset: Float = 0f

294

): TopAppBarState

295

```

296

297

**Usage Examples:**

298

299

```kotlin

300

// TopAppBar with custom colors (iOS-style)

301

TopAppBar(

302

title = { Text("My App") },

303

colors = TopAppBarDefaults.centerAlignedTopAppBarColors(

304

containerColor = MaterialTheme.colorScheme.primaryContainer,

305

titleContentColor = MaterialTheme.colorScheme.onPrimaryContainer,

306

navigationIconContentColor = MaterialTheme.colorScheme.onPrimaryContainer

307

),

308

navigationIcon = {

309

IconButton(onClick = { /* back navigation */ }) {

310

Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back")

311

}

312

}

313

)

314

315

// TopAppBar with scroll behavior

316

val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())

317

318

Scaffold(

319

modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),

320

topBar = {

321

TopAppBar(

322

title = { Text("Scrolling App Bar") },

323

scrollBehavior = scrollBehavior

324

)

325

}

326

) { paddingValues ->

327

LazyColumn(

328

modifier = Modifier.fillMaxSize(),

329

contentPadding = paddingValues

330

) {

331

items(100) { index ->

332

Text(

333

text = "Item $index",

334

modifier = Modifier.padding(16.dp)

335

)

336

}

337

}

338

}

339

340

// Medium-sized TopAppBar with custom colors

341

MediumTopAppBar(

342

title = { Text("Large Title") },

343

colors = TopAppBarDefaults.mediumTopAppBarColors(

344

containerColor = MaterialTheme.colorScheme.surface,

345

titleContentColor = MaterialTheme.colorScheme.primary

346

),

347

scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()

348

)

349

```

350

351

### BottomNavigation

352

353

Bottom navigation bar container with iOS tab bar styling and behavior.

354

355

```kotlin { .api }

356

/**

357

* Material Design bottom navigation with iOS tab bar adaptations

358

* @param modifier Modifier to be applied to this BottomNavigation

359

* @param backgroundColor The background color for this BottomNavigation

360

* @param contentColor The preferred content color provided by this BottomNavigation to its children

361

* @param elevation The elevation of this BottomNavigation

362

* @param content The content of this BottomNavigation, typically BottomNavigationItems

363

*/

364

@Composable

365

fun BottomNavigation(

366

modifier: Modifier = Modifier,

367

backgroundColor: Color = MaterialTheme.colors.primarySurface,

368

contentColor: Color = contentColorFor(backgroundColor),

369

elevation: Dp = BottomNavigationDefaults.Elevation,

370

content: @Composable RowScope.() -> Unit

371

)

372

```

373

374

### BottomNavigationItem

375

376

Individual bottom navigation items with iOS-style selection states and animations.

377

378

```kotlin { .api }

379

/**

380

* Material Design bottom navigation item with iOS tab styling

381

* @param selected Whether this item is selected

382

* @param onClick Called when this item is clicked

383

* @param icon The icon for this item, typically an Icon

384

* @param modifier Modifier to be applied to this item

385

* @param enabled Controls the enabled state of this item

386

* @param label Optional text label for this item

387

* @param alwaysShowLabel Whether to always show the label for this item

388

* @param selectedContentColor The color of the content when this item is selected

389

* @param unselectedContentColor The color of the content when this item is not selected

390

*/

391

@Composable

392

fun RowScope.BottomNavigationItem(

393

selected: Boolean,

394

onClick: () -> Unit,

395

icon: @Composable () -> Unit,

396

modifier: Modifier = Modifier,

397

enabled: Boolean = true,

398

label: @Composable (() -> Unit)? = null,

399

alwaysShowLabel: Boolean = true,

400

selectedContentColor: Color = LocalContentColor.current,

401

unselectedContentColor: Color = selectedContentColor.copy(alpha = ContentAlpha.medium)

402

)

403

```

404

405

**Usage Examples:**

406

407

```kotlin

408

// iOS-style bottom navigation

409

var selectedTab by remember { mutableStateOf(0) }

410

val tabs = listOf(

411

Triple("Home", Icons.Default.Home, Icons.Outlined.Home),

412

Triple("Search", Icons.Default.Search, Icons.Outlined.Search),

413

Triple("Favorites", Icons.Default.Favorite, Icons.Outlined.FavoriteBorder),

414

Triple("Profile", Icons.Default.Person, Icons.Outlined.Person)

415

)

416

417

BottomNavigation(

418

backgroundColor = MaterialTheme.colors.surface,

419

contentColor = MaterialTheme.colors.primary

420

) {

421

tabs.forEachIndexed { index, (title, selectedIcon, unselectedIcon) ->

422

BottomNavigationItem(

423

icon = {

424

Icon(

425

if (selectedTab == index) selectedIcon else unselectedIcon,

426

contentDescription = null

427

)

428

},

429

label = { Text(title) },

430

selected = selectedTab == index,

431

onClick = { selectedTab = index },

432

selectedContentColor = MaterialTheme.colors.primary,

433

unselectedContentColor = MaterialTheme.colors.onSurface.copy(alpha = 0.6f)

434

)

435

}

436

}

437

```

438

439

### BottomAppBar

440

441

Bottom app bar with FAB integration and iOS-style positioning.

442

443

```kotlin { .api }

444

/**

445

* Material Design bottom app bar with iOS-optimized FAB integration

446

* @param modifier Modifier to be applied to this BottomAppBar

447

* @param backgroundColor The background color for this BottomAppBar

448

* @param contentColor The preferred content color provided by this BottomAppBar to its children

449

* @param cutoutShape The shape of the cutout that will be added to the BottomAppBar

450

* @param elevation The elevation of this BottomAppBar

451

* @param content The content of this BottomAppBar

452

*/

453

@Composable

454

fun BottomAppBar(

455

modifier: Modifier = Modifier,

456

backgroundColor: Color = MaterialTheme.colors.primarySurface,

457

contentColor: Color = contentColorFor(backgroundColor),

458

cutoutShape: Shape? = null,

459

elevation: Dp = AppBarDefaults.BottomAppBarElevation,

460

content: @Composable RowScope.() -> Unit

461

)

462

```

463

464

### NavigationRail

465

466

Vertical navigation component for larger iOS devices like iPad.

467

468

```kotlin { .api }

469

/**

470

* Material Design navigation rail optimized for iOS larger screens

471

* @param modifier Modifier to be applied to this NavigationRail

472

* @param backgroundColor The background color for this NavigationRail

473

* @param contentColor The preferred content color provided by this NavigationRail to its children

474

* @param elevation The elevation of this NavigationRail

475

* @param header Optional header content displayed at the top

476

* @param content The content of this NavigationRail, typically NavigationRailItems

477

*/

478

@Composable

479

fun NavigationRail(

480

modifier: Modifier = Modifier,

481

backgroundColor: Color = MaterialTheme.colors.surface,

482

contentColor: Color = contentColorFor(backgroundColor),

483

elevation: Dp = NavigationRailDefaults.Elevation,

484

header: @Composable (ColumnScope.() -> Unit)? = null,

485

content: @Composable ColumnScope.() -> Unit

486

)

487

```

488

489

### Drawer Components

490

491

Material Design drawer components with iOS-style presentation and gestures.

492

493

```kotlin { .api }

494

/**

495

* State of the DrawerLayout composable

496

*/

497

@Stable

498

class DrawerState(

499

initialValue: DrawerValue,

500

confirmStateChange: (DrawerValue) -> Boolean = { true }

501

) {

502

val currentValue: DrawerValue

503

val isAnimationRunning: Boolean

504

val isClosed: Boolean

505

val isOpen: Boolean

506

507

suspend fun open()

508

suspend fun close()

509

suspend fun animateTo(targetValue: DrawerValue, anim: AnimationSpec<Float> = DrawerConstants.defaultAnimationSpec)

510

suspend fun snapTo(targetValue: DrawerValue)

511

}

512

513

/**

514

* Create and remember a DrawerState

515

*/

516

@Composable

517

fun rememberDrawerState(

518

initialValue: DrawerValue,

519

confirmStateChange: (DrawerValue) -> Boolean = { true }

520

): DrawerState

521

522

enum class DrawerValue {

523

Closed, Open

524

}

525

```

526

527

**Usage Examples:**

528

529

```kotlin

530

// Modal drawer with iOS-style presentation

531

@Composable

532

fun ModalDrawerExample() {

533

val drawerState = rememberDrawerState(DrawerValue.Closed)

534

val scope = rememberCoroutineScope()

535

536

ModalDrawer(

537

drawerState = drawerState,

538

drawerShape = RoundedCornerShape(topEnd = 16.dp, bottomEnd = 16.dp),

539

drawerContent = {

540

Column(

541

modifier = Modifier

542

.fillMaxHeight()

543

.width(300.dp)

544

.padding(16.dp)

545

) {

546

Text(

547

"Drawer Header",

548

style = MaterialTheme.typography.h6,

549

modifier = Modifier.padding(bottom = 16.dp)

550

)

551

Divider()

552

// Drawer items

553

repeat(5) { index ->

554

TextButton(

555

onClick = {

556

scope.launch { drawerState.close() }

557

},

558

modifier = Modifier.fillMaxWidth()

559

) {

560

Text("Menu Item ${index + 1}")

561

}

562

}

563

}

564

}

565

) {

566

// Main content

567

Scaffold(

568

topBar = {

569

TopAppBar(

570

title = { Text("Drawer Example") },

571

navigationIcon = {

572

IconButton(

573

onClick = {

574

scope.launch { drawerState.open() }

575

}

576

) {

577

Icon(Icons.Default.Menu, contentDescription = "Menu")

578

}

579

}

580

)

581

}

582

) { paddingValues ->

583

// Screen content

584

}

585

}

586

}

587

```

588

589

## Navigation Defaults and Utilities

590

591

```kotlin { .api }

592

object AppBarDefaults {

593

val TopAppBarElevation: Dp = 4.dp

594

val BottomAppBarElevation: Dp = 8.dp

595

}

596

597

object BottomNavigationDefaults {

598

val Elevation: Dp = 8.dp

599

}

600

601

object NavigationRailDefaults {

602

val Elevation: Dp = 0.dp

603

}

604

605

object DrawerDefaults {

606

val Elevation: Dp = 16.dp

607

val scrimColor: Color = Color.Black.copy(alpha = 0.32f)

608

}

609

610

enum class FabPosition {

611

Center, End

612

}

613

614

@Stable

615

class ScaffoldState(

616

val drawerState: DrawerState,

617

val snackbarHostState: SnackbarHostState

618

)

619

620

@Composable

621

fun rememberScaffoldState(

622

drawerState: DrawerState = rememberDrawerState(DrawerValue.Closed),

623

snackbarHostState: SnackbarHostState = remember { SnackbarHostState() }

624

): ScaffoldState

625

```

626

627

### TabRow

628

629

Material Design tab layout for organizing content into different views with iOS-optimized touch targets.

630

631

```kotlin { .api }

632

/**

633

* Material Design fixed tab row with iOS-optimized spacing and touch targets

634

* @param selectedTabIndex The index of the currently selected tab

635

* @param modifier Modifier to be applied to this tab row

636

* @param backgroundColor The background color for the tab row

637

* @param contentColor The preferred content color provided by this tab row to its children

638

* @param indicator The indicator that represents which tab is currently selected

639

* @param divider The divider displayed at the bottom of the tab row

640

* @param tabs The tabs inside this tab row, typically this will be multiple Tab components

641

*/

642

@Composable

643

fun TabRow(

644

selectedTabIndex: Int,

645

modifier: Modifier = Modifier,

646

backgroundColor: Color = MaterialTheme.colors.primarySurface,

647

contentColor: Color = contentColorFor(backgroundColor),

648

indicator: @Composable (tabPositions: List<TabPosition>) -> Unit = @Composable { tabPositions ->

649

TabRowDefaults.Indicator(

650

Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex])

651

)

652

},

653

divider: @Composable () -> Unit = @Composable {

654

TabRowDefaults.Divider()

655

},

656

tabs: @Composable () -> Unit

657

)

658

659

/**

660

* Material Design scrollable tab row for large numbers of tabs with iOS momentum scrolling

661

* @param selectedTabIndex The index of the currently selected tab

662

* @param modifier Modifier to be applied to this tab row

663

* @param backgroundColor The background color for the tab row

664

* @param contentColor The preferred content color provided by this tab row to its children

665

* @param edgePadding The padding between the starting and ending edge of the scrollable tab row

666

* @param indicator The indicator that represents which tab is currently selected

667

* @param divider The divider displayed at the bottom of the tab row

668

* @param tabs The tabs inside this tab row, typically this will be multiple Tab components

669

*/

670

@Composable

671

fun ScrollableTabRow(

672

selectedTabIndex: Int,

673

modifier: Modifier = Modifier,

674

backgroundColor: Color = MaterialTheme.colors.primarySurface,

675

contentColor: Color = contentColorFor(backgroundColor),

676

edgePadding: Dp = TabRowDefaults.ScrollableTabRowPadding,

677

indicator: @Composable (tabPositions: List<TabPosition>) -> Unit = @Composable { tabPositions ->

678

TabRowDefaults.Indicator(

679

Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex])

680

)

681

},

682

divider: @Composable () -> Unit = @Composable {

683

TabRowDefaults.Divider()

684

},

685

tabs: @Composable () -> Unit

686

)

687

688

/**

689

* Material Design tab with iOS-optimized touch feedback and accessibility

690

* @param selected Whether this tab is currently selected

691

* @param onClick The callback to be invoked when this tab is selected

692

* @param modifier Modifier to be applied to this tab

693

* @param enabled Controls the enabled state of this tab

694

* @param text The text label displayed in this tab

695

* @param icon The optional icon displayed in this tab

696

* @param interactionSource The MutableInteractionSource representing the stream of interactions

697

* @param selectedContentColor The color of the content when this tab is selected

698

* @param unselectedContentColor The color of the content when this tab is not selected

699

*/

700

@Composable

701

fun Tab(

702

selected: Boolean,

703

onClick: () -> Unit,

704

modifier: Modifier = Modifier,

705

enabled: Boolean = true,

706

text: @Composable (() -> Unit)? = null,

707

icon: @Composable (() -> Unit)? = null,

708

interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },

709

selectedContentColor: Color = LocalContentColor.current,

710

unselectedContentColor: Color = selectedContentColor.copy(alpha = ContentAlpha.medium)

711

)

712

713

/**

714

* LeadingIconTab with both icon and text arranged horizontally

715

*/

716

@Composable

717

fun LeadingIconTab(

718

selected: Boolean,

719

onClick: () -> Unit,

720

text: @Composable () -> Unit,

721

icon: @Composable () -> Unit,

722

modifier: Modifier = Modifier,

723

enabled: Boolean = true,

724

interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },

725

selectedContentColor: Color = LocalContentColor.current,

726

unselectedContentColor: Color = selectedContentColor.copy(alpha = ContentAlpha.medium)

727

)

728

729

object TabRowDefaults {

730

val ScrollableTabRowPadding: Dp = 52.dp

731

732

@Composable

733

fun Indicator(

734

modifier: Modifier = Modifier,

735

height: Dp = 2.dp,

736

color: Color = LocalContentColor.current

737

)

738

739

@Composable

740

fun Divider(

741

modifier: Modifier = Modifier,

742

thickness: Dp = 1.dp,

743

color: Color = LocalContentColor.current.copy(alpha = 0.12f)

744

)

745

}

746

747

@Stable

748

class TabPosition(val left: Dp, val width: Dp) {

749

val right: Dp get() = left + width

750

}

751

752

fun Modifier.tabIndicatorOffset(

753

currentTabPosition: TabPosition

754

): Modifier

755

```

756

757

**Usage Examples:**

758

759

```kotlin

760

// Basic tab row with text tabs

761

var selectedTab by remember { mutableStateOf(0) }

762

val tabs = listOf("Home", "Search", "Profile")

763

764

Column {

765

TabRow(selectedTabIndex = selectedTab) {

766

tabs.forEachIndexed { index, title ->

767

Tab(

768

selected = selectedTab == index,

769

onClick = { selectedTab = index },

770

text = { Text(title) }

771

)

772

}

773

}

774

775

// Content based on selected tab

776

when (selectedTab) {

777

0 -> HomeContent()

778

1 -> SearchContent()

779

2 -> ProfileContent()

780

}

781

}

782

783

// Tab row with icons and text

784

TabRow(selectedTabIndex = currentTab) {

785

Tab(

786

selected = currentTab == 0,

787

onClick = { currentTab = 0 },

788

text = { Text("Calls") },

789

icon = { Icon(Icons.Default.Call, contentDescription = null) }

790

)

791

Tab(

792

selected = currentTab == 1,

793

onClick = { currentTab = 1 },

794

text = { Text("Messages") },

795

icon = { Icon(Icons.Default.Email, contentDescription = null) }

796

)

797

Tab(

798

selected = currentTab == 2,

799

onClick = { currentTab = 2 },

800

text = { Text("Contacts") },

801

icon = { Icon(Icons.Default.Person, contentDescription = null) }

802

)

803

}

804

805

// Scrollable tab row for many tabs

806

ScrollableTabRow(

807

selectedTabIndex = selectedTabIndex,

808

backgroundColor = MaterialTheme.colors.surface,

809

contentColor = MaterialTheme.colors.onSurface

810

) {

811

categories.forEachIndexed { index, category ->

812

Tab(

813

selected = selectedTabIndex == index,

814

onClick = { selectedTabIndex = index },

815

text = { Text(category.name) }

816

)

817

}

818

}

819

820

// Leading icon tab with horizontal arrangement

821

LeadingIconTab(

822

selected = currentTab == 0,

823

onClick = { currentTab = 0 },

824

text = { Text("Documents") },

825

icon = { Icon(Icons.Default.Description, contentDescription = null) }

826

)

827

```

828

829

### NavigationBar (Material 3)

830

831

Material 3 navigation bar for bottom navigation with modern design language and iOS-optimized behavior.

832

833

```kotlin { .api }

834

/**

835

* Material 3 NavigationBar for bottom navigation with iOS integration

836

* @param modifier Modifier to be applied to this navigation bar

837

* @param containerColor The color used for the background of this navigation bar

838

* @param contentColor The preferred color for content inside this navigation bar

839

* @param tonalElevation When containerColor is ColorScheme.surface, a translucent primary color overlay is applied

840

* @param windowInsets A window insets that the navigation bar will respect

841

* @param content The content of this navigation bar, typically NavigationBarItem components

842

*/

843

@Composable

844

fun NavigationBar(

845

modifier: Modifier = Modifier,

846

containerColor: Color = NavigationBarDefaults.containerColor,

847

contentColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,

848

tonalElevation: Dp = NavigationBarDefaults.Elevation,

849

windowInsets: WindowInsets = NavigationBarDefaults.windowInsets,

850

content: @Composable RowScope.() -> Unit

851

)

852

853

/**

854

* Material 3 NavigationBarItem with iOS-optimized selection behavior

855

* @param selected Whether this item is currently selected

856

* @param onClick Called when this item is clicked

857

* @param icon The icon for this item

858

* @param modifier Modifier to be applied to this item

859

* @param enabled Controls the enabled state of this item

860

* @param label Optional text label for this item

861

* @param alwaysShowLabel Whether to always show the label for this item

862

* @param colors NavigationBarItemColors that will be used to resolve the colors used for this item

863

* @param interactionSource The MutableInteractionSource representing the stream of interactions

864

*/

865

@Composable

866

fun RowScope.NavigationBarItem(

867

selected: Boolean,

868

onClick: () -> Unit,

869

icon: @Composable () -> Unit,

870

modifier: Modifier = Modifier,

871

enabled: Boolean = true,

872

label: @Composable (() -> Unit)? = null,

873

alwaysShowLabel: Boolean = true,

874

colors: NavigationBarItemColors = NavigationBarItemDefaults.colors(),

875

interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }

876

)

877

878

object NavigationBarDefaults {

879

val Elevation: Dp = 3.dp

880

val containerColor: Color @Composable get() = MaterialTheme.colorScheme.surface

881

val windowInsets: WindowInsets @Composable get() = WindowInsets.systemBars.only(WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom)

882

}

883

884

object NavigationBarItemDefaults {

885

@Composable

886

fun colors(

887

selectedIconColor: Color = NavigationBarTokens.ActiveIconColor.toColor(),

888

selectedTextColor: Color = NavigationBarTokens.ActiveLabelTextColor.toColor(),

889

indicatorColor: Color = NavigationBarTokens.ActiveIndicatorColor.toColor(),

890

unselectedIconColor: Color = NavigationBarTokens.InactiveIconColor.toColor(),

891

unselectedTextColor: Color = NavigationBarTokens.InactiveLabelTextColor.toColor(),

892

disabledIconColor: Color = NavigationBarTokens.InactiveIconColor.toColor().copy(alpha = 0.38f),

893

disabledTextColor: Color = NavigationBarTokens.InactiveLabelTextColor.toColor().copy(alpha = 0.38f)

894

): NavigationBarItemColors

895

}

896

897

interface NavigationBarItemColors

898

899

interface WindowInsets {

900

companion object {

901

val systemBars: WindowInsets

902

}

903

904

fun only(sides: WindowInsetsSides): WindowInsets

905

}

906

907

enum class WindowInsetsSides {

908

Start, Top, End, Bottom, Horizontal, Vertical, All

909

}

910

```

911

912

**Usage Examples:**

913

914

```kotlin

915

// Basic navigation bar with icons and labels

916

var selectedItem by remember { mutableStateOf(0) }

917

val items = listOf("Home", "Search", "Profile")

918

val icons = listOf(Icons.Default.Home, Icons.Default.Search, Icons.Default.Person)

919

920

Scaffold(

921

bottomBar = {

922

NavigationBar {

923

items.forEachIndexed { index, item ->

924

NavigationBarItem(

925

icon = { Icon(icons[index], contentDescription = null) },

926

label = { Text(item) },

927

selected = selectedItem == index,

928

onClick = { selectedItem = index }

929

)

930

}

931

}

932

}

933

) { innerPadding ->

934

// Screen content

935

}

936

937

// Navigation bar with badges

938

NavigationBar {

939

NavigationBarItem(

940

icon = {

941

BadgedBox(

942

badge = { Badge { Text("3") } }

943

) {

944

Icon(Icons.Default.Email, contentDescription = null)

945

}

946

},

947

label = { Text("Messages") },

948

selected = selectedTab == 0,

949

onClick = { selectedTab = 0 }

950

)

951

952

NavigationBarItem(

953

icon = { Icon(Icons.Default.Home, contentDescription = null) },

954

label = { Text("Home") },

955

selected = selectedTab == 1,

956

onClick = { selectedTab = 1 }

957

)

958

959

NavigationBarItem(

960

icon = {

961

BadgedBox(

962

badge = { Badge() }

963

) {

964

Icon(Icons.Default.Notifications, contentDescription = null)

965

}

966

},

967

label = { Text("Alerts") },

968

selected = selectedTab == 2,

969

onClick = { selectedTab = 2 }

970

)

971

}

972

973

// Custom colors navigation bar

974

NavigationBar(

975

containerColor = MaterialTheme.colorScheme.surfaceVariant

976

) {

977

NavigationBarItem(

978

icon = { Icon(Icons.Default.Home, contentDescription = null) },

979

label = { Text("Home") },

980

selected = currentDestination == "home",

981

onClick = { navigateTo("home") },

982

colors = NavigationBarItemDefaults.colors(

983

selectedIconColor = MaterialTheme.colorScheme.primary,

984

unselectedIconColor = MaterialTheme.colorScheme.onSurfaceVariant,

985

selectedTextColor = MaterialTheme.colorScheme.primary,

986

unselectedTextColor = MaterialTheme.colorScheme.onSurfaceVariant

987

)

988

)

989

}

990

```