charty

StackedHorizontalBarChart#

Best for showing cumulative part-to-whole composition across categories in a horizontal layout.

StackedHorizontalBarChart

Kotlin
StackedHorizontalBarChart(    data = {        listOf(            BarGroup(label = "Product A", values = listOf(30f, 50f, 20f)),            BarGroup(label = "Product B", values = listOf(60f, 25f, 45f)),        )    },    modifier = Modifier.fillMaxWidth().height(200.dp),    colors = ChartyColor.Solid(Color(0xFF00897B)),    config = StackedHorizontalBarChartConfig(        barWidthFraction = 0.6f,        rightCornerRadius = CornerRadius.Medium,        animation = Animation.Default,    ),    onSegmentClick = { segment -> println("Tapped ${segment.barGroup.label} segment ${segment.segmentIndex}") },)

Every group must have at least one value, and all values must be non-negative — the chart throws an IllegalArgumentException otherwise.

Unlike NormalizedHorizontalBarChart, rows here keep their real lengths: a row with a larger total is visibly longer.

Click data: StackedHorizontalBarSegment(barGroup, segmentIndex, segmentValue)

Corner radius#

Kotlin
config = StackedHorizontalBarChartConfig(rightCornerRadius = CornerRadius.Custom(radius = 10f))

Rounds the trailing (rightmost) corners of the last segment. None, Small, Medium, Large, ExtraLarge, or Custom(radius).

Rolling window#

Kotlin
config = StackedHorizontalBarChartConfig(visibleWindow = 10, animation = Animation.Fast)

Keeps only the last N rows on screen; null or at least 2.

Persistent markers#

Kotlin
config = StackedHorizontalBarChartConfig(    visibleWindow = 10,    markers = listOf(PersistentMarker(dataIndex = -1, label = "Newest")),)

A negative dataIndex counts back from the end of the drawn data, so -1 marks the newest row.

Animating value changes#

Kotlin
config = StackedHorizontalBarChartConfig(animateValueChanges = true, animation = Animation.Fast)

Tooltip#

Kotlin
StackedHorizontalBarChart(    data = { groups },    modifier = Modifier.fillMaxWidth().height(200.dp),    colors = ChartyColors.DefaultGradient,    tooltip = ChartTooltip.canvas(),    config = StackedHorizontalBarChartConfig(        tooltipFormatter = { segment -> "${segment.barGroup.label}: ${segment.segmentValue}" },    ),)

Accessibility#

A generated stacked-bar summary plus one focusable node per row, laid out top-to-bottom.

Kotlin
interactionConfig = ChartInteractionConfig(accessibilityDescription = "Revenue composition per product")

StackedHorizontalBarChartConfig#

PropertyTypeDefaultDescription
barWidthFractionFloat0.6fRow thickness as a fraction of its slot; 0f..1f
barSpacingFloat0fExtra gap between rows; non-negative
rightCornerRadiusCornerRadiusCornerRadius.MediumRounds the trailing corners of the last segment
animationAnimationAnimation.DefaultGrow-from-left entry animation
animateValueChangesBooleanfalseTween segment values on data change
referenceLineReferenceLineConfig?nullOptional vertical guide line at a fixed value
markersList<PersistentMarker>emptyList()Persistent pinned labels
tooltipConfigTooltipConfig?null (the theme's)Canvas tooltip appearance
tooltipPositionTooltipPositionAUTOABOVE, BELOW, or AUTO
tooltipFormatter(StackedHorizontalBarSegment) -> String"label [i]: value"Tooltip text
visibleWindowInt?nullRolling "show last N" window; null or >= 2

Limitations#