Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package app.plugbrain.android.ui.designsystem.components.button
package app.plugbrain.android.ui.designsystem.components.sheetdrawer

import android.content.res.Configuration
import androidx.compose.foundation.layout.Arrangement
Expand Down Expand Up @@ -32,6 +32,8 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import app.plugbrain.android.R
import app.plugbrain.android.ui.designsystem.components.button.PlugButtonPrimary
import app.plugbrain.android.ui.designsystem.components.button.PlugButtonSecondary
import app.plugbrain.android.ui.theme.MathlockAppTheme

@OptIn(ExperimentalMaterial3Api::class)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,32 @@
package app.plugbrain.android.ui.designsystem.components.button
package app.plugbrain.android.ui.designsystem.components.textfield

import android.content.res.Configuration
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.focusable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.OutlinedTextFieldDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
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.shadow
import androidx.compose.ui.focus.FocusRequester
Expand All @@ -33,8 +36,9 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import app.plugbrain.android.ui.designsystem.components.button.PlugNumericalInputDefaults.ElevationFocused
import app.plugbrain.android.ui.designsystem.components.button.PlugNumericalInputDefaults.Shape
import app.plugbrain.android.ui.designsystem.components.textfield.PlugNumericalInputDefaults.ElevationFeedback
import app.plugbrain.android.ui.designsystem.components.textfield.PlugNumericalInputDefaults.ElevationFocused
import app.plugbrain.android.ui.designsystem.components.textfield.PlugNumericalInputDefaults.Shape
import app.plugbrain.android.ui.theme.MathlockAppTheme

@Composable
Expand Down Expand Up @@ -66,10 +70,16 @@ fun PlugNumericalInput(
val interactionSource = remember { MutableInteractionSource() }
val isFocused by interactionSource.collectIsFocusedAsState()
val elevation by animateDpAsState(
if (isFocused) ElevationFocused else 0.dp,
when {
isFocused -> ElevationFocused
isSuccess -> ElevationFeedback
isError -> ElevationFeedback
else -> 0.dp
},
label = "anim_elevation",
)
OutlinedTextField(

BasicTextField(
value = value,
onValueChange = onValueChange,
enabled = enabled,
Expand All @@ -83,30 +93,9 @@ fun PlugNumericalInput(
),
textStyle = MaterialTheme.typography.labelLarge.copy(
textAlign = TextAlign.Center,
color = focusTextColor,
),
singleLine = true,
placeholder = {
Text(
text = placeholder,
style = MaterialTheme.typography.labelLarge,
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
)
},
colors = OutlinedTextFieldDefaults.colors(
focusedContainerColor = MaterialTheme.colorScheme.surfaceVariant,
unfocusedContainerColor = MaterialTheme.colorScheme.surfaceVariant,
focusedTextColor = focusTextColor,
unfocusedTextColor = focusTextColor,
focusedPlaceholderColor = MaterialTheme.colorScheme.onSurfaceVariant,
unfocusedPlaceholderColor = MaterialTheme.colorScheme.onSurfaceVariant,
focusedBorderColor = focusBorderColor,
unfocusedBorderColor = unfocusBorderColor,
),
shape = Shape,
trailingIcon = {
PlugNumericalInputIcon(isSuccess = isSuccess, isError = isError)
},
modifier = modifier.then(
if (isFocused || isSuccess || isError) {
Modifier.shadow(
Expand All @@ -119,12 +108,50 @@ fun PlugNumericalInput(
Modifier
},
),
decorationBox = { innerTextField ->
Box(
modifier = Modifier
.fillMaxWidth()
.background(
color = MaterialTheme.colorScheme.surfaceVariant,
shape = Shape,
)
.border(
width = 1.dp,
color = if (isFocused) focusBorderColor else unfocusBorderColor,
shape = Shape,
)
.padding(horizontal = 16.dp, vertical = 15.dp),
contentAlignment = Alignment.Center,
) {
if (value.isEmpty()) {
Text(
text = placeholder,
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant,
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth(),
)
}
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
) {
Box(modifier = Modifier.weight(1f), contentAlignment = Alignment.Center) { innerTextField() }
PlugNumericalInputIcon(
isSuccess = isSuccess,
isError = isError,
)
}
}
},
)
}

private object PlugNumericalInputDefaults {
val Shape = RoundedCornerShape(50)
val ElevationFocused = 12.dp
val ElevationFeedback = 6.dp
}

@Composable
Expand All @@ -143,6 +170,7 @@ private fun PlugNumericalInputIcon(
tint = MaterialTheme.colorScheme.error,
contentDescription = "Input invalid",
)
else -> null
}
}

