Kotlin MIT

charts

🟢 Charts for Jetpack Compose — Multiplatform (Android · iOS · Web · Desktop)

H

HDCharts

Dernière activité 29 sept. 2026
HDCharts/charts

461

étoiles

25

forks

15

issues ouvertes

androidandroid-chartchartchartscompose-multiplatformiosjetpack-composejetpack-compose-chartsjsjvmkotlinlibrary

Ce README est souvent en anglais.

HDCharts logo HDCharts logo

A Kotlin Multiplatform chart library built with Jetpack Compose.

demo-light


📚 Documentation

https://charts.hdcode.dev/

🟢 Production Demo

https://charts.hdcode.dev/demo

✨ Snapshot Demo

https://charts.hdcode.dev/demo/snapshot/

🏀 Playground

https://charts.hdcode.dev/playground

Get Started

Important

To try HDCharts, use the latest snapshot. It is the most capable build, with many new features and bug fixes. Add maven("https://central.sonatype.com/repository/maven-snapshots/") to your repositories to use it.

dependencyResolutionManagement {
    repositories {
        mavenCentral()
    }
}

All chart types

Use the umbrella artifact when you want all chart types with the simplest setup.

commonMain.dependencies {
    implementation("io.github.hdcharts:charts:<version>")
}

Individual chart modules

Use independent modules when you want only specific chart types and smaller dependency footprint.

commonMain.dependencies {
    implementation("io.github.hdcharts:line:<version>")
    implementation("io.github.hdcharts:pie:<version>")
    implementation("io.github.hdcharts:bar:<version>")
    implementation("io.github.hdcharts:histogram:<version>")
    implementation("io.github.hdcharts:stacked-bar:<version>")
    implementation("io.github.hdcharts:stacked-area:<version>")
    implementation("io.github.hdcharts:radar:<version>")
    implementation("io.github.hdcharts:gauge:<version>")
}

BOM

Use BOM for version alignment where Gradle platforms are supported. For KMP commonMain, keep explicit versions as shown above.

dependencies {
    implementation(platform("io.github.hdcharts:bom:<version>"))
    implementation("io.github.hdcharts:line")
    implementation("io.github.hdcharts:pie")
    implementation("io.github.hdcharts:bar")
    implementation("io.github.hdcharts:histogram")
    implementation("io.github.hdcharts:stacked-bar")
    implementation("io.github.hdcharts:stacked-area")
    implementation("io.github.hdcharts:radar")
    implementation("io.github.hdcharts:gauge")
}

Example

@Composable
fun BasicLineChart() {
    val values = listOf(42.0, 38.0, 45.0, 51.0, 47.0, 54.0, 49.0)
    val labels = listOf("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")

    val dataSet = values.toChartData(
        categories = labels,
    )

    LineChart(
        data = dataSet,
        modifier = Modifier
            .fillMaxWidth()
            .height(260.dp),
    )
}

The chart modifier controls its size and placement. Surrounding chrome stays with the consumer:

Card {
    LineChart(
        data = dataSet,
        modifier = Modifier
            .fillMaxWidth()
            .height(260.dp),
    )
}

Basic line chart example

v3 API

Sizing

The chart composable's modifier is the only sizing control. A bounded modifier becomes a rectangular plot; a one-axis bounded modifier derives a square fallback; a fully unbounded modifier falls back to a 200.dp default.

LineChart(
    data = dataSet,
    modifier = Modifier
        .fillMaxWidth()
        .height(260.dp),
)

Surrounding chrome

Background, shadow, shape, and outer spacing are not applied by the chart. Wrap the chart in any Compose surface to add chrome.

Card(modifier = Modifier.padding(16.dp)) {
    LineChart(
        data = dataSet,
        modifier = Modifier.fillMaxWidth().height(260.dp),
    )
}

Content spacing

ChartContainerDefaults.style() returns a ChartContainerStyle with styleTitle and contentPadding. Set contentPadding to change the internal spacing reserved for axes, title, and legend.

LineChart(
    data = dataSet,
    modifier = Modifier.fillMaxWidth().height(260.dp),
    style = LineChartDefaults.style(
        chartContainerStyle = ChartContainerDefaults.style(contentPadding = 8.dp),
    ),
)

Style per chart

Each chart module exposes its own *Defaults.style() factory. Use named arguments to customize only the parts you care about. The example below customizes line color, axis, points, and zoom controls; everything else keeps its default.

LineChart(
    data = dataSet,
    title = "Daily Support Tickets",
    modifier = Modifier.fillMaxWidth().height(260.dp),
    style = LineChartDefaults.style(
        chartContainerStyle = ChartContainerDefaults.style(),
        line = LineVisualStyle(
            color = Color(0xFF1E88E5),
            alpha = 1f,
            colors = emptyList(),
            strokeWidth = 2.dp,
            bezier = true,
        ),
        points = LinePointStyle(color = Color(0xFF1E88E5), size = 4.dp, visible = true),
        axis = LineAxisStyle(
            visible = true,
            color = Color.Gray,
            lineWidth = 1.dp,
            yLabels = AxisLabelStyle(visible = true, color = Color.Gray, size = 12.sp, maxCount = 5),
            xLabels = AxisLabelStyle(visible = true, color = Color.Gray, size = 12.sp, maxCount = 7),
        ),
        zoomControlsVisible = true,
    ),
)

Fixed Y-axis range

By default the Y-axis is derived from the data, which can make small fluctuations look exaggerated when the axis doesn't start at zero. Set range on *Defaults.style() to pin min, max, or both, independently of one another; whichever bound you leave null keeps deriving from the data.

LineChart(
    data = dataSet,
    modifier = Modifier.fillMaxWidth().height(260.dp),
    style = LineChartDefaults.style(
        range = LineChartDefaults.range(min = 0.0, max = 100.0),
    ),
)

BarChart exposes the same range block on BarChartDefaults.style().

Selection

Use rememberChartSelection() to hoist selection. The chart calls back into it; you read selectedIndex to drive external UI such as legends or summary cards.

val selection = rememberChartSelection()
val values = listOf(42.0, 38.0, 45.0, 51.0, 47.0, 54.0, 49.0)

LineChart(
    data = values.toChartData(),
    modifier = Modifier.fillMaxWidth().height(260.dp),
    selection = selection,
)

val selected = values.getOrNull(selection.selectedIndex ?: 0)
Text("Selected: $selected")

Responsive layout

Compose the chart with any layout, including Row, Column, LazyColumn, or BoxWithConstraints. A bounded modifier is always honored; an unbounded one falls back to the documented defaults.

Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
    LineChart(
        data = lineData,
        modifier = Modifier.fillMaxWidth().height(220.dp),
    )
    Spacer(modifier = Modifier.height(16.dp))
    BarChart(
        data = barData,
        modifier = Modifier.fillMaxWidth().height(220.dp),
    )
}

Animation and interaction

animateOnStart controls the initial reveal animation; interactionEnabled disables gestures, selection, and zoom controls together. Disable interaction to embed a chart inside a tappable card without conflicts.

LineChart(
    data = dataSet,
    modifier = Modifier.fillMaxWidth().height(260.dp),
    animateOnStart = true,
    interactionEnabled = false,
)

Contributing

See CONTRIBUTING.md for contribution guidelines.

License

MIT

Projets similaires

A powerful and extensible chart library for Compose Multiplatform.

Kotlinandroidandroid-librarychart
Ppatrykandpatrick
3,2 k étoiles199

Animated & Flexible Practical Charts For Jetpack Compose

Kotlinandroidandroid-chartandroid-charts
Eehsannarmani
917 étoiles74

Simple Android compose charts.

Kotlinandroidchartsjetpack-compose
Ttehras
778 étoiles72