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.
Import via Components → New component → Import from code → paste YAML
Preview
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 animationUsage
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
| Property | Type | Default |
|---|---|---|
ChartDataTable with Label (text), Series (text), and Value (number) columns. One row per label × series. | Table | Jan–Jun sample |
LabelsTable with Label column defining x-axis categories. Controls bar count and label text. | Table | Jan–Jun |
SeriesConfigTable mapping each Series name to a hex Color. First row = bottom stack, second = top. | Table | Mobile #3B82F6, Desktop #93C5FD |
ChartTitleTitle 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" |
ShowGridShow horizontal grid lines. Y-axis labels always render regardless of this setting. | Boolean | true |
ShowLegendShow color swatches with series names at top-right. | Boolean | true |
ShowTitleShow the ChartTitle text. | Boolean | true |
ShowValuesShow stacked total above each bar. | Boolean | false |
AnimateEnable bar grow-up animation with staggered delays. | Boolean | true |
AnimationDurationDuration of each bar’s animation in seconds. | Number | 0.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
// 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 = trueDark theme, custom colors
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
// 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
| Field | Type | Notes |
|---|---|---|
| Label | Text | Category label. Must match a row in the Labels property. |
| Series | Text | Series name. Must match a row in SeriesConfig. |
| Value | Number | Numeric value. Y-axis auto-scales to the data range. |
Labels record
| Field | Type | Notes |
|---|---|---|
| Label | Text | Category name displayed on x-axis. Controls bar count and ordering. |
SeriesConfig record
| Field | Type | Notes |
|---|---|---|
| Series | Text | Series name matching ChartData rows. |
| Color | Text | Hex 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)