KPI Cards

Responsive KPI cards with icons, values, and percentage changes. Auto-adjusts from 1 to 4 columns based on screen size. Three style variants (Standard, Compact, Filled), theme-aware styling. 12 controls, 6 properties.

cmpKPI.yaml

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

Preview

All Assets

118

+14%vs last month

In Use

6

-8%vs last month

Available

111

+12%vs last month

Expiring Soon

1

Warranty expiring in less than 30 days

Installation

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

Copy the YAML component definition and import into Power Apps Studio.

# In Power Apps Studio:
1. Components → New component → Import from code
2. Paste YAML definition
3. Component appears in library
4. Add to screens for KPI display

Properties

Input

PropertyTypeDefault
Data

Table of KPI items. Each row needs Icon, Value, Label, PercentChange, PercentLabel, IconBg, IconColor. Optional: isHidden, ID.

Table4 sample cards
Style

"Standard" (icon top-right, footer), "Compact" (icon left, inline percent), or "Filled" (colored background from IconBg, no icon).

Text"Compact"
StyleConfig

Record with colors, space, radius, type, and heights tokens. Type tokens: value (size/sizeCompact/weight), label (size/weight), body (size/weight).

RecordLight theme tokens
Icons

Table of {Name, SVG} rows. SVG strings use "COLOR" placeholder replaced at runtime by IconColor.

Table6 built-in icons
ColumnsLayout

Record with Mobile, Tablet, Desktop column counts and breakpoint widths.

Record{Mobile:1, Tablet:2, Desktop:4}
AnimationEffect

"Pop" (scale in), "Push" (slide), or "None" (instant).

Text"Pop"

Events

EventDescription
OnCardClickFires when any card is tapped. Receives the full KPI record as ClickedItem (ID, Icon, Value, Label, PercentChange, PercentLabel, IconBg, IconColor).

Implementation Details

Responsive grid system

The component renders a vertical Gallery with WrapCount driven by responsive breakpoints. At runtime, App.Width is compared against ColumnsLayout.MobileBreakpoint (640) and TabletBreakpoint (1024) to select 1, 2, or 4 columns. Gallery template contains a ManualLayout GroupContainer (conKPICard) that holds all card internals.

Icon library

Icons are rendered as inline SVG via an Image control. The Icons table contains raw SVG strings with a “COLOR” placeholder that gets replaced by ThisItem.IconColor at runtime using Substitute(). The encoded SVG is passed as a data URI to the Image property. Custom icons can be added to the Icons table.

Three style variants

Standard

Icon top-right in a 48 px circle. 190 px tall card with value center-left and a footer row showing percent + label.

Best for: Full dashboards, detail views

Compact

Icon left-aligned, value and percent inline on one row. 88 px tall — roughly half the height of Standard.

Best for: Above tables, tight layouts, mobile

Filled

Card background becomes IconBg, all text becomes IconColor, icon circle is hidden, border drops to 0. Same data columns — no extra fields needed.

Best for: Hero rows, landing pages, exec summaries

Dynamic height

Component height is calculated from the visible card count, breakpoint column count, and card height (88px Compact vs 190px Standard/Filled), plus appropriate padding. This prevents clipping when cards wrap to multiple rows on narrower screens.

Examples

Responsive layout — mobile, tablet, desktop

Mobile · 1 col

All Assets

118

In Use

6

Available

111

Expiring Soon

1

Tablet · 2 col

All Assets

118

+14%

In Use

6

-8%

Available

111

+12%

Expiring Soon

1

Desktop · 4 col

All Assets

118

+14%

In Use

6

-8%

Available

111

+12%

Expiring Soon

1

ColumnsLayout: {Mobile: 1, MobileBreakpoint: 640, Tablet: 2, TabletBreakpoint: 1024, Desktop: 4}

Basic static data

All Assets

118

+14%vs last month

In Use

6

-8%vs last month

Available

111

+12%vs last month

Expiring Soon

1

Warranty expiring in less than 30 days
// Simple static data
cmpKPIDashboard.Data: Table(
    {
      Icon: "Box",
      Value: 118,
      Label: "All Assets",
      PercentChange: 14,
      PercentLabel: "vs last month",
      IconBg: "#EBF5FF",
      IconColor: "#2196F3"
    },
    {
      Icon: "TrendLines",
      Value: 6,
      Label: "In Use",
      PercentChange: -8,
      PercentLabel: "vs last month",
      IconBg: "#FFF3E0",
      IconColor: "#FF9800"
    }
)

Compact — above a data table

All Assets

118 +14%

In Use

6 -8%

Available

111 +12%

Expiring Soon

