Skip to content

TabRow

TabRow is a navigation component in COUI that reproduces the ColorOS 16 segment button (COUISegmentButtonLayout). It provides two variants: the contour style (a capsule container with a sliding indicator) and the standard style (the same segment button without the container fill), suitable for content categorization and navigation scenarios.

Import

kotlin
import io.github.suqi8.coui.kmp.basic.TabRow // Standard style (frameless)
import io.github.suqi8.coui.kmp.basic.TabRowWithContour // Contour style (segment button)

Basic Usage

Standard Style

The standard style draws only the sliding capsule indicator and its drop shadow, on a transparent background by default.

kotlin
val tabs = listOf("Recommended", "Following", "Popular", "Featured")
var selectedTabIndex by remember { mutableStateOf(0) }

TabRow(
    tabs = tabs,
    selectedTabIndex = selectedTabIndex,
    onTabSelected = { selectedTabIndex = it }
)

Contour Style

The contour style matches the ColorOS segment button: a 40dp capsule container with a 4dp inset around the sliding indicator. Segments are measured from their label width (at least 52dp) and distributed to fill the row.

kotlin
val tabs = listOf("All", "Photos", "Videos", "Documents")
var selectedTabIndex by remember { mutableStateOf(0) }

TabRowWithContour(
    tabs = tabs,
    selectedTabIndex = selectedTabIndex,
    onTabSelected = { selectedTabIndex = it }
)

Preserve Scroll Position

When the tabs cannot fit at their minimum width, the row becomes scrollable.

kotlin
val tabs = listOf("Tab 1", "Tab 2", "Tab 3", "Tab 4", "Tab 5")
var selectedTabIndex by remember { mutableStateOf(3) }
val tabListState = rememberLazyListState()

TabRowWithContour(
    tabs = tabs,
    selectedTabIndex = selectedTabIndex,
    onTabSelected = { selectedTabIndex = it },
    listState = tabListState,
)

Properties

TabRow Properties

Property NameTypeDescriptionDefault ValueRequired
tabsList<String>List of tab texts-Yes
selectedTabIndexIntCurrent selected tab index-Yes
onTabSelected(Int) -> UnitCallback when tab is selected-Yes
modifierModifierModifier for the tab rowModifierNo
colorsTabRowColorsColor configurationTabRowDefaults.tabRowColors(backgroundColor = Color.Transparent)No
minWidthDpMinimum width of each tabTabRowDefaults.TabRowMinWidthNo
maxWidthDpMaximum width of each tabTabRowDefaults.TabRowMaxWidthNo
heightDpHeight of the tab rowTabRowDefaults.TabRowHeightNo
cornerRadiusDpCorner radius of the indicatorTabRowDefaults.TabRowCornerRadiusNo
itemSpacingDpSpacing between tabs0.dpNo
contentAlignmentAlignmentAlignment of tab contentAlignment.CenterNo
listStateLazyListState?External scroll state for tabsnullNo
interactionSourceMutableInteractionSource?Interaction source for tab itemsnullNo
indicationIndication?Indication for tab itemsnullNo

TabRowWithContour Properties

Property NameTypeDescriptionDefault ValueRequired
tabsList<String>List of tab texts-Yes
selectedTabIndexIntCurrent selected tab index-Yes
onTabSelected(Int) -> UnitCallback when tab is selected-Yes
modifierModifierModifier for the tab rowModifierNo
colorsTabRowColorsColor configurationTabRowDefaults.tabRowColors()No
minWidthDpMinimum width of each tabTabRowDefaults.TabRowWithContourMinWidthNo
maxWidthDpMaximum width of each tabTabRowDefaults.TabRowWithContourMaxWidthNo
heightDpHeight of the tab rowTabRowDefaults.TabRowWithContourHeightNo
cornerRadiusDpCorner radius of the indicatorTabRowDefaults.TabRowWithContourCornerRadiusNo
contourPaddingDpInset between container and indicatorTabRowDefaults.TabRowWithContourPaddingNo
itemSpacingDpSpacing between tabs0.dpNo
contentAlignmentAlignmentAlignment of tab contentAlignment.CenterNo
listStateLazyListState?External scroll state for tabsnullNo
interactionSourceMutableInteractionSource?Interaction source for tab itemsnullNo
indicationIndication?Indication for tab itemsnullNo

