style: tab bar

This commit is contained in:
2026-06-08 20:02:51 +03:30
parent 16128e5304
commit 34ae6a1b54
2 changed files with 100 additions and 23 deletions
@@ -0,0 +1,90 @@
package com.approagency.pharmacy.presentation.common
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import com.vada.caller.ui.theme.dime
/**
* نوار تب‌های سگمنتی: تبِ انتخاب‌شده به‌صورت یک «قرص» پررنگ نمایش داده می‌شود
* تا کاملاً قابل لمس و قابل‌تشخیص باشد. عرض همه‌ی تب‌ها برابر است.
*/
@Composable
fun SegmentedTabBar(
tabs: List<String>,
selectedIndex: Int,
onSelected: (Int) -> Unit,
modifier: Modifier = Modifier
) {
val dime = MaterialTheme.dime
Row(
modifier = modifier
.fillMaxWidth()
.clip(MaterialTheme.shapes.large)
.background(MaterialTheme.colorScheme.surfaceContainerHigh)
.padding(dime.xxs),
horizontalArrangement = Arrangement.spacedBy(dime.xxs)
) {
tabs.forEachIndexed { index, title ->
val selected = index == selectedIndex
val background by animateColorAsState(
targetValue = if (selected) MaterialTheme.colorScheme.primary else Color.Transparent,
animationSpec = tween(durationMillis = 200),
label = "segmentBackground"
)
val foreground by animateColorAsState(
targetValue = if (selected)
MaterialTheme.colorScheme.onPrimary
else
MaterialTheme.colorScheme.onSurfaceVariant,
animationSpec = tween(durationMillis = 200),
label = "segmentForeground"
)
val interactionSource = remember { MutableInteractionSource() }
Box(
modifier = Modifier
.weight(1f)
.clip(MaterialTheme.shapes.medium)
.background(background)
.clickable(
interactionSource = interactionSource,
indication = null
) { onSelected(index) }
.padding(vertical = dime.sm, horizontal = dime.xs),
contentAlignment = Alignment.Center
) {
Text(
text = title,
style = MaterialTheme.typography.labelMedium,
fontWeight = if (selected) FontWeight.Bold else FontWeight.Medium,
color = foreground,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
textAlign = TextAlign.Center
)
}
}
}
}
@@ -14,8 +14,6 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Tab
import androidx.compose.material3.TabRow
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
@@ -29,13 +27,13 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.LayoutDirection
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavController import androidx.navigation.NavController
import com.approagency.pharmacy.presentation.common.ErrorState import com.approagency.pharmacy.presentation.common.ErrorState
import com.approagency.pharmacy.presentation.common.Loading import com.approagency.pharmacy.presentation.common.Loading
import com.approagency.pharmacy.presentation.common.SegmentedTabBar
import com.approagency.pharmacy.presentation.components.drugdetail.BrandNamesTabContent import com.approagency.pharmacy.presentation.components.drugdetail.BrandNamesTabContent
import com.approagency.pharmacy.presentation.components.drugdetail.DosageFormsTabContent import com.approagency.pharmacy.presentation.components.drugdetail.DosageFormsTabContent
import com.approagency.pharmacy.presentation.components.drugdetail.GeneralInfoTabContent import com.approagency.pharmacy.presentation.components.drugdetail.GeneralInfoTabContent
@@ -140,26 +138,15 @@ fun DrugDetailScreen(
) )
} }
TabRow( SegmentedTabBar(
selectedTabIndex = selectedTab, tabs = tabs,
containerColor = MaterialTheme.colorScheme.surface, selectedIndex = selectedTab,
contentColor = MaterialTheme.colorScheme.primary onSelected = { selectedTab = it },
) { modifier = Modifier.padding(
tabs.forEachIndexed { index, title -> horizontal = dime.md,
Tab( vertical = dime.sm
selected = selectedTab == index, )
onClick = { selectedTab = index }, )
text = {
Text(
text = title,
style = MaterialTheme.typography.labelLarge,
fontWeight = if (selectedTab == index) FontWeight.Bold else FontWeight.Normal,
maxLines = 1
)
}
)
}
}
LazyColumn( LazyColumn(
modifier = Modifier modifier = Modifier