1
AssetStatusLocation
cmpKPI.Style = "Compact"

// Compact cards are 88px tall — perfect
// for placing above a gallery or table.
// Inline percent sits next to the value.

cmpKPI.OnCardClick =
    Set(varSelectedStatus, ClickedItem.Label);
    UpdateContext({locFilter: ClickedItem.Label})

Filled — executive summary

All Assets

118

+14%vs last month

In Use

6

-8%vs last month

Available

111

+12%vs last month

Expiring Soon

1

Warranty expiring in less than 30 days
cmpKPI.Style = "Filled"

// Card Fill = ColorValue(ThisItem.IconBg)
// All text = ColorValue(ThisItem.IconColor)
// Icon circle is hidden — the card IS the color
// No new data columns needed

// Dark mode: swap IconBg/IconColor for
// darker values or override StyleConfig

Live data — SharePoint connection

Total Value

$45.2K

+14%vs last month

Open Orders

234

-8%vs last month
// Named formula — declarative, auto-refreshing
KPIData =
    ForAll(
        GroupBy(Assets, "Status", "Group"),
        {
            ID: CountRows(Group),
            Icon: Switch(Status,
                "Available", "Package",
                "In Use", "TrendLines",
                "Box"
            ),
            Value: CountRows(Group),
            Label: Status,
            PercentChange: Round(
                (CountRows(Group) - varPrev)
                    / varPrev * 100,  0
            ),
            PercentLabel: "vs last month",
            IconBg: Switch(Status,
                "Available", "#E8F5E9",
                "#EBF5FF"
            ),
            IconColor: Switch(Status,
                "Available", "#4CAF50",
                "#2196F3"
            )
        }
    )

cmpKPI.Data = KPIData

Click interactions — navigate with context

All Assets

118 +14%

In Use

6 -8%
// Handle card clicks
cmpKPIDashboard.OnCardClick: 
    Navigate(
        DetailsScreen, 
        ScreenTransition.Push,
        {
            SelectedKPI: ThisItem.Label,
            KPIValue: ThisItem.Value
        }
    )

// Or update a variable
cmpKPIDashboard.OnCardClick: 
    Set(varSelectedKPI, ThisItem);
    Set(varShowDetails, true);

Data Schema

Data record

FieldTypeNotes
IDNumberOptional. Unique identifier for each card.
IconTextName matching an Icons table entry (e.g. "Box", "TrendLines", "Warning").
ValueNumberMain KPI value displayed as large text.
LabelTextCard title shown above the value.
PercentChangeNumberTrend percentage. Positive = green ↑, negative = red ↓. Blank to hide.
PercentLabelTextFooter text next to percent (e.g. "vs last month"). Blank to hide.
IconBgTextHex background for icon circle. In Filled style, becomes the entire card background.
IconColorTextHex color for icon SVG stroke. In Filled style, becomes all text color.
isHiddenBooleanOptional. Set true to hide a card without removing it from the data source.

Architecture

12 controls — 5 Text@0.0.51, 2 Classic/Button, 1 Image, 4 GroupContainer.

6 input properties — Data, Style, StyleConfig, Icons, ColumnsLayout, AnimationEffect.

1 event — OnCardClick.

Default size — Parent.Width × dynamic height. Card height: 88px (Compact) or 190px (Standard/Filled).

cmpKPI (Parent.Width × dynamic height)
└── cntStatsRow (GroupContainer — AutoLayout, horizontal wrap)
    └── galKPIs (Gallery — vertical, WrapCount by breakpoint)
        └── conKPICard (GroupContainer — ManualLayout)
            ├── txtLabel (Text@0.0.51 — card title, 13px semibold)
            ├── cntValueRow (GroupContainer — AutoLayout horizontal)
            │   ├── txtValue (Text@0.0.51 — main number, FillPortions=1)
            │   └── txtPercentInline (Text@0.0.51 — Compact only, W=70)
            ├── cntKPIFooter (GroupContainer — AutoLayout, Standard+Filled)
            │   ├── txtFooterPercent (Text@0.0.51 — ↑/↓ percent, 14px)
            │   └── txtFooterSub (Text@0.0.51 — "vs last month", 12px)
            ├── btnIconBg (Classic/Button — icon circle, hidden in Filled)
            ├── imgIconKPI (Image — inline SVG, hidden in Filled)
            └── btnCardOverlay (Classic/Button — OnSelect → OnCardClick)

Style switching:
  Filled  → card Fill=IconBg, text=IconColor, icon hidden, border=0
  Compact → 88px height, icon left, inline percent, no footer
  Standard → 190px height, icon top-right, footer with percent+label