DecoratedButton done

This commit is contained in:
Nymos 2025-02-18 19:38:28 +03:00
parent 35eb1c5b5e
commit eccc58782a
5 changed files with 167 additions and 3 deletions

View File

@ -5,6 +5,9 @@
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
<SelectionState runConfigName="presentation">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
</selectionStates>
</component>
</project>

5
.idea/gradle.xml generated
View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
@ -9,7 +10,9 @@
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/data" />
<option value="$PROJECT_DIR$/domain" />
<option value="$PROJECT_DIR$/presentation" />
</set>
</option>
<option name="resolveExternalAnnotations" value="false" />

View File

@ -0,0 +1,148 @@
package com.nto.presentation.composable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonColors
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.nto.presentation.composable.DecoratedButtonType.Default
import com.nto.presentation.composable.DecoratedButtonType.Disabled
import com.nto.presentation.theme.NTOTheme
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
enum class DecoratedButtonType {
Default, Disabled
}
object DecoratedButtonValues {
private val DefaultColors: ButtonColors
@Composable get() = ButtonColors(
contentColor = NTOTheme.colors.primaryBackground,
containerColor = NTOTheme.colors.button,
disabledContentColor = Color.Unspecified,
disabledContainerColor = Color.Unspecified
)
private val DisabledColors: ButtonColors
@Composable get() = ButtonColors(
contentColor = NTOTheme.colors.primaryBackground,
containerColor = NTOTheme.colors.buttonDisabled,
disabledContentColor = Color.Unspecified,
disabledContainerColor = Color.Unspecified
)
@Composable
fun getDefaultColor(type: DecoratedButtonType): ButtonColors {
return when (type) {
Default -> DefaultColors
Disabled -> DisabledColors
}
}
}
/**
* High level element that utilizes [DecoratedButtonType] to obtain [DecoratedButtonValues] and use it's colors accordingly.
*
* Consists of a button with a text inside it. By fact that's just a wrapper to simplify reusing process.
*
* @param text text to display inside a button.
* @param isDisabled mutable variable that represents button state. Should be in viewmodel or screen state. After being converted to the instance of [DecoratedButtonType] that is used to obtain [ButtonColors] inside [DecoratedButtonValues].
* @param modifier modifier that should contain [Modifier.height] and [Modifier.width] or other size definition to work correctly.
* @param shape element will be clipped to that shape.
* @param onClick function to be invoked on button click.
*
* @sample [DecoratedButtonSample]
*
*/
@Composable
fun DecoratedButton(
text: String,
isDisabled: Boolean,
modifier: Modifier = Modifier,
shape: Shape = RoundedCornerShape(10.dp),
onClick: () -> Unit,
) {
NTOTheme {
Button(
modifier = modifier, shape = shape, colors = DecoratedButtonValues.getDefaultColor(
when (isDisabled) {
true -> Disabled
false -> Default
}
), onClick = onClick
) {
Text(
text,
style = NTOTheme.typography.displaySmall,
color = NTOTheme.colors.secondaryText
)
}
}
}
@Stable
internal class DecoratedButtonSample {
class SampleViewModel {
private val _state = MutableStateFlow(SampleState())
val state: StateFlow<SampleState>
get() = _state.asStateFlow()
fun setDisabledState(data: Boolean) {
_state.value = _state.value.copy(data = data)
}
}
data class SampleState(
var data: Boolean = false
)
@Preview
@Composable
private fun InputFieldPreview() {
NTOTheme {
val sampleViewModel = SampleViewModel()
val state = sampleViewModel.state.collectAsState()
Column(modifier = Modifier.fillMaxSize()) {
//Filled button preset
DecoratedButton(
text = "Get Started",
isDisabled = state.value.data,
modifier = Modifier
.height(60.dp)
.width(300.dp),
shape = RoundedCornerShape(10.dp)
) {
//...
}
//Disabled button preset
Spacer(modifier = Modifier.height(10.dp))
DecoratedButton(
text = "Get Started",
isDisabled = !state.value.data,
modifier = Modifier
.height(60.dp)
.width(300.dp),
shape = RoundedCornerShape(10.dp)
) {
//...
}
}
}
}
}

View File

@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@ -29,6 +30,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import com.nto.presentation.R
import com.nto.presentation.composable.DecoratedButton
import com.nto.presentation.composable.InputField
import com.nto.presentation.composable.InputFieldOptions
import com.nto.presentation.theme.NTOTheme
@ -114,7 +116,15 @@ fun LoginScreen(
)
}
Spacer(Modifier.height(50.dp))
//TODO: LoginButton
DecoratedButton(
stringResource(R.string.action_login),
state.disabled,
modifier = Modifier
.width(364.dp)
.height(60.dp)
) {
viewModel.login(navController)
}
}
}
}

View File

@ -1,6 +1,6 @@
<resources>
<string name="app_name">presentation</string>
<string name="login_button">Войти</string>
<string name="action_login">Войти</string>
<string name="text_email">Почта</string>
<string name="text_password">Пароль</string>
<string name="greeting_login_description">Войдите в свой аккаунт чтобы продолжить</string>