Stacked Bar Chart

Animated inline-SVG stacked bar chart with 2-series support, dynamic labels, auto-scaling Y-axis, value labels, and spline easing animations. 1 control, 11 properties. Renders entirely in a single Image control via data:image/svg+xml.

cmpStackedBarChart.yaml

Import via Components → New component → Import from code → paste YAML

Preview

Mobile / DesktopMobileDesktop0326496128160JanFebMarAprMayJun

Installation

This component requires Modern controls to be enabled. Settings → Updates → Preview → Modern controls and themes

# In Power Apps Studio:
1. Components tab → New component → Import from code
2. Paste the full YAML definition
3. Add the component to any screen
4. Press F5 (Preview) to trigger the entry animation

Usage

Basic stacked chart

// Labels: define x-axis categories
cmpStackedBarChart.Labels = Table(
    { Label: "Jan" }, { Label: "Feb" },
    { Label: "Mar" }
)

// ChartData: one row per label × series combination
cmpStackedBarChart.ChartData = Table(
    { Label: "Jan", Series: "Mobile",  Value: 55 },
    { Label: "Jan", Series: "Desktop", Value: 65 },
    { Label: "Feb", Series: "Mobile",  Value: 65 },
    { Label: "Feb", Series: "Desktop", Value: 55 },
    { Label: "Mar", Series: "Mobile",  Value: 40 },
    { Label: "Mar", Series: "Desktop", Value: 25 }
)

// SeriesConfig: define series names and hex colors
cmpStackedBarChart.SeriesConfig = Table(
    { Series: "Mobile",  Color: "#3B82F6" },
    { Series: "Desktop", Color: "#93C5FD" }
)

cmpStackedBarChart.ChartTitle = "Traffic by Device"

Data from SharePoint / Dataverse

// Shape data into Label + Series + Value rows
cmpStackedBarChart.ChartData =
    ForAll(
        GroupBy(
            Filter(Orders, Year(Date) = 2024),
            "Month", "Channel", "Group"
        ),
        {
            Label:  Text(Month, "mmm"),
            Series: Channel,
            Value:  Sum(Group, Amount)
        }
    )

// Map series to brand colors
cmpStackedBarChart.SeriesConfig = Table(
    { Series: "Online",  Color: "#8B5CF6" },
    { Series: "In-Store", Color: "#D8B4FE" }
)

Dark theme, no animation

cmpStackedBarChart.Theme = "Dark"
cmpStackedBarChart.Animate = false
cmpStackedBarChart.ShowValues = true
cmpStackedBarChart.ShowGrid = true
cmpStackedBarChart.ShowLegend = true
cmpStackedBarChart.ShowTitle = true
cmpStackedBarChart.ChartTitle = "Revenue Breakdown"

Properties

Input

PropertyTypeDefault
ChartData

Table with Label (text), Series (text), and Value (number) columns. One row per label × series.

TableJan–Jun sample
Labels

Table with Label column defining x-axis categories. Controls bar count and label text.

TableJan–Jun
SeriesConfig

Table mapping each Series name to a hex Color. First row = bottom stack, second = top.

TableMobile #3B82F6, Desktop #93C5FD
ChartTitle

Title text rendered at the top-left of the SVG.

Text"Mobile / Desktop"
Theme

"Light" or "Dark". Controls background, axis, grid, and label colors.

Text"Light"
ShowGrid

Show horizontal grid lines. Y-axis labels always render regardless of this setting.

Booleantrue
ShowLegend

Show color swatches with series names at top-right.

Booleantrue
ShowTitle

Show the ChartTitle text.

Booleantrue
ShowValues

Show stacked total above each bar.

Booleanfalse
Animate

Enable bar grow-up animation with staggered delays.

Booleantrue
AnimationDuration

Duration of each bar’s animation in seconds.

Number0.8

No output properties or events — the component is purely visual (SVG rendering). 11 input properties total.

Implementation Details

Single-control SVG rendering

The entire chart is a single Image control whose Image property generates a data:image/svg+xml URI. No additional dependencies — works anywhere Power Apps renders images, including galleries and PDF exports.

Dynamic labels via Labels property

The Labels property defines x-axis categories. Pass 4 quarters, 6 months, or 12 departments — bars auto-space via gap = pw / CountRows(labels). Bar width adapts to label count: wider for ≤4 items (0.55 ratio), narrower for 9+ (0.42). The component iterates with Sequence(nLbl) and joins via LookUp(Data, Label = currentLabel && Series = serName)— labels without data render as zero-height bars.

Auto-scaling Y-axis