Expand All @@ -151,6 +179,11 @@ private fun PlugNumericalInputIcon(
showBackground = true,
uiMode = Configuration.UI_MODE_NIGHT_NO,
)
@Preview(
name = "Font Scale",
showBackground = true,
fontScale = 2f,
)
@Preview(
name = "Dark Mode",
showBackground = true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
Expand All @@ -25,7 +21,7 @@ import androidx.compose.ui.unit.dp
import app.cash.paparazzi.DeviceConfig
import app.cash.paparazzi.Paparazzi
import app.plugbrain.android.R
import app.plugbrain.android.ui.designsystem.components.button.PlugBottomSheetDrawer
import app.plugbrain.android.ui.designsystem.components.sheetdrawer.PlugBottomSheetDrawer
import app.plugbrain.android.ui.theme.MathlockAppTheme
import org.junit.Rule
import org.junit.Test
Expand Down Expand Up @@ -54,7 +50,6 @@ class PlugBottomSheetScreenshotTest {
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun bottomSheetTest(darkTheme: Boolean = false) {
var showSheet by remember { mutableStateOf(true) }
val sheetState = rememberModalBottomSheetState()

LaunchedEffect(Unit) { sheetState.expand() }
Expand Down Expand Up @@ -87,7 +82,7 @@ class PlugBottomSheetScreenshotTest {
secondaryCtaText = "Stay Focused!",
secondaryCtaAction = { },
secondaryCtaIcon = Icons.Rounded.Check,
onDismiss = { showSheet = false },
onDismiss = { },
sheetState = sheetState,
) {
Text(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package app.plugbrain.android.screenshots

import androidx.compose.foundation.background
import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
Expand All @@ -15,7 +16,7 @@ import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.unit.dp
import app.cash.paparazzi.DeviceConfig
import app.cash.paparazzi.Paparazzi
import app.plugbrain.android.ui.designsystem.components.button.PlugNumericalInput
import app.plugbrain.android.ui.designsystem.components.textfield.PlugNumericalInput
import app.plugbrain.android.ui.theme.MathlockAppTheme
import org.junit.Rule
import org.junit.Test
Expand All @@ -40,64 +41,83 @@ class PlugNumericalInputScreenshotTest {
numericalInputTest(darkTheme = true)
}
}
}

@Composable
private fun numericalInputTest(darkTheme: Boolean = false) {
val focusRequester = remember { FocusRequester() }
class PlugNumericalInputFontScaleScreenshotTest {
@get:Rule
val paparazziBigFontScale =
Paparazzi(
deviceConfig = DeviceConfig.PIXEL_5.copy(fontScale = 2f),
)

LaunchedEffect(Unit) {
focusRequester.requestFocus()
@Test
fun plugNumericalInputBigFontScaleTests() {
paparazziBigFontScale.snapshot {
numericalInputTest()
}
}
}

@Composable
private fun numericalInputTest(darkTheme: Boolean = false) {
val focusRequester = remember { FocusRequester() }

LaunchedEffect(Unit) {
focusRequester.requestFocus()
}

MathlockAppTheme(dynamicColor = false, darkTheme = darkTheme) {
Column(
modifier = Modifier.background(MaterialTheme.colorScheme.surface),
) {
PlugNumericalInput(
value = "",
onValueChange = {},
onSubmit = {},
placeholder = "Unfocused",
modifier =
Modifier
.padding(8.dp)
.fillMaxWidth(),
)
PlugNumericalInput(
value = "Focused",
onValueChange = {},
onSubmit = {},
placeholder = "Focused",
modifier =
Modifier
.focusRequester(focusRequester)
.focusable()
.padding(8.dp)
.fillMaxWidth(),
)
PlugNumericalInput(
value = "Success",
onValueChange = {},
onSubmit = {},
placeholder = "Success",
isSuccess = true,
modifier =
Modifier
.padding(8.dp)
.fillMaxWidth(),
)
PlugNumericalInput(
value = "Error",
onValueChange = {},
onSubmit = {},
placeholder = "Error",
isError = true,
modifier =
Modifier
.padding(8.dp)
.fillMaxWidth(),
)
}
MathlockAppTheme(dynamicColor = false, darkTheme = darkTheme) {
Column(
modifier =
Modifier
.background(MaterialTheme.colorScheme.background)
.padding(32.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
PlugNumericalInput(
value = "",
onValueChange = {},
onSubmit = {},
placeholder = "Unfocused",
modifier =
Modifier
.padding(8.dp)
.fillMaxWidth(),
)
PlugNumericalInput(
value = "Focused",
onValueChange = {},
onSubmit = {},
placeholder = "Focused",
modifier =
Modifier
.focusRequester(focusRequester)
.focusable()
.padding(8.dp)
.fillMaxWidth(),
)
PlugNumericalInput(
value = "Success",
onValueChange = {},
onSubmit = {},
placeholder = "Success",
isSuccess = true,
modifier =
Modifier
.padding(8.dp)
.fillMaxWidth(),
)
PlugNumericalInput(
value = "Error",
onValueChange = {},
onSubmit = {},
placeholder = "Error",
isError = true,
modifier =
Modifier
.padding(8.dp)
.fillMaxWidth(),
)
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading