---
title: Checkbox
description: A checkbox component with full control over the indicator, bounds, and checked animation.
---



```kotlin expandable title="CheckboxDemo.kt" githubUrl="https://github.com/composablehorizons/compose-unstyled/blob/main/demo/src/commonMain/kotlin/com/composeunstyled/demo/checkbox/CheckboxDemo.kt"
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.PathFillType
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.StrokeJoin
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.path
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.composeunstyled.CheckedIndicator
import com.composeunstyled.UnstyledCheckbox
import com.composeunstyled.UnstyledIcon
import com.composeunstyled.demo.borderToken
import com.composeunstyled.demo.colors
import com.composeunstyled.demo.contentToken
import com.composeunstyled.demo.surfaceToken
import com.composeunstyled.theme.Theme

@Preview
@Composable
fun CheckboxDemo() {
  var checked by remember { mutableStateOf(true) }
  Box(
    modifier = Modifier.fillMaxSize(),
    contentAlignment = Alignment.Center,
  ) {
    UnstyledCheckbox(
      checked = checked,
      onCheckedChange = { checked = it },
      modifier = Modifier.clip(RectangleShape),
      accessibilityLabel = "Enable notifications",
      indication = LocalIndication.current,
    ) {
      CheckedIndicator(
        modifier = Modifier
          .size(24.dp)
          .background(Theme[colors][surfaceToken], RectangleShape)
          .border(1.dp, Theme[colors][borderToken], RectangleShape),
        indication = LocalIndication.current,
      ) {
        UnstyledIcon(checkIcon())
      }
    }
  }
}

@Composable
private fun checkIcon(): ImageVector {
  val color = Theme[colors][contentToken]
  return remember(color) {
    ImageVector.Builder(
      name = "Check",
      defaultWidth = 24.dp,
      defaultHeight = 24.dp,
      viewportWidth = 24f,
      viewportHeight = 24f,
    ).apply {
      path(
        fill = null,
        fillAlpha = 1.0f,
        stroke = SolidColor(color),
        strokeAlpha = 1.0f,
        strokeLineWidth = 2f,
        strokeLineCap = StrokeCap.Round,
        strokeLineJoin = StrokeJoin.Round,
        strokeLineMiter = 1.0f,
        pathFillType = PathFillType.NonZero,
      ) {
        moveTo(20f, 6f)
        lineTo(9f, 17f)
        lineToRelative(-5f, -5f)
      }
    }.build()
  }
}
```



## Features

- Custom interaction bounds
- Custom checked indicator
- Animated checked content
- Accessibility label

## Installation

```kotlin
implementation("com.composables:composeunstyled-checkbox:2.10.0")
```

## Anatomy

```kotlin
UnstyledCheckbox(
  checked = checked,
  onCheckedChange = onCheckedChange,
) {
  CheckedIndicator {
  }
}
```

## Concepts

- `UnstyledCheckbox` represents the interactive bounds of the checkbox.
- `CheckedIndicator` represents the visible checked state. It automatically shows and hides its
  content based on the `UnstyledCheckbox` state.
- Give `CheckedIndicator` a fixed size when its content only exists while checked. Without a fixed
  size, the checkbox can change layout size when the indicator appears or disappears.

## Accessibility

Screen readers will automatically read any text placed inside `UnstyledCheckbox`.

Use the `accessibilityLabel` parameter when the checkbox has no visible text label.

## Code Examples

### Making an entire row checkable

Use the `UnstyledCheckbox` component as the row container to make the full row toggleable. This is useful when the label should also toggle the checkbox:

```kotlin expandable
UnstyledCheckbox(
  checked = checked,
  onCheckedChange = { checked = it },
) {
  Row {
    CheckedIndicator {
      BasicText("✓")
    }

    BasicText("Accept all terms")
  }
}
```

### Creating larger checkbox interaction bounds

Use padding on the `CheckedIndicator` component to place the visible checkbox inside a larger
interaction area. This is useful when the ripple or touch target should be larger than the visible
checkbox:

### Animating the checked indicator

Use the `enter` and `exit` parameters on `CheckedIndicator` to animate the checked content.

```kotlin expandable
UnstyledCheckbox(
  checked = checked,
  onCheckedChange = { checked = it },
) {
  CheckedIndicator(
    enter = fadeIn(),
    exit = fadeOut(),
  ) {
    BasicText("Selected")
  }
}
```

### Creating a custom checked indicator animation

Use the `checked` state value to draw your own indicator instead of `CheckedIndicator`. This is useful when your design system needs a custom checkmark animation:

### Labeling an icon-only checkbox

Use the `accessibilityLabel` parameter when the checkbox content has no text:

```kotlin expandable
UnstyledCheckbox(
  checked = checked,
  onCheckedChange = { checked = it },
  accessibilityLabel = "Enable notifications",
) {
  CheckedIndicator {
    BasicText("✓")
  }
}
```

## API Reference

### UnstyledCheckbox

| Parameter | Type | Description |
|-----------|------|-------------|
| `checked` | `Boolean` | Whether the checkbox is checked. |
| `onCheckedChange` | `(Boolean) -> Unit` | Callback when the checked state changes. |
| `modifier` | `Modifier` | Modifier to be applied to the checkbox. |
| `enabled` | `Boolean` |  |
| `interactionSource` | `MutableInteractionSource?` |  |
| `indication` | `Indication?` |  |
| `accessibilityLabel` | `String?` |  |
| `content` | `CheckboxScope.() -> Unit` |  |
### CheckboxScope.CheckedIndicator

| Parameter | Type | Description |
|-----------|------|-------------|
| `modifier` | `Modifier` | Modifier to be applied to the checkbox. |
| `indication` | `Indication?` |  |
| `enter` | `EnterTransition` |  |
| `exit` | `ExitTransition` |  |
| `content` | `AnimatedVisibilityScope.() -> Unit` |  |
