Badge

Customize

Notification bell with count badge, pulse animation, and custom SVG icon support. 9 properties (8 input + 1 event), 6 controls. Timer-driven pulse when count is zero.

badge.yaml

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

Preview

5
Count
99+
99+ cap
Pulse

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. Wire OnSelect to navigate or open a panel

Usage

Basic notification badge

// Named formula for unread count
UnreadCount = CountRows(Filter(Notifications, Read = false))

// Component properties
Badge.BadgeCount = UnreadCount
Badge.HasNotifications = UnreadCount > 0
Badge.OnSelect = Navigate(NotificationsScreen)

Custom icon and badge color

// Email icon with blue stroke, orange badge
Badge.IconSvg = "<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'><rect x='2' y='4' width='20' height='16' rx='2'/><path d='m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7'/></svg>"
Badge.IconColor = "#2563EB"
Badge.BadgeColor = RGBA(234, 88, 12, 1)
Badge.BadgeCount = CountRows(Filter(Emails, Unread))

Pulse-only (no count)

// Activity indicator without a number
Badge.BadgeCount = 0
Badge.HasNotifications = !IsEmpty(
    Filter(ActivityLog, Timestamp > User().LastCheckTime)
)
Badge.OnSelect = UpdateContext({locShowActivity: true})

Properties

Input

PropertyTypeDefault
BadgeColor

Background color of the count badge and pulse dot.

ColorRGBA(220,38,38,1)
BadgeCount

Number to display. Caps at 99+. Set to 0 for pulse-only mode.

Number5
HasNotifications

Controls badge/pulse visibility. When true with BadgeCount = 0, shows pulse animation.

Booleantrue
HoverText

Tooltip and accessible label for the icon.

Text""
IconColor

Hex color override for the SVG icon stroke (e.g. "#2563EB").

Text""
IconSvg

Raw SVG markup. Falls back to a bell icon if blank.

Text""
Size

Component width and height in pixels.

Number45
Theme

"Light" or "Dark". Controls icon stroke color and container border.

Text"Light"

Event

PropertyTypeDescription
OnSelectEventFormula executed when the bell is tapped. Fires via a transparent Classic/Button overlay.

8 input properties + 1 event. No output properties.

Implementation Details

Auto-sizing badge

Badge width scales with the count: single digits (1–9) render as a circle matching the badge height, two digits (10–99) expand to 20px, and anything over 99 shows “99+” at 24px wide. Height is capped at 45% of the parent container viaMin(20, Parent.Height * 0.45).

Pulse animation

A Timer@2.1.0 runs at 1000ms intervals. The pulse container's size and opacity are computed fromtmrPulse.Value / tmrPulse.Durationusing Power(p, 0.6) for an ease-out curve. The pulse uses a hardcoded red with animated alpha since Power Fx doesn't support extracting RGB channels from a Color value. The count badge uses BadgeColor directly.

SVG icon rendering

The bell icon is rendered in an Image control via a data:image/svg+xml URI. Pass any Lucide or custom SVG to IconSvg to replace the default bell. IconColor overrides the stroke color on the default bell; for custom SVGs, use stroke='currentColor' in your markup and set IconColor to control it.

Tap handling

A transparent Classic/Button overlays the entire component to capture taps and route them to the OnSelect event property. The button shows a subtle hover fill based on the Theme property.

Self-contained

No external dependencies. All colors derive from the Theme and BadgeColor properties. The container border, icon stroke, and hover fill all adapt automatically.

Examples

Email notification (custom icon)

12
Badge.IconSvg = "<svg ...email icon.../>"
Badge.IconColor = "#2563EB"
Badge.BadgeCount = CountRows(
    Filter(Emails, Unread)
)
Badge.OnSelect = Navigate(EmailScreen)

Shopping cart (dark, orange badge)

3
Badge.Theme = "Dark"
Badge.BadgeColor = RGBA(234, 88, 12, 1)
Badge.IconSvg = "<svg ...cart icon.../>"
Badge.BadgeCount = CountRows(ShoppingCart)
Badge.OnSelect = Navigate(CartScreen)

Activity pulse (no count)

Badge.BadgeCount = 0
Badge.HasNotifications = !IsEmpty(
    Filter(ActivityLog,
        Timestamp > User().LastCheckTime)
)
Badge.OnSelect =
    UpdateContext({locShowActivity: true})

Architecture

6 controls — GroupContainer (manual) + Image + GroupContainer (pulse) + Timer + GroupContainer (badge) + Text + Classic/Button overlay.

9 properties — 8 input + 1 event. No output properties.

Default size — 45 × 45px (controlled by Size property).

Badge (Size × Size, Fill: transparent)
└── cntBellContainer (GroupContainer, ManualLayout)
    ├── Fill: theme-aware subtle background
    ├── BorderColor: theme-aware border
    ├── imgBell (Image)
    │   └── data:image/svg+xml (IconSvg or default bell)
    ├── cntPulseAnimation (GroupContainer)
    │   ├── Fill: red with animated opacity (alpha fade-out)
    │   ├── Size: animated via Power(p, 0.6)
    │   ├── Visible: HasNotifications && BadgeCount = 0
    │   └── tmrPulse (Timer, 1000ms, Repeat, hidden)
    ├── cntNotificationBadge (GroupContainer)
    │   ├── Fill: BadgeColor
    │   ├── Width: auto-sized (circle → 20px → 24px)
    │   ├── Visible: HasNotifications || BadgeCount > 0
    │   └── lblNotificationCount (Text@0.0.51)
    │       └── "99+" cap, bold, white, centered
    └── btnBell (Classic/Button, transparent overlay)
        └── OnSelect: Badge.OnSelect()

Want to customize this component?

Use the visual builder to configure colors, icons, and behavior without writing code.

Open Builder