-
Notifications
You must be signed in to change notification settings - Fork 1
Textfield, OutlinedTextField 구현 #29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 7 commits
e98f309
ee30409
aecec9f
f60d87a
92d48b5
2f7624d
794b368
c2bf0e9
7c0450c
85ed1da
7f92bbe
f857cee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| 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.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 { androidx.compose.runtime.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, | ||
| ) | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| 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.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 { androidx.compose.runtime.mutableStateOf("") } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이거도요 |
||
| 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 | ||
| ) | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -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)) | ||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기두 |
||||||||||||||
| .padding(start = 16.dp, end = 12.dp, top = 12.dp, bottom = 12.dp) | ||||||||||||||
| ) { | ||||||||||||||
|
Comment on lines
+48
to
+56
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Surface를 사용하면 간단하게 될 것 같아요! |
||||||||||||||
| 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, | ||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
| contentDescription = null, | ||||||||||||||
| tint = HandyTheme.colors.iconBasicTertiary, | ||||||||||||||
| modifier = Modifier | ||||||||||||||
| .clickable( | ||||||||||||||
| indication = null, | ||||||||||||||
| interactionSource = interactionSource, | ||||||||||||||
| onClick = onClickTrailingIcon | ||||||||||||||
| ) | ||||||||||||||
| .padding(start = 12.dp) | ||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. padding보다는 Spacer가 명시적이어서 나을 것 같긴 한데 어떻게 생각하시나요?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 좋은 것 같아요! 위에 it도 그렇고 이부분도 가이드로 통일하면 좋을 것 같아 다른 컴포넌트들도 반영해볼게요~ |
||||||||||||||
| ) | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| 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 { | ||||||||||||||
|
Comment on lines
+105
to
+114
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
이 함수는 외부에서 사용될 함수가 아니라면 internal이나 private로 해주시면 좋을 것 같습니다.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 접근 지정자를 빼먹었던 것 같아요! 반영했습니다~ |
||||||||||||||
| 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 | ||||||||||||||
| ) | ||||||||||||||
| } | ||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 그러면 TextArea는 별도의 PR로 올려주시고 여기서는 제외하는 게 좋을 것 같습니다! |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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, | ||
| ) | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
|
Comment on lines
+12
to
+14
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 한 줄 띄워주세요~! |
||
| 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, | ||
| ) | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
요거만 임포트해서 줄여주시면 좋을거 같습니다