Jetpack Compose gives you great flexibility in creating UI components, and the Slider is no exception. While the default slider is quite functional, sometimes design specifications require a more visually tailored experience, such as a thicker track, a custom-colored thumb, or unique active and inactive colors.

In this article, we’ll break down a custom slider implementation in Jetpack Compose that meets these design needs.

Basic Idea

We're building a custom horizontal slider with.

Code Overview

Here's the complete code snippet.

Slider(
    value = state.sittingPercentage,
    onValueChange = viewModel::onSittingPercentageChange,
    valueRange = 0f..100f,
    modifier = Modifier
        .fillMaxWidth()
        .height(32.dp),
    colors = SliderDefaults.colors(
        thumbColor = ButtonCommonGreenColor,
        activeTrackColor = ButtonCommonGreenColor,
        inactiveTrackColor = ButtonCommonGreenColor.copy(alpha = 0.3f)
    ),
    track = { sliderPositions ->
        SliderDefaults.Track(
            sliderState = sliderPositions,
            colors = SliderDefaults.colors(
                activeTrackColor = ButtonCommonGreenColor,
                inactiveTrackColor = Color.DarkGray
            ),
            modifier = Modifier.height(8.dp),
            thumbTrackGapSize = 0.dp,
            drawStopIndicator = { null }
        )
    },
    thumb = {
        Box(
            modifier = Modifier
                .size(16.dp)
                .background(White, shape = CircleShape)
        )
    }
)

Explanation of Each Part

value and onValueChange

These handle the current value of the slider and update the view model when the user interacts with it.

value = state.sittingPercentage,
onValueChange = viewModel::onSittingPercentageChange,

valueRange = 0f..100f

Limits the slider between 0 and 100. Perfect for percentage-based values.

Colors (Top-Level)

colors = SliderDefaults.colors(
    thumbColor = ButtonCommonGreenColor,
    activeTrackColor = ButtonCommonGreenColor,
    inactiveTrackColor = ButtonCommonGreenColor.copy(alpha = 0.3f)
)

This creates a consistent green look across all parts, with the inactive segment being a faded version.

Track

track = { sliderPositions ->
    SliderDefaults.Track(
        sliderState = sliderPositions,
        colors = SliderDefaults.colors(
            activeTrackColor = ButtonCommonGreenColor,
            inactiveTrackColor = Color.DarkGray
        ),
        modifier = Modifier.height(8.dp),
        thumbTrackGapSize = 0.dp,
        drawStopIndicator = { null }
    )
}

Thumb

thumb = {
    Box(
        modifier = Modifier
            .size(16.dp)
            .background(White, shape = CircleShape)
    )
}

This makes the thumb visually distinct from the track, giving a polished, tactile appearance.

Output

Output

When Should You Use This?

This custom slider approach is practical when.

Final Thoughts

Jetpack Compose makes customizing sliders seamless. With a few tweaks, you can build a slider that feels both elegant and functional, like the one above, clean, consistent, and user-friendly.