← 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.

Jump to: · One layout change from the mockup, and why 1. Add the popover's open/close variable 2. Replace the chip row with the trigger button 3. Build the popover 3b. Hide empty types, never show a blank screen 4. Test everything

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: =180

Text 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.

Test so far: the button should show "All types" with a small chevron. Clicking it won't do anything yet — the popover doesn't exist until step 3.

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)
This block is deep — if Studio won't accept it in one paste, paste 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.
Every control above with a fixed 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: =40

Message 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.

Test: pick a type on a tab where you know it currently has zero items (or wait for the popover fix above to make that impossible, and instead switch tabs after picking one that has items elsewhere). Confirm you now see an explanatory message instead of a blank screen, and it correctly names the type that's filtered.

4. Test everything