← Back to Policy Tracker guide
Main Type Filter Popover, Full Build Guide
Replaces the always-visible row of 10 coloured type chips on Main with a single button that opens a popover list. Mockup: the approved before/after design. Filtering behaves identically underneath — same varTypeFilter variable, same colTypeCounts live counts — only how much space it takes up changes.
One layout change from the mockup, and why
The mockup showed the popover as a wrapped grid of pills. Power Apps galleries don't natively wrap items onto multiple rows the way a webpage can — a Gallery lays items out in a single scrolling row or column, nothing in between. Rather than fight that, the popover here is a simple vertical list instead: one row per type, colour swatch on the left, label and count, a checkmark on whichever one is currently active. Same information, same click behaviour, just a list instead of a wrapped grid — and it's a more standard shape for a dropdown filter menu anyway.
Everything else matches the mockup: click the button, the list appears, pick one, it closes and the button's label updates.
1. Add the popover's open/close variable
One new line in App.OnStart, next to the other varShow* flags that already live there.
Find the // Boolean flags (global) block and add this line right after Set(varShowLinkModal, false);:
Set(varShowTypeFilterPopover, false);
2. Replace the chip row with the trigger button
TypeFilterBar stays exactly where it is in the tree — only what's inside it changes. Select TypeFilterBar in Tree view, delete its two children (AllTypesBtn and TypeFilterGallery), then paste this in as its new child.
- btnTypeFilterToggle1:
Control: Classic/Button@2.2.0
Properties:
AlignInContainer: =AlignInContainer.Center
BorderColor: =RGBA(214, 221, 224, 1)
BorderThickness: =1
Color: =RGBA(22, 33, 28, 1)
DisabledBorderColor: =RGBA(166, 166, 166, 1)
Fill: =RGBA(255, 255, 255, 1)
Font: =Font.'Open Sans'
FontWeight: =FontWeight.Bold
Height: =32
HoverBorderColor: =RGBA(11, 74, 54, 1)
HoverFill: =RGBA(227, 239, 232, 1)
OnSelect: =Set(varShowTypeFilterPopover, true)
PaddingLeft: =12
PaddingRight: =12
PressedBorderColor: =RGBA(11, 74, 54, 1)
PressedFill: =RGBA(227, 239, 232, 1)
RadiusBottomLeft: =16
RadiusBottomRight: =16
RadiusTopLeft: =16
RadiusTopRight: =16
Size: =10
Text: |-
=If(
IsBlank(varTypeFilter) || varTypeFilter = "",
"☰ All types ▾",
"☰ " & With(
{FullLabel: Mid(varTypeFilter, Find(" ", varTypeFilter) + 1)},
Switch(
FullLabel,
"Newsletter Item", "Newsletter",
"Internal Document", "Internal",
FullLabel
)
) & " ▾"
)
Width: =180Text uses two escaped unicode characters (the ☰ filter glyph and ▾ chevron) so they survive the paste cleanly — Studio will render them as normal characters once pasted, nothing to type by hand.
3. Build the popover
One new top-level control, added as the very last child of the Main screen (same level as any existing modal, added after everything else in Tree view so it renders on top).
- TypeFilterOverlay1:
Control: GroupContainer@1.5.0
Variant: AutoLayout
Properties:
Fill: =RGBA(53, 61, 63, 0.84)
Height: =Parent.Height
Width: =Parent.Width
LayoutDirection: =LayoutDirection.Vertical
LayoutAlignItems: =LayoutAlignItems.Center
LayoutJustifyContent: =LayoutJustifyContent.Center
Visible: =varShowTypeFilterPopover
Children:
- conTypeFilterCard1:
Control: GroupContainer@1.5.0
Variant: AutoLayout
Properties:
AlignInContainer: =AlignInContainer.SetByContainer
FillPortions: =0
Fill: =RGBA(244, 246, 243, 1)
Width: =360
Height: =520
LayoutDirection: =LayoutDirection.Vertical
LayoutGap: =4
DropShadow: =DropShadow.Regular
RadiusBottomLeft: =16
RadiusBottomRight: =16
RadiusTopLeft: =16
RadiusTopRight: =16
PaddingBottom: =16
PaddingLeft: =16
PaddingRight: =16
PaddingTop: =16
Children:
- conTypeFilterHeader1:
Control: GroupContainer@1.5.0
Variant: AutoLayout
Properties:
FillPortions: =0
Height: =32
LayoutDirection: =LayoutDirection.Horizontal
LayoutJustifyContent: =LayoutJustifyContent.SpaceBetween
LayoutAlignItems: =LayoutAlignItems.Center
Width: =Parent.Width
Children:
- lblTypeFilterTitle1:
Control: ModernText@1.0.0
Properties:
Text: ="Filter by type"
Color: =RGBA(22, 33, 28, 1)
Font: =Font.'Lato Black'
FontWeight: =FontWeight.Bold
Size: =16
- btnTypeFilterClose1:
Control: ModernButton@1.0.0
Properties:
Icon: ="Dismiss"
Layout: =ButtonLayout.IconOnly
Appearance: =ButtonAppearance.Subtle
OnSelect: =Set(varShowTypeFilterPopover, false)
- conTypeFilterAllRow1:
Control: GroupContainer@1.5.0
Variant: ManualLayout
Properties:
FillPortions: =0
Fill: |-
=If(
IsBlank(varTypeFilter) || varTypeFilter = "",
RGBA(227, 239, 232, 1),
RGBA(255, 255, 255, 1)
)
BorderColor: |-
=If(
IsBlank(varTypeFilter) || varTypeFilter = "",
RGBA(11, 74, 54, 1),
RGBA(223, 229, 224, 1)
)
BorderThickness: =1
DropShadow: =DropShadow.None
Height: =44
RadiusBottomLeft: =8
RadiusBottomRight: =8
RadiusTopLeft: =8
RadiusTopRight: =8
Width: =Parent.Width
Children:
- lblTypeFilterAllLabel1:
Control: Label@2.5.1
Properties:
Text: ="All types"
Color: =RGBA(22, 33, 28, 1)
Font: =Font.'Open Sans'
FontWeight: =FontWeight.Bold
Size: =10
Height: =Parent.Height
Width: =Parent.Width - 40
X: =14
- iconTypeFilterAllCheck1:
Control: ModernIcon@1.1.1
Properties:
Icon: ="Checkmark"
IconColor: =RGBA(11, 74, 54, 1)
Visible: =IsBlank(varTypeFilter) || varTypeFilter = ""
Height: =16
Width: =16
X: =Parent.Width - 30
Y: =14
- recTypeFilterAllHit1:
Control: Rectangle@2.3.0
Properties:
Fill: =RGBA(0, 0, 0, 0)
Height: =Parent.Height
Width: =Parent.Width
HoverFill: =RGBA(0, 0, 0, 0.03)
OnSelect: |-
=Set(varTypeFilter, "");
Reset(HeaderGallery);
Set(varShowTypeFilterPopover, false)
- galTypeFilterList1:
Control: Gallery@2.15.0
Variant: VariableHeight
Properties:
FillPortions: =1
Items: |-
=AddColumns(
colChoiceColors,
TypeCount,
CountRows(Filter(colTypeCounts, 'Document Type'.Value = ChoiceValue))
)
TemplateSize: =48
Width: =Parent.Width
Children:
- conTypeFilterRow1:
Control: GroupContainer@1.5.0
Variant: ManualLayout
Properties:
Fill: |-
=If(
varTypeFilter = ThisItem.ChoiceValue,
ColorFade(ThisItem.ColorCode, 0.85),
RGBA(255, 255, 255, 1)
)
BorderColor: |-
=If(
varTypeFilter = ThisItem.ChoiceValue,
ThisItem.ColorCode,
RGBA(223, 229, 224, 1)
)
BorderThickness: =1
DropShadow: =DropShadow.None
Height: =40
RadiusBottomLeft: =8
RadiusBottomRight: =8
RadiusTopLeft: =8
RadiusTopRight: =8
Width: =Parent.TemplateWidth - 4
Y: =4
Children:
- recTypeFilterSwatch1:
Control: Classic/Button@2.2.0
Properties:
BorderThickness: =0
Color: =RGBA(0, 0, 0, 0)
DisplayMode: =DisplayMode.View
Fill: =ThisItem.ColorCode
HoverBorderColor: =RGBA(0, 0, 0, 0)
HoverColor: =RGBA(0, 0, 0, 0)
HoverFill: =ThisItem.ColorCode
PressedBorderColor: =RGBA(0, 0, 0, 0)
PressedColor: =RGBA(0, 0, 0, 0)
PressedFill: =ThisItem.ColorCode
Height: =Parent.Height - 16
Width: =4
X: =12
Y: =8
RadiusBottomLeft: =2
RadiusBottomRight: =2
RadiusTopLeft: =2
RadiusTopRight: =2
Text: =""
- lblTypeFilterRowLabel1:
Control: Label@2.5.1
Properties:
Text: |-
=With(
{FullLabel: Mid(ThisItem.ChoiceValue, Find(" ", ThisItem.ChoiceValue) + 1)},
Switch(
FullLabel,
"Newsletter Item", "Newsletter",
"Internal Document", "Internal",
FullLabel
)
) & " (" & ThisItem.TypeCount & ")"
Color: =RGBA(22, 33, 28, 1)
Font: =Font.'Open Sans'
FontWeight: =FontWeight.Semibold
Size: =10
Height: =Parent.Height
Width: =Parent.Width - 60
X: =28
- iconTypeFilterRowCheck1:
Control: ModernIcon@1.1.1
Properties:
Icon: ="Checkmark"
IconColor: =ThisItem.ColorCode
Visible: =varTypeFilter = ThisItem.ChoiceValue
Height: =16
Width: =16
X: =Parent.Width - 26
Y: =12
- recTypeFilterRowHit1:
Control: Rectangle@2.3.0
Properties:
Fill: =RGBA(0, 0, 0, 0)
Height: =Parent.Height
Width: =Parent.Width
HoverFill: =RGBA(0, 0, 0, 0.03)
OnSelect: |-
=Set(varTypeFilter, ThisItem.ChoiceValue);
Reset(HeaderGallery);
Set(varShowTypeFilterPopover, false)TypeFilterOverlay1 down through galTypeFilterList1 first (stop before its own Children:), confirm that lands, then select galTypeFilterList1 and paste the conTypeFilterRow1 block (from - conTypeFilterRow1: down) as its item template.Height/Width under an AutoLayout parent has FillPortions stated explicitly. Radius only ever appears on GroupContainer, ModernText/ModernButton, or Classic/Button with DisplayMode.View — including the small rounded colour swatch (recTypeFilterSwatch1), which uses the button-as-shape pattern rather than a plain Rectangle, since Rectangle doesn't support Radius* at all.3b. Hide empty types, and never show a blank screen
Found from live testing: clicking a type with zero items for the current tab left the main list completely blank, no explanation. Two changes, both small.
First: don't list a type in the popover at all if it has zero items for whatever tab is currently selected. galTypeFilterList1.Items, full replacement (adds one Filter() wrapper around the existing formula, nothing else changes):
=Filter(
AddColumns(
colChoiceColors,
TypeCount,
CountRows(Filter(colTypeCounts, 'Document Type'.Value = ChoiceValue))
),
TypeCount > 0
)Second, as a safety net: add a "no items match" message to the main list itself, for the case this doesn't fully cover on its own — pick a type while it has items on one tab, then switch to a different tab where that same type has none. The filter stays active across tabs, so you'd land back on a blank screen a different way. This message catches that regardless of how you got to zero results.
Select GalleryContainer in Tree view (the container that holds HeaderGallery), paste this in as a new child, alongside HeaderGallery:
- lblNoFilterResults1:
Control: Label@2.5.1
Properties:
Align: =Align.Center
Color: =RGBA(112, 116, 134, 1)
Font: =Font.'Open Sans'
Height: =120
Size: =11
Text: |-
=If(
IsBlank(varTypeFilter) || varTypeFilter = "",
"No items to show here.",
"No " & With(
{FullLabel: Mid(varTypeFilter, Find(" ", varTypeFilter) + 1)},
Switch(
FullLabel,
"Newsletter Item", "Newsletter",
"Internal Document", "Internal",
FullLabel
)
) & " items on this tab. Try a different tab, or clear the filter."
)
VerticalAlign: =VerticalAlign.Middle
Visible: =CountRows(HeaderGallery.AllItems) = 0
Width: =Parent.Width
Y: =40Message is specific about which filter is causing the empty state, and suggests the fix, rather than just saying "nothing found." Also fires for the general case (no filter active, but the tab itself is genuinely empty, e.g. a quiet "Issues" tab with 0 items) with a plainer message, not just the type-filter case.
4. Test everything
- Click the new button, confirm the popover opens showing "All types" plus only the doc types that actually have items on the current tab — a type with zero items for this tab shouldn't appear in the list at all.
- Pick a type. Confirm the popover closes, the button's label updates to that type's short name, and the item list on Main filters exactly as it did before.
- Reopen the popover, confirm the type you picked shows the green highlight and checkmark, and "All types" no longer does.
- Click "All types" from inside the popover, confirm it clears the filter and the button goes back to reading "All types."
- Switch dashboard tabs (Current/Future/Issues/Previously Published) with a type filter active, confirm the count next to each type in the popover updates to match the newly selected tab, same as the old chips did, and confirm the popover's own list of visible types changes to match too.
- Confirm the close (X) button in the popover header works without changing the current filter.