Y-axis max is calculated dynamically: RoundUp(Max(Data, Value) × 2.2 / 20) × 20. This rounds to clean grid intervals with ~15% headroom. The grid divides into 5 intervals with labels always visible, even when ShowGrid = false (only the baseline renders).

2-series stacking

Supports exactly 2 series from SeriesConfig. Series 1 (Index 1) renders as the bottom bar, series 2 (Index 2) stacks on top. Y positions: series 1 at bY - h1, series 2 at bY - h1 - h2. The top segment has rx='3' for rounded caps.

Animation system

When Animate = true, bars use SVG <animate> elements with spline easing (keySplines='0.4 0 0.2 1'). Bars stagger at (barIndex - 1) × 0.06s. When Animate = false, bars render at their final position with no animation elements.

Limitations

Exactly 2 series (adding a third requires modifying the formula). No interactive tooltips (inline SVG in Image controls doesn't support hover events). Empty state renders a centered “No data” message when Labels or ChartData are empty.

Examples

Default: Mobile vs Desktop traffic

Mobile / DesktopMobileDesktop0326496128160JanFebMarAprMayJun
// Default YAML sample data
cmpStackedBarChart.ChartData = Table(
    {Label:"Jan",Series:"Mobile",Value:55},
    {Label:"Jan",Series:"Desktop",Value:65},
    {Label:"Feb",Series:"Mobile",Value:65},
    {Label:"Feb",Series:"Desktop",Value:65},
    ...
)
cmpStackedBarChart.SeriesConfig = Table(
    {Series:"Mobile",  Color:"#3B82F6"},
    {Series:"Desktop", Color:"#93C5FD"}
)
cmpStackedBarChart.ChartTitle = "Mobile / Desktop"
cmpStackedBarChart.Animate = true

Dark theme, custom colors

Revenue vs CostsRevenueCosts04080120160200Jan125Feb110Mar140Apr110
cmpStackedBarChart.Theme = "Dark"
cmpStackedBarChart.ShowValues = true
cmpStackedBarChart.Labels = Table(
    {Label:"Jan"},{Label:"Feb"},
    {Label:"Mar"},{Label:"Apr"}
)
cmpStackedBarChart.SeriesConfig = Table(
    {Series:"Revenue", Color:"#22C55E"},
    {Series:"Costs",   Color:"#4ADE80"}
)
cmpStackedBarChart.ChartTitle = "Revenue vs Costs"

Minimal: no title, legend, or grid

0326496128160JanFebMar
// Minimal sparkline-style
cmpStackedBarChart.ShowTitle = false
cmpStackedBarChart.ShowLegend = false
cmpStackedBarChart.ShowGrid = false
cmpStackedBarChart.Animate = false

cmpStackedBarChart.SeriesConfig = Table(
    {Series:"Mobile",  Color:"#8B5CF6"},
    {Series:"Desktop", Color:"#C4B5FD"}
)

Data Schema

ChartData record

FieldTypeNotes
LabelTextCategory label. Must match a row in the Labels property.
SeriesTextSeries name. Must match a row in SeriesConfig.
ValueNumberNumeric value. Y-axis auto-scales to the data range.

Labels record

FieldTypeNotes
LabelTextCategory name displayed on x-axis. Controls bar count and ordering.

SeriesConfig record

FieldTypeNotes
SeriesTextSeries name matching ChartData rows.
ColorTextHex color string (e.g. "#3B82F6"). Used for bars and legend swatches.

Architecture

1 control — a single Image control rendering an inline SVG via EncodeUrl().

11 properties — all input. No output properties or events.

Default size — App.Width × 400px. SVG viewBox is 700 × 320 with 50px padding.

cmpStackedBarChart (App.Width × 400, Fill: transparent)
└── imgStackedBarChart (Image control)
    └── Image = "data:image/svg+xml," & EncodeUrl(svg)

    SVG structure (viewBox 700×320, padding 50):
    ├── <text> ChartTitle (top-left, conditional on ShowTitle)
    ├── <g> Legend (top-right, conditional on ShowLegend)
    │   ├── <rect rx=3> + <text> Series 1 swatch
    │   └── <rect rx=3> + <text> Series 2 swatch
    ├── Y-axis labels × 6 (always visible, auto-scaled)
    ├── Grid lines × 6 (conditional on ShowGrid, baseline always)
    └── For each label in Labels property:
        ├── <text> X-axis label
        ├── <rect> Series 1 bar (bottom, with <animate> if enabled)
        ├── <rect rx=3> Series 2 bar (stacked on top)
        └── <text> Value label (conditional on ShowValues)