Chips
Material Design 3 chip group with input, filter, and choice modes. Per-item color and variant overrides, 5 sizes, 4 style variants, overflow badge, and closable input chips. 82 controls, 13 properties. Supports up to 10 items.
Import via Components → New component → Import from code → paste YAML
Preview
Click × to remove chips
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 see the fully rendered componentUsage
This component is stateless
The chip component reads selected directly from the Items input and never toggles it internally. Your host app must manage state via a collection and update it through the OnSelect event. Without this wiring, filter and choice chips will not show checkmarks or selected fill states.
1. Define items in a collection
// Screen.OnVisible — first row must include all fields (schema row)
ClearCollect(colChips,
{ id: "1", label: "Approved", icon: "", color: "", variant: "", selected: false },
{ id: "2", label: "Rejected", color: "error" },
{ id: "3", label: "Pending", color: "warning" },
{ id: "4", label: "Draft" }
)
// Bind the component to the collection
cmpChips.Items = colChips2. Filter chips — multi-select toggle
cmpChips.ChipType = "filter"
// OnSelect — toggle the clicked chip's selected state
UpdateIf(
colChips,
id = cmpChips.SelectedItem.id,
{ selected: !selected }
)
// Click "Approved" → selected flips to true
// → collection updates → component re-reads Items
// → chip shows checkmark + filled color3. Choice chips — single select
cmpChips.ChipType = "choice"
// OnSelect — deselect all, then select the clicked chip
UpdateIf(colChips, true, { selected: false });
UpdateIf(
colChips,
id = cmpChips.SelectedItem.id,
{ selected: true }
)4. Input chips — removable tags
cmpChips.ChipType = "input"
cmpChips.Config = { Closable: true }
cmpChips.Items = colChips
// OnClose — remove the chip from the collection
Remove(colChips,
LookUp(colChips, id = cmpChips.SelectedItem.id))
// Add new tag from a TextInput
Collect(colChips,
{ id: Text(GUID()), label: txtTag.Text });
Reset(txtTag)Properties
Input
| Property | Type | Default |
|---|---|---|
ItemsChip data: id, label, icon, color, variant, selected | Table | 10 sample chips |
ChipType"input" (removable), "filter" (multi-select), "choice" (single-select) | Text | "input" |
ColorGlobal fallback: "primary", "secondary", "success", "warning", "error" | Text | "secondary" |
VariantGlobal fallback: "filled", "tonal", "outlined", "text" | Text | "tonal" |
Size"x-small", "small", "default", "large", "x-large" | Text | "default" |
ConfigSettings record: Theme, Wrap, Closable, Disabled, Radius, Gap, MaxVisible | Record | See Config |
CustomColorsHex override per semantic color (primary, secondary, success, warning, error) | Record | All empty "" |
IconsPrepend (global leading icon) and Check (filter checkmark character) | Record | {Prepend:"", Check:"✓"} |
CharWidthsCharacter width lookup table for pixel-perfect text measurement | Table | Segoe UI Semibold |
Output
| Property | Type | Description |
|---|---|---|
SelectedItem | Record | Full record of the last clicked or closed chip (set via _chipSelected variable). |
Events
| Event | Description |
|---|---|
OnSelect | Fires when a chip body is clicked. Hidden when input mode with Closable enabled to prevent accidental triggers. |
OnClose | Fires when the close (×) button is clicked. Only active when ChipType = "input" and Config.Closable = true. |
OnOverflow | Fires when the overflow (+N) badge is clicked. Visible when Items count exceeds MaxVisible. |
Implementation Details
Fixed 10-slot architecture
Like the breadcrumbs component, chips uses fixed slots (cntChip1–cntChip10) instead of a gallery. Each slot contains 8 controls: outer container, content AutoLayout, icon image, auto-width label, close button group with image and button, plus a transparent hit-target button. Visibility is gated by CountRows(Items) >= N && N <= MaxVisible.
Color resolution cascade
Colors resolve in order: per-item color field → component-level Color property → CustomColors hex overrides → built-in Material palette. The same cascade applies for variant: per-item first, then the global Variant. This lets you mix tonal success chips with outlined primary chips in the same group.
Stateless selection by ChipType
The component never mutates its own Items — the host app owns all state. input: No selection state. Close button visible when Closable is true; the main hit button hides to prevent accidental taps. filter: Multi-select. Use UpdateIf(colChips, id = SelectedItem.id, { selected: !selected }) in OnSelect to toggle. A selected chip shows its filled color with a checkmark icon. choice: Single-select (radio). Use UpdateIf(colChips, true, { selected: false }) then UpdateIf(colChips, id = SelectedItem.id, { selected: true }) in OnSelect.
Pixel-perfect text width
Each chip label width is calculated using the CharWidths lookup table: Sum(Split(text,""), LookUp(CharWidths, Char=Value).Size) × FontSize × 1.05 + 6. This enables auto-width chips without a gallery, preventing text overflow and unnecessary whitespace.
Overflow badge
When MaxVisible is set and the Items table exceeds it, a btnOverflow button appears showing “+N”. Clicking it fires the OnOverflow event. The button displays a tooltip with the full count.
Icon support
Icons accept emoji (wrapped in SVG text element), raw SVG strings, or data: URIs. Set per-item via the icon field, or globally via Icons.Prepend. For filter chips, a selected chip with no custom icon shows the Icons.Check character (default “✓”).
Examples
Status tags (tonal, mixed colors)
// First row defines all columns (schema row)
cmpChips.Items = Table(
{ id:"1", label:"Approved",
icon:"", color:"success",
variant:"tonal", selected:false },
{ id:"2", label:"Rejected",
color:"error" },
{ id:"3", label:"Pending",
color:"warning" },
{ id:"4", label:"Draft" }
)
cmpChips.ChipType = "input"
cmpChips.Config = { Closable: false }Size picker (choice, outlined)
// Screen.OnVisible
ClearCollect(colSizes, cmpChips.Items)
cmpChips.ChipType = "choice"
cmpChips.Variant = "outlined"
cmpChips.Items = colSizes
// OnSelect — single select
UpdateIf(colSizes, true,
{ selected: false });
UpdateIf(colSizes,
id = cmpChips.SelectedItem.id,
{ selected: true })Overflow with +N badge
// 10 items, only show 3
cmpChips.Config = {
MaxVisible: 3,
Gap: 8
}
// Handle overflow click
cmpChips.OnOverflow =
Set(varShowAllTags, true)Data Schema
Items record
icon, color, variant, selected) to establish the schema. Subsequent rows can omit them — values fall back to component-level defaults via Coalesce.| Field | Type | Notes |
|---|---|---|
| id | Text | Required. Unique identifier. |
| label | Text | Required. Display text. Width auto-calculated via CharWidths. |
| icon | Text | Optional. Emoji, SVG string, or data: URI. Falls back to Icons.Prepend. |
| color | Text | Optional. "primary" / "secondary" / "success" / "warning" / "error". Falls back to component Color. |
| variant | Text | Optional. "filled" / "tonal" / "outlined" / "text". Falls back to component Variant. |
| selected | Boolean | Required for filter/choice. Component is stateless — manage via UpdateIf in OnSelect. |
Config record
| Field | Type | Default | Notes |
|---|---|---|---|
| Theme | Text | "light" | "light" or "dark" |
| Wrap | Boolean | false | Reserved. Chips scroll horizontally via LayoutOverflowX. |
| Closable | Boolean | true | Show × button on input chips. Hides main OnSelect button. |
| Disabled | Boolean | false | Disable close buttons and interactions. |
| Radius | Number | 99 | Border radius in px. Clamped to half the chip height (pill by default). |
| Gap | Number | 8 | Horizontal gap between chips (AutoLayout LayoutGap). |
| MaxVisible | Number | 10 | Max chips shown before +N overflow badge appears. |
Architecture
82 controls — 1 wrapper + 10 chip slots (8 controls each) + 1 overflow button.
13 properties — 9 input, 1 output, 3 events.
Default size — 800 × 50px. Height varies by Size property (38–62px).
cmpChips (width 800, height: x-small 38 / small 44 / default 50 / large 56 / x-large 62)
└── cntChipsWrapper (AutoLayout Horizontal, LayoutOverflowX: Scroll)
├── cntChip1 (visible: Items ≥ 1 && 1 ≤ MaxVisible)
│ ├── cntContent1 (AutoLayout Horizontal, gap 4)
│ │ ├── imgIcon1 — emoji/SVG/data: URI, or ✓ for selected filter
│ │ ├── lblText1 — auto-width via CharWidths formula
│ │ └── cntClose1 — visible: input + Closable + !Disabled
│ │ ├── imgClose1 (× circle SVG, theme-aware)
│ │ └── btnClose1 → Set(_chipSelected, ...); OnClose()
│ └── btnChip1 → Set(_chipSelected, ...); OnSelect()
│ (hidden when input + Closable to avoid double-tap)
├── cntChip2 … cntChip10 (identical pattern, Index offset)
└── btnOverflow → "+N" text, fires OnOverflow()
(visible: Items > MaxVisible)