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.
- 1. Go to the Components tab (right side panel, next to Screens)
- 2. Click New component — this creates a blank component
- 3. Click outside the new component to deselect it
- 4. Paste the YAML with Ctrl+V / ⌘V
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 _scSelected 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 width
Component width scales dynamically based on DisplayMode. In Icons mode each slot is a square matching the component height (Small = 32px, Medium = 40px, Large = 48px). In Text mode each slot is ~88px wide at Medium. In Both mode each slot is ~112px wide at Medium. The gallery divides the total width equally across all options in every mode.
Selection state
Selection is tracked via _scSelected (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 — Height varies by Size (32/40/48). Width scales dynamically based on DisplayMode — icon, text, and combined modes each use different per-slot multipliers.
cmpSegmentedControl (auto-width based on DisplayMode × slot count)
└── 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(_scSelected, 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 IconPositionCommunity
Use the toolbar to format · or type markdown directly