Skip to main content
FioriSwiftUICore provides three KPI components that together cover numeric indicators, progress visualizations, and grouped KPI dashboards.
ComponentPurpose
KPIItemSingle KPI value with an optional caption
KPIProgressItemKPI shown as a circular progress chart
KPIHeaderHorizontal row of up to four KPI items with an optional banner message

KPIItem

KPIItem renders a formatted KPI value composed of typed sub-items (metric digits, units, icons, trend indicators) alongside an optional caption.

Parameters

kpiCaption
any View / AttributedString?
Label shown below the KPI value.
items
[any KPISubItemModel]
Array of sub-items that make up the formatted KPI value. Each item has a kPISubItemValue: TextOrIcon and a kPISubItemType: KPISubitemType (.metric, .unit, .icon).
proposedViewSize
KPIItemSize
default:".small"
Controls the overall size of the KPI display. Use .small for compact layouts and .large for featured KPIs.
alignment
Alignment
default:".center"
Horizontal alignment of the KPI value and caption.

Usage

struct KPISubItemModelImpl: KPISubItemModel {
    let id = UUID()
    let kPISubItemValue: TextOrIcon
    let kPISubItemType: KPISubitemType
}

let revenueItems: [KPISubItemModelImpl] = [
    KPISubItemModelImpl(
        kPISubItemValue: .icon(Image(systemName: "arrowtriangle.up.fill")),
        kPISubItemType: .icon
    ),
    KPISubItemModelImpl(
        kPISubItemValue: .text("$"),
        kPISubItemType: .unit
    ),
    KPISubItemModelImpl(
        kPISubItemValue: .text("26.9"),
        kPISubItemType: .metric
    ),
    KPISubItemModelImpl(
        kPISubItemValue: .text("M"),
        kPISubItemType: .unit
    )
]

KPIItem(
    kpiCaption: "Revenue",
    items: revenueItems,
    proposedViewSize: .large,
    alignment: .leading
)

KPIProgressItem

KPIProgressItem displays a KPI value inside a circular progress ring. It accepts a Binding<KPIItemData> so the ring animates as the value changes.

Parameters

data
Binding<KPIItemData>
required
The KPI data to visualize. Use KPIItemData.percent(_:) for a 0–1 fraction, or KPIItemData.fraction(_:_:_:) for a numerator/denominator pair.
kpiCaption
AttributedString?
Label shown below the circular chart.
footnote
AttributedString?
Secondary label beneath the caption.
chartSize
KPIProgressItemSize
default:".large"
Size of the circular chart. .small items are hidden in KPIHeader.

Usage

@State private var downloadProgress = KPIItemData.percent(0.65)
@State private var taskCompletion = KPIItemData.fraction(76, 90, NumberFormatter())

KPIProgressItem(
    kpiCaption: "Downloading",
    data: $downloadProgress
)

KPIProgressItem(
    kpiCaption: "Tasks complete",
    footnote: "76 of 90",
    data: $taskCompletion,
    chartSize: .large
)

KPIHeader

KPIHeader arranges up to four KPIItem or KPIProgressItem views in a horizontal row. Items beyond the first four are ignored. KPIProgressItem items with .small chart size are also hidden automatically.

Parameters

items
[any KPIHeaderItemModel]
Array of KPIItem or KPIProgressItem values. Maximum of four are displayed.
bannerMessage
BannerMessage?
Optional banner displayed below the KPI row.
isItemOrderForced
Bool
default:"false"
When true, items retain their supplied order even on smaller screens.
interItemSpacing
CGFloat?
Custom spacing between KPI items. Uses the system default when nil.
isPresented
Binding<Bool>
required
Controls the visibility of the header.

Usage

@State private var isPresented = true
@State private var downloadData = KPIItemData.percent(0.65)

let kpiItems: [any KPIHeaderItemModel] = [
    KPIItem(
        kpiCaption: "Open orders",
        items: [KPISubItemModelImpl(kPISubItemValue: .text("42"), kPISubItemType: .metric)],
        proposedViewSize: .small
    ),
    KPIProgressItem(
        kpiCaption: "Downloading",
        data: $downloadData
    ),
    KPIItem(
        kpiCaption: "On-time delivery",
        items: [KPISubItemModelImpl(kPISubItemValue: .text("94"), kPISubItemType: .metric)],
        proposedViewSize: .large
    )
]

KPIHeader(items: kpiItems, isPresented: $isPresented)
    .headerSeparator(true)

Separator customization

// Show separator with default style
KPIHeader(...).headerSeparator(true)

// Show a colored separator
KPIHeader(...).headerSeparator(true, color: .red)

// Show a thick separator
KPIHeader(...).headerSeparator(true, color: .blue, lineWidth: 1.5)

// Hide separator
KPIHeader(...).headerSeparator(false)

Build docs developers (and LLMs) love