Skip to content

Yakcov

Yet Another Kotlin COmpose Validation library.

Yakcov makes TextField (and any other input) validation painless in Compose Multiplatform. Validators are backed by Compose snapshot state, so your UI reacts automatically; validation outcomes are severity-ranked (ERROR, WARNING, INFO, SUCCESS); and the same rules run on Android, JVM, JS, Wasm, and iOS.

These docs can't lie

Every code block on this site is pulled from the docs-examples module, which compiles in CI against the current library API. If an example here stopped working, the build would fail before the docs could ship.

Install

Yakcov publishes all targets to Maven Central — add the common artifact and Gradle resolves the right target per platform:

commonMain {
    dependencies {
        implementation("com.chrisjenx.yakcov:library:${version}")
    }
}

Yakcov in 30 seconds

@Composable
fun BasicSignUpScreen(onSubmit: (email: String, password: String) -> Unit) {
    // No state holder: the validators live in the composable, remembered across
    // recompositions. Each one owns its TextFieldValue draft + validation state.
    val email = rememberTextFieldValueValidator(rules = listOf(Required, Email))
    val password = rememberTextFieldValueValidator(rules = listOf(Required, MinLength(8)))

    Column {
        with(email) {
            OutlinedTextField(
                value = value,
                onValueChange = ::onValueChange,
                label = { Text("Email") },
                isError = isError(),
                supportingText = supportingText(),
                singleLine = true,
                modifier = Modifier
                    .fillMaxWidth()
                    // Show errors when focus leaves the field; shake on invalid submit.
                    .validationConfig(validateOnFocusLost = true, shakeOnInvalid = true),
            )
        }
        with(password) {
            OutlinedTextField(
                value = value,
                onValueChange = ::onValueChange,
                label = { Text("Password") },
                isError = isError(),
                supportingText = supportingText(),
                singleLine = true,
                modifier = Modifier
                    .fillMaxWidth()
                    .validationConfig(validateOnFocusLost = true, shakeOnInvalid = true),
            )
        }
        Button(
            onClick = {
                // Form-level validate(): surfaces errors on every field, true when all pass.
                if (listOf(email, password).validate()) {
                    onSubmit(email.value.text, password.value.text)
                }
            },
            modifier = Modifier.fillMaxWidth(),
        ) { Text("Create account") }
    }
}

Where next