Skip to content

InputView

The ColorOS "card input": a white card (12dp corners) holding an optional 16sp medium title and a bare, undecorated text field, with the counter / clear / password buttons at the end of the field and a 10sp error caption below the card. Mirrors COUICardSingleInputView (single line) and COUICardMultiInputView (multi line, counter at the bottom-end corner of the card). The error caption fades in over 217ms / out over 283ms with the COUI ease curve, and the field plays the COUI error shake while it is shown.

Import

kotlin
import io.github.suqi8.coui.kmp.basic.InputView
import io.github.suqi8.coui.kmp.basic.InputViewDefaults

Basic Usage

kotlin
var nickname by remember { mutableStateOf("") }

InputView(
    value = nickname,
    onValueChange = { nickname = it },
    title = "Nickname",
    label = "Enter your nickname",
    showCount = true,
    maxCount = 10,
    showClearButton = true,
    errorMessage = if (nickname.contains(' ')) "Nickname cannot contain spaces" else "",
)

Multi-line Card

Set singleLine = false for the COUICardMultiInputView form: the counter moves to the bottom-end corner of the card (12sp) and animates to the error color when the limit is hit:

kotlin
var signature by remember { mutableStateOf("") }

InputView(
    value = signature,
    onValueChange = { signature = it },
    label = "Signature",
    showCount = true,
    maxCount = 100,
    singleLine = false,
)

Component States

Disabled State

kotlin
InputView(
    value = "Read only value",
    onValueChange = {},
    title = "Nickname",
    enabled = false,
)

Properties

InputView

PropertyTypeDescriptionDefault ValueRequired
valueStringText value of the input field-Yes
onValueChange(String) -> UnitCallback when text changes-Yes
modifierModifierModifier applied to the componentModifierNo
titleStringTitle inside the card, hidden when empty""No
labelStringLabel (hint) of the inner field""No
enabledBooleanWhether the component is enabledtrueNo
readOnlyBooleanWhether the field is read-onlyfalseNo
showCountBooleanShow the "length/max" counter (needs maxCount > 0)falseNo
maxCountIntMaximum characters, 0 means unlimited0No
showClearButtonBooleanShow a clear button while focused and not emptyfalseNo
showPasswordToggleBooleanShow the password eye toggle (masks the text)falseNo
errorMessageStringError caption below the card, empty hides it""No
cornerRadiusDpCorner radius of the cardInputViewDefaults.CornerRadiusNo
colorsInputViewColorsColors of card, title, counter and error lineInputViewDefaults.inputViewColors()No
textFieldColorsTextFieldColorsColors of the inner fieldTextFieldDefaults.textFieldColors()No
textStyleTextStyleText style of the input textTextFieldDefaults.textStyle(TextFieldMode.None)No
keyboardOptionsKeyboardOptionsKeyboard optionsKeyboardOptions.DefaultNo
keyboardActionsKeyboardActionsKeyboard actionsKeyboardActions.DefaultNo
singleLineBooleanSingle-line card (true) or multi-line card (false)trueNo
maxLinesIntMaximum linesIf singleLine then 1, else 5No
visualTransformationVisualTransformationVisual transformationVisualTransformation.NoneNo
leadingIcon@Composable (() -> Unit)?Leading iconnullNo
trailingIcon@Composable (() -> Unit)?Trailing icon, placed after the built-in buttonsnullNo
interactionSourceMutableInteractionSource?Interaction sourcenullNo

InputViewDefaults

ConstantTypeDescriptionDefault Value
CornerRadiusDpCorner radius of the card (couiRoundCornerM)12.dp
ContentPaddingDpHorizontal content padding inside the card16.dp
TitlePaddingTopDpTop padding of the title12.dp
TitlePaddingBottomDpBottom padding of the title4.dp
TitleMinHeightDpMinimum height of the title22.dp
FieldPaddingVerticalDpVertical field padding without a title15.dp
FieldPaddingBottomWithTitleDpBottom field padding when a title is shown (top is 0)12.dp
MultiFieldPaddingDpVertical field padding in the multi-line card13.dp
MultiCountSpacingDpGap between the multi-line field and its counter4.dp
MultiCountMarginBottomDpBottom margin of the multi-line counter12.dp
MultiCountFontSizeTextUnitFont size of the multi-line counter12.sp
CountFontSizeTextUnitFont size of the single-line inline counter10.sp
ErrorFontSizeTextUnitFont size of the error caption10.sp
ErrorPaddingTopDpTop padding of the error caption4.dp
MaxLinesIntDefault maximum lines5

titleTextStyle() returns the default title style (16sp, medium weight, COUI couiTextAppearanceHeadline6).

inputViewColors() factory

ParameterTypeDefault
cardColorColorCOUITheme.colorScheme.surfaceContainer
titleColorColorCOUITheme.colorScheme.onSurface
disabledTitleColorColorCOUITheme.colorScheme.disabledOnSurface
countColorColorCOUITheme.colorScheme.onSurfaceVariantActions
errorColorColorCOUITheme.colorScheme.error

Behavior

  • The inner field is fully undecorated (TextFieldMode.None, COUIEditText MODE_BACKGROUND_NO_LINE) — no underline and no border, exactly like the card inputs in ColorOS Settings.
  • When maxCount > 0 the input is hard-limited to that many characters; the counter (if shown) reads length/max and animates to the error color at the limit (250ms, like COUICardMultiInputView).
  • Setting a non-empty errorMessage shows the caption below the card (fade in 217ms / out 283ms, COUI ease 0.33, 0, 0.67, 1) and plays the COUI error shake on the field. The last non-empty message keeps showing during the fade-out.
  • Field paddings mirror COUICardSingleInputView: 15dp top/bottom without a title; 0dp top / 12dp bottom when a title is shown; 13dp in the multi-line card.

Advanced Usage

Password input with validation

kotlin
var password by remember { mutableStateOf("") }

InputView(
    value = password,
    onValueChange = { password = it },
    title = "Password",
    label = "At least 8 characters",
    showPasswordToggle = true,
    errorMessage = if (password.isNotEmpty() && password.length < 8) "Password is too short" else "",
    keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
)

Changelog

Released under the Apache-2.0 License