TabRowDefaults Object

The TabRowDefaults object provides default configurations for the TabRow component.

Constants

Constant NameTypeValueDescription
TabRowHeightDp40.dpDefault height of tab row for standard style
TabRowWithContourHeightDp40.dpDefault height of tab row for contour style
TabRowWithContourTinyHeightDp32.dpHeight of the COUI SegmentButton.Tiny style
TabRowCornerRadiusDp20.dpDefault indicator corner radius (capsule) for standard style
TabRowWithContourCornerRadiusDp16.dpDefault indicator corner radius (capsule) for contour style
TabRowWithContourTinyCornerRadiusDp14.dpIndicator corner radius of the SegmentButton.Tiny style
TabRowWithContourPaddingDp4.dpDefault inset between container and indicator
TabRowWithContourTinyPaddingDp2.dpContour inset of the SegmentButton.Tiny style
TabRowMinWidthDp52.dpMin width of tabs for standard style
TabRowWithContourMinWidthDp52.dpMin width of tabs for contour style
TabRowMaxWidthDpDp.InfinityMax width of tabs for standard style (unbounded, tabs fill row)
TabRowWithContourMaxWidthDpDp.InfinityMax width of tabs for contour style (unbounded, tabs fill row)

Methods

Method NameTypeDescription
tabRowColors()TabRowColorsCreate default color configuration

TabRowColors Class

Property NameTypeDescription
backgroundColorColorBackground color of the container
contentColorColorDefault content color of tabs
selectedBackgroundColorColorColor of the sliding indicator
selectedContentColorColorContent color of the selected tab

Advanced Usage

Custom Colors

kotlin
val tabs = listOf("Latest", "Popular", "Following")
var selectedTabIndex by remember { mutableStateOf(0) }

TabRow(
    tabs = tabs,
    selectedTabIndex = selectedTabIndex,
    onTabSelected = { selectedTabIndex = it },
    colors = TabRowDefaults.tabRowColors(
        backgroundColor = Color.LightGray.copy(alpha = 0.5f),
        contentColor = Color.Gray,
        selectedBackgroundColor = COUITheme.colorScheme.primary,
        selectedContentColor = Color.White
    )
)

Tiny Variant

kotlin
val tabs = listOf("Photo", "Video", "Portrait")
var selectedTabIndex by remember { mutableStateOf(0) }

TabRowWithContour(
    tabs = tabs,
    selectedTabIndex = selectedTabIndex,
    onTabSelected = { selectedTabIndex = it },
    height = TabRowDefaults.TabRowWithContourTinyHeight,
    cornerRadius = TabRowDefaults.TabRowWithContourTinyCornerRadius,
    contourPadding = TabRowDefaults.TabRowWithContourTinyPadding
)

Using with Pager

kotlin
val tabs = listOf("Page 1", "Page 2", "Page 3")
val pagerState = rememberPagerState { tabs.size }
var selectedTabIndex by remember { mutableStateOf(0) }

LaunchedEffect(pagerState.currentPage) {
    selectedTabIndex = pagerState.currentPage
}

LaunchedEffect(selectedTabIndex) {
    pagerState.animateScrollToPage(selectedTabIndex)
}

Surface {
    Column {
        TabRow(
            tabs = tabs,
            selectedTabIndex = selectedTabIndex,
            onTabSelected = { selectedTabIndex = it }
        )
        HorizontalPager(
            pagerState = pagerState,
            modifier = Modifier.fillMaxSize()
        ) { page ->
            Box(
                modifier = Modifier.fillMaxSize(),
                contentAlignment = Alignment.Center
            ) {
                Text("Page Content ${page + 1}")
            }
        }
    }
}

Changelog

Released under the Apache-2.0 License