mirror of
https://github.com/bitwarden/android.git
synced 2026-04-29 04:18:52 -05:00
PM-24942: Move Segmented control to UI module (#5727)
This commit is contained in:
@@ -1,151 +0,0 @@
|
||||
package com.x8bit.bitwarden.ui.platform.components.segment
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||
import androidx.compose.foundation.layout.displayCutout
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.union
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.material3.SegmentedButton
|
||||
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
|
||||
import androidx.compose.material3.SingleChoiceSegmentedButtonRowScope
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.text.style.Hyphens
|
||||
import androidx.compose.ui.unit.Density
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.bitwarden.ui.platform.base.util.nullableTestTag
|
||||
import com.bitwarden.ui.platform.base.util.toDp
|
||||
import com.bitwarden.ui.platform.theme.BitwardenTheme
|
||||
import com.x8bit.bitwarden.ui.platform.components.segment.color.bitwardenSegmentedButtonColors
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
private const val FONT_SCALE_THRESHOLD = 1.5f
|
||||
|
||||
/**
|
||||
* Displays a Bitwarden styled row of segmented buttons.
|
||||
*
|
||||
* @param options List of options to display.
|
||||
* @param modifier Modifier.
|
||||
* @param windowInsets The insets to be applied to this composable.
|
||||
* @param optionContent For outer context the content lambda passes back the index of the option,
|
||||
* the weighted width (in [Dp]) per option (total width / # number of options), and the
|
||||
* corresponding [SegmentedButtonState].
|
||||
*/
|
||||
@Composable
|
||||
fun BitwardenSegmentedButton(
|
||||
options: ImmutableList<SegmentedButtonState>,
|
||||
modifier: Modifier = Modifier,
|
||||
windowInsets: WindowInsets = WindowInsets.displayCutout
|
||||
.union(WindowInsets.navigationBars)
|
||||
.only(WindowInsetsSides.Horizontal),
|
||||
density: Density = LocalDensity.current,
|
||||
optionContent: @Composable SingleChoiceSegmentedButtonRowScope.(
|
||||
Int,
|
||||
Dp,
|
||||
SegmentedButtonState,
|
||||
) -> Unit = { _, _, optionState ->
|
||||
this.SegmentedButtonOptionContent(
|
||||
option = optionState,
|
||||
)
|
||||
},
|
||||
) {
|
||||
if (options.isEmpty()) return
|
||||
Box(
|
||||
modifier = modifier
|
||||
.background(color = BitwardenTheme.colorScheme.background.secondary)
|
||||
.padding(top = 4.dp, bottom = 8.dp, start = 16.dp, end = 16.dp)
|
||||
.windowInsetsPadding(insets = windowInsets),
|
||||
) {
|
||||
var weightedWidth by remember {
|
||||
mutableStateOf(0.dp)
|
||||
}
|
||||
SingleChoiceSegmentedButtonRow(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(
|
||||
color = BitwardenTheme.colorScheme.background.primary,
|
||||
shape = BitwardenTheme.shapes.segmentedControl,
|
||||
)
|
||||
.onGloballyPositioned {
|
||||
weightedWidth = (it.size.width / options.size).toDp(density)
|
||||
}
|
||||
.padding(horizontal = 2.dp, vertical = 2.dp)
|
||||
.height(IntrinsicSize.Min),
|
||||
space = 0.dp,
|
||||
) {
|
||||
options.forEachIndexed { index, option ->
|
||||
optionContent(index, weightedWidth, option)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default content definition for each option in a [BitwardenSegmentedButton].
|
||||
*/
|
||||
@Composable
|
||||
fun SingleChoiceSegmentedButtonRowScope.SegmentedButtonOptionContent(
|
||||
option: SegmentedButtonState,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val fontScale = LocalConfiguration.current.fontScale
|
||||
val labelVerticalPadding = if (fontScale > FONT_SCALE_THRESHOLD) {
|
||||
8.dp
|
||||
} else {
|
||||
0.dp
|
||||
}
|
||||
SegmentedButton(
|
||||
enabled = option.isEnabled,
|
||||
selected = option.isChecked,
|
||||
onClick = option.onClick,
|
||||
colors = bitwardenSegmentedButtonColors(),
|
||||
shape = BitwardenTheme.shapes.segmentedControl,
|
||||
border = BorderStroke(width = 0.dp, color = Color.Transparent),
|
||||
label = {
|
||||
Text(
|
||||
text = option.text,
|
||||
style = BitwardenTheme.typography.labelLarge.copy(
|
||||
hyphens = Hyphens.Auto,
|
||||
),
|
||||
modifier = Modifier.padding(
|
||||
vertical = labelVerticalPadding,
|
||||
horizontal = 4.dp,
|
||||
),
|
||||
)
|
||||
},
|
||||
icon = {
|
||||
// No icon required
|
||||
},
|
||||
modifier = modifier.nullableTestTag(tag = option.testTag),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Models state for an individual button in a [BitwardenSegmentedButton].
|
||||
*/
|
||||
data class SegmentedButtonState(
|
||||
val text: String,
|
||||
val onClick: () -> Unit,
|
||||
val isChecked: Boolean,
|
||||
val isEnabled: Boolean = true,
|
||||
val testTag: String? = null,
|
||||
)
|
||||
@@ -1,25 +0,0 @@
|
||||
package com.x8bit.bitwarden.ui.platform.components.segment.color
|
||||
|
||||
import androidx.compose.material3.SegmentedButtonColors
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.bitwarden.ui.platform.theme.BitwardenTheme
|
||||
|
||||
/**
|
||||
* Provides a default set of Bitwarden-styled colors for segmented buttons.
|
||||
*/
|
||||
@Composable
|
||||
fun bitwardenSegmentedButtonColors(): SegmentedButtonColors = SegmentedButtonColors(
|
||||
activeContainerColor = BitwardenTheme.colorScheme.filledButton.backgroundReversed,
|
||||
activeContentColor = BitwardenTheme.colorScheme.filledButton.foregroundReversed,
|
||||
activeBorderColor = Color.Transparent,
|
||||
inactiveContainerColor = BitwardenTheme.colorScheme.background.primary,
|
||||
inactiveContentColor = BitwardenTheme.colorScheme.text.secondary,
|
||||
inactiveBorderColor = Color.Transparent,
|
||||
disabledActiveContainerColor = BitwardenTheme.colorScheme.background.primary,
|
||||
disabledActiveContentColor = BitwardenTheme.colorScheme.filledButton.foregroundDisabled,
|
||||
disabledActiveBorderColor = Color.Transparent,
|
||||
disabledInactiveContainerColor = BitwardenTheme.colorScheme.background.primary,
|
||||
disabledInactiveContentColor = BitwardenTheme.colorScheme.stroke.divider,
|
||||
disabledInactiveBorderColor = Color.Transparent,
|
||||
)
|
||||
@@ -56,6 +56,9 @@ import com.bitwarden.ui.platform.components.field.model.TextToolbarType
|
||||
import com.bitwarden.ui.platform.components.model.CardStyle
|
||||
import com.bitwarden.ui.platform.components.model.TooltipData
|
||||
import com.bitwarden.ui.platform.components.model.TopAppBarDividerStyle
|
||||
import com.bitwarden.ui.platform.components.segment.BitwardenSegmentedButton
|
||||
import com.bitwarden.ui.platform.components.segment.SegmentedButtonOptionContent
|
||||
import com.bitwarden.ui.platform.components.segment.SegmentedButtonState
|
||||
import com.bitwarden.ui.platform.components.slider.BitwardenSlider
|
||||
import com.bitwarden.ui.platform.components.snackbar.BitwardenSnackbarData
|
||||
import com.bitwarden.ui.platform.components.snackbar.BitwardenSnackbarHost
|
||||
@@ -78,9 +81,6 @@ import com.x8bit.bitwarden.ui.platform.components.coachmark.model.CoachMarkHighl
|
||||
import com.x8bit.bitwarden.ui.platform.components.coachmark.rememberLazyListCoachMarkState
|
||||
import com.x8bit.bitwarden.ui.platform.components.dropdown.BitwardenMultiSelectButton
|
||||
import com.x8bit.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
|
||||
import com.x8bit.bitwarden.ui.platform.components.segment.BitwardenSegmentedButton
|
||||
import com.x8bit.bitwarden.ui.platform.components.segment.SegmentedButtonOptionContent
|
||||
import com.x8bit.bitwarden.ui.platform.components.segment.SegmentedButtonState
|
||||
import com.x8bit.bitwarden.ui.platform.composition.LocalAppResumeStateManager
|
||||
import com.x8bit.bitwarden.ui.platform.composition.LocalIntentManager
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
|
||||
|
||||
Reference in New Issue
Block a user