Segmented Control
Material Design 3 segmented control for mutually exclusive options. Three display modes (Text, Icons, Both), three sizes, icon position control, per-option disable, and theme-aware styling. 21 controls, 10 properties.
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. Set Options table and DefaultValueUsage
Basic text-only
cmpSegmentedControl.Options = Table(
{ Value: "list", Label: "List" },
{ Value: "grid", Label: "Grid" }
)
cmpSegmentedControl.DefaultValue = "list"
cmpSegmentedControl.DisplayMode = "Text"
cmpSegmentedControl.Size = "Medium"
cmpSegmentedControl.Theme = "Light"Icon-only compact toolbar
// App.Formulas — define SVG icons once
svgList = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2'%3E%3Cline x1='9' x2='21' y1='6' y2='6'/%3E%3Cline x1='9' x2='21' y1='12' y2='12'/%3E%3Cline x1='9' x2='21' y1='18' y2='18'/%3E%3Ccircle cx='4' cy='6' r='1.5' fill='%23666'/%3E%3Ccircle cx='4' cy='12' r='1.5' fill='%23666'/%3E%3Ccircle cx='4' cy='18' r='1.5' fill='%23666'/%3E%3C/svg%3E";
svgGrid = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2'%3E%3Crect x='3' y='3' width='7' height='7' rx='1'/%3E%3Crect x='14' y='3' width='7' height='7' rx='1'/%3E%3Crect x='3' y='14' width='7' height='7' rx='1'/%3E%3Crect x='14' y='14' width='7' height='7' rx='1'/%3E%3C/svg%3E";
svgTable = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2'%3E%3Crect x='3' y='3' width='18' height='18' rx='2'/%3E%3Cpath d='M3 9h18M3 15h18M12 3v18'/%3E%3C/svg%3E";
cmpSegmentedControl.Options = Table(
{ Value: "list", Icon: svgList },
{ Value: "grid", Icon: svgGrid },
{ Value: "table", Icon: svgTable }
)
cmpSegmentedControl.DisplayMode = "Icons"
cmpSegmentedControl.Size = "Small"
cmpSegmentedControl.EqualWidth = falseReading selection & handling changes
// Read the current value
Label1.Text = cmpSegmentedControl.SelectedValue
// Switch views based on selection
galListView.Visible = cmpSegmentedControl.SelectedValue = "list"
galGridView.Visible = cmpSegmentedControl.SelectedValue = "grid"
// React to changes via OnChange event
cmpSegmentedControl.OnChange = Switch(
Self.SelectedValue,
"list", Set(varLayout, "vertical"),
"grid", Set(varLayout, "grid"),
"table", Navigate(TableScreen)
)Properties
Input
| Property | Type | Default |
|---|---|---|
OptionsTable with Value, Label (optional), Icon (optional). No limit on option count. | Table | 3 items (list, grid, table) |
DefaultValueInitial selected value. Must match a Value in the Options table. | Text | "list" |
DisplayMode"Text" (labels only), "Icons" (icons only), or "Both" (icon + label). | Text | "Both" |
IconPosition"Left" or "Top". Only applies when DisplayMode is "Both". | Text | "Left" |
Size"Small" (32px), "Medium" (40px), or "Large" (48px). | Text | "Medium" |
EqualWidthWhen true, all option buttons share equal width. When false, icon-only mode auto-sizes. | Boolean | false |
DisabledDisable entire component. All options become non-interactive. | Boolean | false |
Theme"Light" or "Dark". Controls wrapper, selection indicator, and text colors. | Text | "Light" |
Output
| Property | Type | Description |
|---|---|---|
SelectedValue | Text | Currently selected option value. Falls back to DefaultValue when varSelectedSegment is blank. |
Events
| Event | Description |
|---|---|
OnChange | Fires after the user selects a different option. Read SelectedValue inside this handler. |
Implementation Details
Gallery-based architecture
The component uses a single horizontal gallery (galOptions) bound to the Options table via ForAll(Sequence(CountRows(Options))). Each template item contains a ManualLayout container for the selected fill, an AutoLayout container for centering icon + label, and a transparent button overlay for click handling. This supports any number of options without duplicated controls.
AutoLayout centering
Inside each gallery template, a cntContent AutoLayout container handles icon + label positioning with LayoutJustifyContent.Center and LayoutAlignItems.Center. No X/Y positioning math is needed. The layout direction flips between Horizontal (IconPosition = “Left”) and Vertical (IconPosition = “Top”) automatically.
Three display modes
Text: Only the label is visible, centered. Icons: Only the icon is visible, centered. Both: Icon and label are shown together. IconPosition controls layout — “Left” places the icon inline with the text, “Top” stacks them vertically with the icon above. Gap between icon and label scales with Size (Small = 4px, Medium = 6px, Large = 8px).
Auto-sizing for icon mode
When DisplayMode = "Icons" and EqualWidth = false, the component width scales dynamically: each option gets a square cell matching the component height (Small = 32px, Medium = 40px, Large = 48px per option, plus 6px wrapper padding). In all other modes the width is fixed at 400px.
Selection state
Selection is tracked via varSelectedSegment (set on button click). The SelectedValue output falls back to DefaultValue when the variable is blank (initial load). The selected option container shows a contrasting fill color (white on light, gray-700 on dark) and the label weight changes to Semibold.
Icon support
Icons are rendered as Image controls from SVG data URIs. Pass URL-encoded SVGs (e.g. data:image/svg+xml,%3Csvg...) in the Icon column. Define them as named formulas in App.Formulas for reuse across the app.
Examples
View switcher (Text mode)
cmpSegmentedControl.Options = Table(
{ Value: "list", Label: "List" },
{ Value: "grid", Label: "Grid" }
)
cmpSegmentedControl.DisplayMode = "Text"
cmpSegmentedControl.EqualWidth = true
galListView.Visible =
cmpSegmentedControl.SelectedValue = "list"Compact toolbar (Icon-only)
cmpSegmentedControl.Options = Table(
{ Value: "list", Icon: svgList },
{ Value: "grid", Icon: svgGrid },
{ Value: "table", Icon: svgTable }
)
cmpSegmentedControl.DisplayMode = "Icons"
cmpSegmentedControl.Size = "Small"
cmpSegmentedControl.EqualWidth = false
// svgList/svgGrid/svgTable = named formulas
// with SVG data URIs (see Usage above)Navigation (Icon + Text)
// App.Formulas — define SVG icons once
svgList = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2'%3E%3Cline x1='9' x2='21' y1='6' y2='6'/%3E%3Cline x1='9' x2='21' y1='12' y2='12'/%3E%3Cline x1='9' x2='21' y1='18' y2='18'/%3E%3Ccircle cx='4' cy='6' r='1.5' fill='%23666'/%3E%3Ccircle cx='4' cy='12' r='1.5' fill='%23666'/%3E%3Ccircle cx='4' cy='18' r='1.5' fill='%23666'/%3E%3C/svg%3E";
svgGrid = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2'%3E%3Crect x='3' y='3' width='7' height='7' rx='1'/%3E%3Crect x='14' y='3' width='7' height='7' rx='1'/%3E%3Crect x='3' y='14' width='7' height='7' rx='1'/%3E%3Crect x='14' y='14' width='7' height='7' rx='1'/%3E%3C/svg%3E";
svgTable = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2'%3E%3Crect x='3' y='3' width='18' height='18' rx='2'/%3E%3Cpath d='M3 9h18M3 15h18M12 3v18'/%3E%3C/svg%3E";
cmpSegmentedControl.Options = Table(
{ Value: "list", Label: "List", Icon: svgList },
{ Value: "grid", Label: "Grid", Icon: svgGrid },
{ Value: "table", Label: "Table", Icon: svgTable }
)
cmpSegmentedControl.DisplayMode = "Both"
cmpSegmentedControl.IconPosition = "Left"
cmpSegmentedControl.Size = "Medium"Data Schema
Options record
| Field | Type | Notes |
|---|---|---|
| Value | Text | Required. Unique identifier returned by SelectedValue. |
| Label | Text | Optional. Display text. Required when DisplayMode is "Text" or "Both". |
| Icon | Text | Optional. URL-encoded SVG data URI. Required when DisplayMode is "Icons" or "Both". Define as named formulas in App.Formulas. |
Architecture
7 controls — 1 wrapper + 1 gallery with 5 controls per template (2 containers, 1 image, 1 text, 1 button).
10 properties — 8 input, 1 output, 1 event.
Default size — 400 × 40px. Height varies by Size (32/40/48). Width scales dynamically in icon-only mode.
cmpSegmentedControl (400 × 40, or auto-width in icon mode)
└── cntWrapper (AutoLayout Horizontal, 3px padding, themed border + fill)
└── galOptions (Horizontal Gallery, bound to Options via ForAll)
└── [per item template]
├── cntOption (ManualLayout — selected fill + rounded corners)
│ └── cntContent (AutoLayout — centers icon + label)
│ ├── imgIcon — SVG data URI, visible in Icons/Both modes
│ └── lblText — Label text, visible in Text/Both modes
└── btnOption — transparent hit target → Set(varSelectedSegment, ThisItem.ItemValue); OnChange()
Selection: cntOption.Fill swaps to white (light) / gray-700 (dark)
Text: Weight → Semibold when selected, Regular otherwise
Layout: cntContent direction flips Horizontal ↔ Vertical based on IconPosition