diff --git a/app/src/main/kotlin/com/yourssu/handy/demo/OutlinedTextFieldPreview.kt b/app/src/main/kotlin/com/yourssu/handy/demo/OutlinedTextFieldPreview.kt new file mode 100644 index 00000000..2ea80384 --- /dev/null +++ b/app/src/main/kotlin/com/yourssu/handy/demo/OutlinedTextFieldPreview.kt @@ -0,0 +1,60 @@ +package com.yourssu.handy.demo + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.yourssu.handy.compose.HandyTheme +import com.yourssu.handy.compose.icons.HandyIcons +import com.yourssu.handy.compose.icons.filled.Cancel +import com.yourssu.handy.compose.textfield.OutlinedTextField + +@Preview +@Composable +fun OutlinedTextFieldPreview() { + HandyTheme { + Column( + modifier = Modifier + .wrapContentSize() + .padding(20.dp), + verticalArrangement = Arrangement.spacedBy(20.dp) + ) { + val (text, onValueChange) = remember { mutableStateOf("") } + OutlinedTextField( + value = text, + placeholder = "placeholder", + trailingIcon = HandyIcons.Filled.Cancel, + onValueChange = onValueChange, + ) + + OutlinedTextField( + value = text, + placeholder = "placeholder", + trailingIcon = HandyIcons.Filled.Cancel, + isError = true, + onValueChange = onValueChange, + ) + + OutlinedTextField( + value = text, + placeholder = "placeholder", + trailingIcon = HandyIcons.Filled.Cancel, + enabled = false, + onValueChange = onValueChange, + ) + + OutlinedTextField( + value = text, + placeholder = "placeholder", + enabled = false, + onValueChange = onValueChange, + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/com/yourssu/handy/demo/TextFieldPreview.kt b/app/src/main/kotlin/com/yourssu/handy/demo/TextFieldPreview.kt new file mode 100644 index 00000000..c78ef2f3 --- /dev/null +++ b/app/src/main/kotlin/com/yourssu/handy/demo/TextFieldPreview.kt @@ -0,0 +1,57 @@ +package com.yourssu.handy.demo + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.yourssu.handy.compose.HandyTheme +import com.yourssu.handy.compose.icons.HandyIcons +import com.yourssu.handy.compose.icons.filled.Cancel +import com.yourssu.handy.compose.textfield.TextField + +@Preview +@Composable +fun TextFieldPreview() { + HandyTheme { + Column( + modifier = Modifier.wrapContentSize().padding(20.dp), + verticalArrangement = Arrangement.spacedBy(20.dp) + ) { + val (text, onValueChange) = remember { mutableStateOf("") } + TextField( + value = text, + textLabel = "Label", + helperText = "Helper Text", + placeholder = "placeholder", + trailingIcon = HandyIcons.Filled.Cancel, + onValueChange = onValueChange + ) + + TextField( + value = text, + textLabel = "Label", + helperText = "Helper Text", + placeholder = "placeholder", + trailingIcon = HandyIcons.Filled.Cancel, + isError = true, + onValueChange = onValueChange + ) + + TextField( + value = text, + textLabel = "Label", + helperText = "Helper Text", + placeholder = "placeholder", + trailingIcon = HandyIcons.Filled.Cancel, + enabled = false, + onValueChange = onValueChange + ) + } + } +} \ No newline at end of file diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/textfield/OutlinedTextField.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/textfield/OutlinedTextField.kt new file mode 100644 index 00000000..b99648eb --- /dev/null +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/textfield/OutlinedTextField.kt @@ -0,0 +1,126 @@ +package com.yourssu.handy.compose.textfield + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.interaction.collectIsFocusedAsState +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.KeyboardOptions +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.unit.dp +import com.yourssu.handy.compose.HandyTheme +import com.yourssu.handy.compose.Icon +import com.yourssu.handy.compose.Text +import com.yourssu.handy.compose.foundation.HandyTypography + +@Composable +fun OutlinedTextField( + value: String, + onValueChange: (String) -> Unit, + modifier: Modifier = Modifier, + placeholder: String? = null, + trailingIcon: ImageVector? = null, + enabled: Boolean = true, + isError: Boolean = false, + isSingleLine: Boolean = true, + onClickTrailingIcon: () -> Unit = {} +) { + val interactionSource = remember { MutableInteractionSource() } + val isFocused = interactionSource.collectIsFocusedAsState().value + + val (borderColor, cursorColor, textColor, placeholderTextColor) = getTextFieldStyle( + enabled, + isError, + isFocused + ) + + Row( + modifier = modifier + .fillMaxWidth() + .clip(RoundedCornerShape(12.dp)) + .background(HandyTheme.colors.bgBasicLight) + .border(1.dp, borderColor, RoundedCornerShape(12.dp)) + .padding(start = 16.dp, end = 12.dp, top = 12.dp, bottom = 12.dp) + ) { + BasicTextField( + value = value, + onValueChange = onValueChange, + modifier = Modifier + .weight(1f) + .fillMaxWidth(), + textStyle = HandyTypography.B1Rg16.toTextStyle().copy(color = textColor), + enabled = enabled, + singleLine = isSingleLine, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text), + interactionSource = interactionSource, + cursorBrush = SolidColor(cursorColor), + decorationBox = { innerTextField -> + if (value.isEmpty() && placeholder != null) { + Text( + text = placeholder, + style = HandyTypography.B1Rg16, + color = placeholderTextColor + ) + } + innerTextField() + } + ) + + trailingIcon?.let { + Icon( + imageVector = trailingIcon, + contentDescription = null, + tint = HandyTheme.colors.iconBasicTertiary, + modifier = Modifier + .clickable( + indication = null, + interactionSource = interactionSource, + onClick = onClickTrailingIcon + ) + .padding(start = 12.dp) + ) + } + } +} + +data class TextFieldStyle( + val borderColor: Color, + val cursorColor: Color, + val textColor: Color, + val placeholderTextColor: Color +) + +@Composable +fun getTextFieldStyle( + enabled: Boolean, + isError: Boolean, + isFocused: Boolean +): TextFieldStyle { + return TextFieldStyle( + borderColor = when { + !enabled -> HandyTheme.colors.bgBasicLight + isError -> HandyTheme.colors.lineStatusNegative + isFocused -> HandyTheme.colors.lineStatusPositive + else -> HandyTheme.colors.bgBasicLight + }, + cursorColor = when { + isError && isFocused -> HandyTheme.colors.lineStatusNegative + isFocused -> HandyTheme.colors.lineStatusPositive + else -> HandyTheme.colors.textBasicPrimary + }, + textColor = if (!enabled) HandyTheme.colors.textBasicDisabled else HandyTheme.colors.textBasicPrimary, + placeholderTextColor = if (!enabled) HandyTheme.colors.textBasicDisabled else HandyTheme.colors.textBasicTertiary + ) +} \ No newline at end of file diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/textfield/TextArea.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/textfield/TextArea.kt new file mode 100644 index 00000000..cc9e2518 --- /dev/null +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/textfield/TextArea.kt @@ -0,0 +1,82 @@ +package com.yourssu.handy.compose.textfield + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.yourssu.handy.compose.HandyTheme +import com.yourssu.handy.compose.Text +import com.yourssu.handy.compose.foundation.HandyTypography + +@Composable +fun TextArea( + value: String, + onValueChange: (String) -> Unit, + modifier: Modifier = Modifier, + placeholder: String? = null, + helperText: String? = null, + maxCharacters: Int = Int.MAX_VALUE, + enabled: Boolean = true, + isError: Boolean = false, +) { + val textHelperColor = when { + isError -> HandyTheme.colors.lineStatusNegative + else -> HandyTheme.colors.textBasicTertiary + } + + Column( + modifier = modifier + ) { + OutlinedTextField( + value = value, + onValueChange = { + onValueChange(it) + }, + placeholder = placeholder, + enabled = enabled, + isError = isError, + isSingleLine = false, + modifier = Modifier + ) + + helperText?.let { + Text( + text = it, + style = HandyTypography.B5Rg12, + color = textHelperColor, + modifier = Modifier.padding(top = 4.dp) + ) + } + } +} + +@Preview +@Composable +fun TextAreaPreview() { + HandyTheme { + Column( + modifier = Modifier.wrapContentSize().padding(20.dp), + verticalArrangement = Arrangement.spacedBy(20.dp) + ) { + val (text, onValueChange) = remember { + androidx.compose.runtime.mutableStateOf( + "inputText inputText asdaasdas inputText inputText asdaasdas inputText inputText asdaasdas" + ) + } + + TextArea( + value = text, + onValueChange = onValueChange, + placeholder = "Placeholder", + helperText = "Helper Text", + maxCharacters = 20, + enabled = true, + ) + } + } +} diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/textfield/TextField.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/textfield/TextField.kt new file mode 100644 index 00000000..f232dd6e --- /dev/null +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/textfield/TextField.kt @@ -0,0 +1,67 @@ +package com.yourssu.handy.compose.textfield + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.unit.dp +import com.yourssu.handy.compose.HandyTheme +import com.yourssu.handy.compose.Text +import com.yourssu.handy.compose.foundation.HandyTypography +@Composable +fun TextField( + value: String, + onValueChange: (String) -> Unit, + modifier: Modifier = Modifier, + textLabel: String? = null, + helperText: String? = null, + placeholder: String? = null, + trailingIcon: ImageVector? = null, + enabled: Boolean = true, + isError: Boolean = false, + isSingleLine: Boolean = true, + onClickTrailingIcon: () -> Unit = {} +) { + + val helperTextColor = when { + isError -> HandyTheme.colors.lineStatusNegative + else -> HandyTheme.colors.textBasicTertiary + } + + Column( + modifier = modifier + ) { + textLabel?.let { + Text( + text = it, + style = HandyTypography.B5Rg12, + color = HandyTheme.colors.textBasicTertiary, + ) + } + + Spacer(modifier = Modifier.height(4.dp)) + + OutlinedTextField( + value = value, + onValueChange = onValueChange, + placeholder = placeholder, + trailingIcon = trailingIcon, + enabled = enabled, + isError = isError, + isSingleLine = isSingleLine, + onClickTrailingIcon = onClickTrailingIcon + ) + + Spacer(modifier = Modifier.height(4.dp)) + + helperText?.let { + Text( + text = it, + style = HandyTypography.B5Rg12, + color = helperTextColor, + ) + } + } +} \ No newline at end of file