Sidebar
A collapsible left navigation sidebar: header with a toggle, a grouped icon-led menu with one nested sub-menu, and a footer user row. Inspired by the shadcn/ui Sidebar composition.
How to Use
- On the Settings tab, edit the 2 group headings, each of the 7 menu items' Label and Icon (pick from the curated icon dropdown; each option shows the actual glyph), and the 2 "Projects" sub-item labels. Item COUNT is fixed at 7 (4 under the first heading, 3 under the second, matching which items sit under "Projects" in the menu); there's no add/remove control, only in-place editing; group membership, the sub-menu's position under "Projects", and the separators aren't settings-driven. The Preview tab and the copyable YAML update together.
- Paste the YAML into Power Apps Studio (Ctrl+V). One GroupContainer (conSidebar) is added. Header, menu, and footer all nest inside it via Vertical AutoLayout.
- Click the «/» button in the header to collapse the sidebar to icon-only (56px) or expand it back (240px), tracked in varSidebarCollapsed, no OnVisible needed. Every text element (group headings, item/sub-item labels, header title, footer name/role) hides independently when collapsed; icons always stay visible.
- Clicking a menu item sets varSidebarSelected and highlights that row with a rounded background pill (imgSidebarItemBg); Dashboard is active by default (Coalesce(varSidebarSelected, "dashboard")). The pill is a separate decorative layer BEHIND the icon/label, never a Fill on the topmost hit-target button itself, so it can never obscure them in any state.
- The "Projects" sub-menu (its 2 labels are settings-driven; its position directly under "Projects" is not) is always-expanded, extra-indented, icon-less rows directly under "Projects" in the same Gallery, not a real per-row expand/collapse accordion. That would need a dynamic per-row height, which this project avoids stacking onto an already-novel first build.
- Icons are hand-drawn inline SVG (via Image + EncodeUrl), not Classic/Icon: the curated Icon dropdown's options don't map to Power Apps' built-in Icon.* set at all; each is a small hand-drawn SVG shape baked directly into the generated Items formula's IconPath field.
- The footer shows a user row (Avatar@1.0.40 + name/role) with a placeholder confirmation toast on click; wire btnSidebarFooterHit's OnSelect to your real account menu once connected.
- This is the first sidebar/collapsible-nav component in this project. Test the collapse toggle and the Type-flagged single-Gallery menu carefully in Studio.
Problem Solved
Provides a ready-made collapsible navigation sidebar (grouped icon-led menu, nested sub-menu, active-item highlighting, icon-only collapse) which Power Apps has no native equivalent for. Unlike a typical PA component, the group headings and each item's label/icon are editable straight from the website's Settings tab, no need to hand-edit a Table()/array literal in Studio for routine content changes.
Integration
The 2 group headings, the 7 items' Label/Icon, and the 2 sub-item labels are all settings-driven; the website computes galSidebarMenu.Items from them and bakes it into the copied YAML. Only the SHAPE (which items sit under which heading, where the Projects sub-menu goes) stays fixed; edit galSidebarMenu.Items directly in the pasted YAML if you need to change that structure itself. Wire each menu row's real navigation (btnSidebarItemHit.OnSelect currently only sets varSidebarSelected for the active-highlight visual) and btnSidebarFooterHit's OnSelect to your real account menu once connected.
YAML Code
- conSidebar:
Control: GroupContainer@1.5.0
Variant: AutoLayout
Properties:
BorderColor: =RGBA(226, 232, 240, 1)
BorderThickness: =1
DropShadow: =DropShadow.None
Fill: =RGBA(255, 255, 255, 1)
Height: =Parent.Height
LayoutAlignItems: =LayoutAlignItems.Stretch
LayoutDirection: =LayoutDirection.Vertical
LayoutGap: =10
Width: =If(Coalesce(varSidebarCollapsed, false), 56, 240)
Children:
- conSidebarHeader:
Control: GroupContainer@1.5.0
Variant: AutoLayout
Properties:
DropShadow: =DropShadow.None
FillPortions: =0
Height: =52
LayoutAlignItems: =LayoutAlignItems.Center
LayoutDirection: =LayoutDirection.Horizontal
LayoutGap: =8
LayoutMinHeight: =0
LayoutMinWidth: =0
PaddingLeft: =12
PaddingRight: =12
Children:
- btnSidebarToggle:
Control: Classic/Button@2.2.0
Properties:
AlignInContainer: =AlignInContainer.Center
BorderColor: =RGBA(0, 0, 0, 0)
BorderThickness: =1
Color: =RGBA(71, 85, 105, 1)
Fill: =RGBA(0, 0, 0, 0)
FocusedBorderThickness: =0
Font: =Font.'Open Sans'
HoverBorderColor: =RGBA(0, 0, 0, 0)
HoverColor: =Self.Color
HoverFill: =RGBA(241, 245, 249, 1)
OnSelect: =Set(varSidebarCollapsed, !Coalesce(varSidebarCollapsed, false))
PressedFill: =RGBA(226, 232, 240, 1)
RadiusBottomLeft: =6
RadiusBottomRight: =6
RadiusTopLeft: =6
RadiusTopRight: =6
Size: =11
Text: =If(Coalesce(varSidebarCollapsed, false), "»", "«")
Height: =28
Width: =28
- lblSidebarHeaderTitle:
Control: Label@2.5.1
Properties:
AlignInContainer: =AlignInContainer.Stretch
Color: =RGBA(15, 23, 42, 1)
FillPortions: =1
Font: =Font.Lato
FontWeight: =FontWeight.Semibold
LayoutMinHeight: =0
LayoutMinWidth: =0
Size: =12
Text: ="CopySnips Portal"
Visible: =!Coalesce(varSidebarCollapsed, false)
Height: =16
- imgSidebarHeaderDivider:
Control: Image@2.2.3
Properties:
AlignInContainer: =AlignInContainer.Stretch
Fill: =RGBA(226, 232, 240, 1)
Image: =Blank()
LayoutMinHeight: =0
LayoutMinWidth: =0
Height: =1
- galSidebarMenu:
Control: Gallery@2.15.0
Variant: Vertical
Properties:
DelayItemLoading: =false
FillPortions: =0
Height: =352
Items: =[{Type:"heading",Label:"Platform",IconPath:"",Value:""}, {Type:"item",Label:"Dashboard",IconPath:"<rect x='3' y='3' width='7' height='7' rx='1'/><rect x='14' y='3' width='7' height='7' rx='1'/><rect x='3' y='14' width='7' height='7' rx='1'/><rect x='14' y='14' width='7' height='7' rx='1'/>",Value:"dashboard"}, {Type:"item",Label:"Projects",IconPath:"<path d='M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z'/>",Value:"projects"}, {Type:"subitem",Label:"Active",IconPath:"",Value:"projects-active"}, {Type:"subitem",Label:"Archived",IconPath:"",Value:"projects-archived"}, {Type:"item",Label:"Messages",IconPath:"<rect x='2' y='4' width='20' height='16' rx='2'/><path d='m22 6-10 7L2 6'/>",Value:"messages"}, {Type:"item",Label:"Calendar",IconPath:"<rect x='3' y='4' width='18' height='18' rx='2'/><line x1='16' y1='2' x2='16' y2='6'/><line x1='8' y1='2' x2='8' y2='6'/><line x1='3' y1='10' x2='21' y2='10'/>",Value:"calendar"}, {Type:"heading",Label:"Workspace",IconPath:"",Value:""}, {Type:"item",Label:"Team",IconPath:"<circle cx='9' cy='8' r='3'/><path d='M3 20c0-3.3 2.7-6 6-6s6 2.7 6 6'/><circle cx='17' cy='9' r='2.5'/><path d='M15.5 13.2c2.3.4 4 2.4 4.5 4.8'/>",Value:"team"}, {Type:"item",Label:"Billing",IconPath:"<rect x='2' y='5' width='20' height='14' rx='2'/><line x1='2' y1='10' x2='22' y2='10'/>",Value:"billing"}, {Type:"item",Label:"Settings",IconPath:"<circle cx='12' cy='12' r='3'/><line x1='12' y1='2' x2='12' y2='5'/><line x1='12' y1='19' x2='12' y2='22'/><line x1='2' y1='12' x2='5' y2='12'/><line x1='19' y1='12' x2='22' y2='12'/>",Value:"settings"}]
LayoutMinHeight: =0
LayoutMinWidth: =0
ShowScrollbar: =false
TemplatePadding: =0
TemplateSize: =32
Children:
- lblSidebarHeading:
Control: Label@2.5.1
Properties:
Color: =RGBA(100, 116, 139, 1)
Font: =Font.Lato
FontWeight: =FontWeight.Semibold
Size: =10
Text: =ThisItem.Label
Visible: =(ThisItem.Type = "heading") && !Coalesce(varSidebarCollapsed, false)
Height: =16
Width: =Parent.TemplateWidth - 16
X: =16
Y: =8
- imgSidebarItemBg:
Control: Image@2.2.3
Properties:
Fill: =If(ThisItem.Value = Coalesce(varSidebarSelected, "dashboard"), RGBA(241, 245, 249, 1), RGBA(0, 0, 0, 0))
Image: =Blank()
RadiusBottomLeft: =6
RadiusBottomRight: =6
RadiusTopLeft: =6
RadiusTopRight: =6
Visible: =ThisItem.Type <> "heading" && (ThisItem.Type = "item" || !Coalesce(varSidebarCollapsed, false))
Height: =28
Width: =Parent.TemplateWidth - 16
X: =8
Y: =2
- imgSidebarItemIcon:
Control: Image@2.2.3
Properties:
Image: |-
="data:image/svg+xml;utf8, " & EncodeUrl("<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='RGBA(51, 65, 85, 1)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'>" & ThisItem.IconPath & "</svg>")
Visible: =ThisItem.Type = "item"
Height: =16
Width: =16
X: =16
Y: =8
- lblSidebarItemLabel:
Control: Label@2.5.1
Properties:
Color: =If(ThisItem.Type = "subitem", RGBA(71, 85, 105, 1), RGBA(15, 23, 42, 1))
Font: =Font.Lato
Size: =If(ThisItem.Type = "subitem", 10, 11)
Text: =ThisItem.Label
Visible: =(ThisItem.Type = "item" || ThisItem.Type = "subitem") && !Coalesce(varSidebarCollapsed, false)
Height: =16
Width: =Parent.TemplateWidth - 52
X: =If(ThisItem.Type = "subitem", 52, 40)
Y: =8
- btnSidebarItemHit:
Control: Classic/Button@2.2.0
Properties:
BorderColor: =RGBA(0, 0, 0, 0)
BorderThickness: =1
Color: =RGBA(0, 0, 0, 0)
Fill: =RGBA(0, 0, 0, 0)
FocusedBorderThickness: =0
Font: =Font.'Open Sans'
HoverBorderColor: =RGBA(226, 232, 240, 1)
HoverColor: =RGBA(0, 0, 0, 0)
HoverFill: =RGBA(0, 0, 0, 0)
OnSelect: =Set(varSidebarSelected, ThisItem.Value)
PressedFill: =RGBA(0, 0, 0, 0)
RadiusBottomLeft: =6
RadiusBottomRight: =6
RadiusTopLeft: =6
RadiusTopRight: =6
Text: =""
Visible: =ThisItem.Type <> "heading" && (ThisItem.Type = "item" || !Coalesce(varSidebarCollapsed, false))
Height: =28
Width: =Parent.TemplateWidth - 16
X: =8
Y: =2
- imgSidebarFooterDivider:
Control: Image@2.2.3
Properties:
AlignInContainer: =AlignInContainer.Stretch
Fill: =RGBA(226, 232, 240, 1)
Image: =Blank()
LayoutMinHeight: =0
LayoutMinWidth: =0
Height: =1
- conSidebarFooter:
Control: GroupContainer@1.5.0
Variant: ManualLayout
Properties:
DropShadow: =DropShadow.None
FillPortions: =0
Height: =65
LayoutMinWidth: =0
Children:
- avtSidebarUser:
Control: Avatar@1.0.40
Properties:
Image: =Blank()
Name: ="Said EL AYYACHI"
Height: =28
Width: =28
X: =12
Y: =14
- conSidebarFooterText:
Control: GroupContainer@1.5.0
Variant: AutoLayout
Properties:
DropShadow: =DropShadow.None
LayoutAlignItems: =LayoutAlignItems.Stretch
LayoutDirection: =LayoutDirection.Vertical
Visible: =!Coalesce(varSidebarCollapsed, false)
Height: =50
Width: =160
X: =50
Y: =12
Children:
- lblSidebarUserName:
Control: Label@2.5.1
Properties:
AlignInContainer: =AlignInContainer.Stretch
Color: =RGBA(15, 23, 42, 1)
Font: =Font.Lato
FontWeight: =FontWeight.Semibold
LayoutMinHeight: =0
LayoutMinWidth: =0
Size: =10
Text: ="Said EL AYYACHI"
Height: =20
- lblSidebarUserRole:
Control: Label@2.5.1
Properties:
AlignInContainer: =AlignInContainer.Stretch
Color: =RGBA(100, 116, 139, 1)
Font: =Font.Lato
LayoutMinHeight: =0
LayoutMinWidth: =0
Size: =9
Text: ="said@copysnips.com"
Height: =30
- btnSidebarFooterHit:
Control: Classic/Button@2.2.0
Properties:
BorderColor: =RGBA(0, 0, 0, 0)
BorderThickness: =1
Color: =RGBA(0, 0, 0, 0)
Fill: =RGBA(0, 0, 0, 0)
FocusedBorderThickness: =0
Font: =Font.'Open Sans'
HoverBorderColor: =RGBA(226, 232, 240, 1)
HoverColor: =RGBA(0, 0, 0, 0)
HoverFill: =RGBA(0, 0, 0, 0)
OnSelect: =Notify("Wire this to your real account menu once connected.", NotificationType.Information)
PressedFill: =RGBA(0, 0, 0, 0)
RadiusBottomLeft: =6
RadiusBottomRight: =6
RadiusTopLeft: =6
RadiusTopRight: =6
Text: =""
Height: =Parent.Height
Width: =Parent.Width
X: =0
Y: =0Implementation
Copies the customized component code directly to your clipboard. Use Ctrl+V in Power Apps Studio.
Something not pasting right? Troubleshooting guide