Sidebar

Collapsible sidebar navigator with dark/light themes, SVG icons, parent/child tree navigation with expand/collapse, number and dot badges, section labels, a user footer with initials avatar, and a context menu. Snaps between 260px (expanded) and 64px (collapsed) — use the IsExpanded output to offset your screen content. 20 properties.

cmpSidebar.yaml
  1. 1. Go to the Components tab (right side panel, next to Screens)
  2. 2. Click New component — this creates a blank component
  3. 3. Click outside the new component to deselect it
  4. 4. Paste the YAML with Ctrl+V / ⌘V

Preview

P
PowerAppsUI
Library
Components
Canvas
PCF
2
Starter Kits
3
Changelog
Account
Profile
Settings
RY
Rodas Yonass
rodas@powerappsui.com
Canvas
Active page content area
24
Components
8
Premium
16
Free

Installation

  1. Copy the YAML using the button above.
  2. Open your canvas app in Power Apps Studio.
  3. Go to Components → New component → Import from code.
  4. Paste the YAML and click Save.
  5. Insert cmpSidebar on your screen. Set Height = App.Height and X = 0, Y = 0.
  6. On your screen's OnVisible, initialize the four required app variables (see Usage below).
  7. Offset your content area with X = cmpSidebar.Width and Width = App.Width - cmpSidebar.Width so it never overlaps the nav.

Usage

Screen OnVisible — initialize variables

// Screen.OnVisible — run once when screen loads
Set(_cmpNavIsExpanded, true);
Set(_cmpNavSelID, 11);                    // default selected item ID
ClearCollect(colNavExpanded, {ID: 1});    // IDs of expanded parent rows

// Wire the sidebar
// cmpSidebar.Items        = <your items table>
// cmpSidebar.Theme        = gTheme
// cmpSidebar.AccentColor  = RGBA(79, 142, 247, 1)
// cmpSidebar.Expanded     = _cmpNavIsExpanded

OnNavSelect — navigate between screens

// cmpSidebar.OnNavSelect
Switch(
    cmpSidebar.SelectedID,
    11, Navigate(scrCanvas,  Transition.None),
    12, Navigate(scrPCF,     Transition.None),
    2,  Navigate(scrKits,    Transition.None),
    3,  Navigate(scrChangelog,Transition.None),
    4,  Navigate(scrProfile, Transition.None),
    5,  Navigate(scrSettings,Transition.None)
)

Custom Items table

// cmpSidebar.Items — full schema
Table(
  // Section header — Icon and Letter are ignored on section rows
  {ID:0,  Title:"Work Orders",   Icon:"",        Letter:"",  Badge:0, BadgeColor:RGBA(0,0,0,0),     BadgeDot:false, IsSection:true,  ParentID:-1, Visible:true},
  // Root item — icon name must match a row in the Icons table
  {ID:1,  Title:"Dashboard",     Icon:"Home",    Letter:"",  Badge:0, BadgeColor:RGBA(0,0,0,0),     BadgeDot:false, IsSection:false, ParentID:-1, Visible:true},
  // Root item — letter fallback shown when Icon is blank
  {ID:2,  Title:"Reports",       Icon:"",        Letter:"R", Badge:5, BadgeColor:RGBA(239,68,68,1), BadgeDot:false, IsSection:false, ParentID:-1, Visible:true},
  // Child items — ParentID points to ID:2
  {ID:21, Title:"Daily",         Icon:"",        Letter:"",  Badge:0, BadgeColor:RGBA(0,0,0,0),     BadgeDot:false, IsSection:false, ParentID:2,  Visible:true},
  {ID:22, Title:"Weekly",        Icon:"",        Letter:"",  Badge:0, BadgeColor:RGBA(0,0,0,0),     BadgeDot:false, IsSection:false, ParentID:2,  Visible:true},
  // Role-gated item
  {ID:3,  Title:"Admin Panel",   Icon:"Shield",  Letter:"",  Badge:0, BadgeColor:RGBA(0,0,0,0),     BadgeDot:false, IsSection:false, ParentID:-1, Visible:gCurrentUser.Role = "Admin"}
)

OnToggle — expand/collapse

// cmpSidebar.OnToggle
Set(_cmpNavIsExpanded, !_cmpNavIsExpanded)

// Offset your content container — bind these properties:
// Content.X     = cmpSidebar.Width
// Content.Width = App.Width - cmpSidebar.Width

// Width snaps automatically:
// Expanded  → 260 px
// Collapsed → 64 px

Footer menu events

// cmpSidebar.OnFooterSettings
Navigate(scrSettings, Transition.None)

// cmpSidebar.OnHelp
Launch("https://docs.yourdomain.com")

// cmpSidebar.OnThemeToggle
Set(gTheme, If(gTheme = "Dark", "Light", "Dark"))
// then bind: cmpSidebar.Theme = gTheme

Dynamic badge from SharePoint

// Compute badge counts in App.OnStart and store in variables
Set(gUnreadNotifications, CountRows(Filter(Notifications, !Read && AssignedTo = User().Email)));
Set(gOpenWorkOrders,      CountRows(Filter('Work Orders', Status = "Open")));

// Then reference them in your Items table
{ID:1, Title:"Work Orders", ..., Badge:gOpenWorkOrders, BadgeColor:RGBA(239,68,68,1), BadgeDot:false, ...},
{ID:4, Title:"Notifications",..., Badge:gUnreadNotifications, BadgeDot:true, ...}

Custom logo image

// AppLogo set — AccentColor tile disappears, image fills the mark
cmpSidebar.AppLogo = yourLogoImage      // any Power Apps Image value

// AppLogo blank (default) — AccentColor tile + first letter of AppName
cmpSidebar.AppLogo = Blank()
cmpSidebar.AppName = "Contoso"          // shows "C" in AccentColor tile

// Tip: use a square PNG/SVG with a transparent background
// The mark is 36×36px with radius 10 — it clips the image to that shape

Extending the icon library

// Add custom icons to the Icons input alongside the defaults
// Any Heroicons or Lucide SVG with stroke='white' works
cmpSidebar.Icons = Table(
    // Keep all defaults, then append your own:
    {Name:"Truck",   SVG:"<svg viewBox='0 0 24 24' width='24' height='24' xmlns='http://www.w3.org/2000/svg' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><rect x='1' y='3' width='15' height='13'/><polygon points='16 8 20 8 23 11 23 16 16 16 16 8'/><circle cx='5.5' cy='18.5' r='2.5'/><circle cx='18.5' cy='18.5' r='2.5'/></svg>"},
    {Name:"Wrench",  SVG:"<svg viewBox='0 0 24 24' width='24' height='24' xmlns='http://www.w3.org/2000/svg' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M14.7 6.3a1 1 0 000 1.4l1.6 1.6a1 1 0 001.4 0l3.77-3.77a6 6 0 01-7.94 7.94l-6.91 6.91a2.12 2.12 0 01-3-3l6.91-6.91a6 6 0 017.94-7.94l-3.76 3.76z'/></svg>"}
)

// Then reference by name in Items:
{ID:1, Title:"Fleet", Icon:"Truck",  ...}
{ID:2, Title:"Maintenance", Icon:"Wrench", ...}

Properties

Input

PropertyTypeDefault
Items

Table driving the navigation. Schema: {ID, Title, Icon, Letter, Badge, BadgeColor, BadgeDot, IsSection, ParentID, Visible}. Set IsSection:true for divider/label rows. Set ParentID to the parent item's ID for child rows or -1 for root level. Set Visible:false for role-gated items.

Table9 built-in rows
AccentColor

Primary accent color applied to selected item highlights, icon fills, badge fills, and the logo mark background.

ColorRGBA(79,142,247,1)
Theme

"Dark" renders on a near-black background. "Light" renders on a soft off-white background. All text, border, hover, and icon colors adapt automatically.

Text"Dark"
Expanded

Initial expanded state. Bind to _cmpNavIsExpanded. The component internally manages collapse — the width snaps between 260px (expanded) and 64px (collapsed). In collapsed mode, only icons show with hover tooltips.

Booleantrue
AppName

First word of the app name shown in the header when expanded.

Text"PowerApps"
AppNameAccent

Second word rendered in AccentColor next to AppName. Set to blank to hide.

Text"UI"
AppLogo

Logo image displayed inside the header mark. When set, the AccentColor tile background becomes transparent and the image fills the mark. When blank, the tile renders in AccentColor with the first letter of AppName as a fallback. Accepts any Power Apps Image value — resource, media upload, or Base64 URI.

ImageBlank()
ShowHeader

Show the logo mark and app name at the top of the nav. Hide for fullscreen or kiosk layouts.

Booleantrue
ShowToggle

Show the expand/collapse toggle pill on the right edge of the header.

Booleantrue
ShowSearch

Show a search input below the header. Only visible when the nav is expanded.

Booleanfalse
ShowUser

Show the current user's initials avatar, name, and email in the footer row. Hides the footer entirely when false.

Booleantrue
Icons

SVG icon library as a table of {Name, SVG} pairs. Reference icons in Items by name string — e.g. Icon:"Grid". Ships with 15 built-in icons: Grid, Layers, File, User, Settings, Home, Dashboard, Bell, Chart, Users, Database, Box, Shield, Code, Help. Extend with any Heroicons or Lucide SVG using stroke='white'.

Table15 built-in icons

Events

EventWhen it fires
OnNavSelectA leaf nav item is tapped. Read SelectedID output to identify which item was pressed and navigate accordingly.
OnToggleThe expand/collapse toggle pill is pressed. Flip your _cmpNavIsExpanded variable here.
OnFooterSettingsSettings is tapped in the footer context menu.
OnHelpHelp is tapped in the footer context menu.
OnThemeToggleTheme is tapped in the footer context menu. Toggle your gTheme variable and bind it back to the Theme property.

Output

PropertyTypeDescription
SelectedIDNumberID of the most recently tapped nav item. Set _cmpNavSelID on OnVisible to pre-select the correct item for the current screen.
IsExpandedBooleanMirrors the internal _cmpNavIsExpanded variable. Use to offset content — bind your content area's X = cmpSidebar.Width.

Implementation Details

App-scoped variables instead of component variables

The component uses AccessAppScope: true and reads/writes three app variables directly: _cmpNavIsExpanded (Boolean), _cmpNavSelID (Number), and colNavExpanded (collection of { ID: Number }). You must initialize all three on each screen's OnVisible so the sidebar starts in the correct state.

Parent/child tree via Filter + colNavExpanded

galNavItems.Items runs a Filter over the Items table. Root-level items (ParentID = -1) are always shown. Child items (ParentID > 0) are shown only when their parent's ID is in colNavExpanded and the nav is expanded. Tapping a parent toggles its ID in/out of colNavExpanded via Collect / RemoveIf.

Tree line and dot connectors

Each child row renders a vertical rctTreeLine rectangle and a cntTreeDot container. The line height is 42px (full row) for non-last children and 21px (half row) for the last child, computed by checking whether any sibling with a higher ID exists via LookUp(Filter(...), ID > ThisItem.ID). The dot fills with AccentColor when the item is selected.

Logo mark — image vs. initial fallback

cntLogoMark switches between two modes based on AppLogo: when set, imgNavLogo is visible and the container Fill is Color.Transparent so the image renders without a colored tile behind it. When AppLogo is blank, imgNavLogo hides, lblLogoInitial shows the first letter of AppName, and the container Fill reverts to AccentColor. Use a square PNG or SVG with a transparent background — the mark is 36×36px with radius 10 and clips the image to that shape.

Collapsed mode tooltips

In collapsed mode, nav labels and badges are hidden. A Tooltip property on btnNavItem shows the item title on hover. Child items are automatically hidden from the gallery when the nav is collapsed (the Filter excludes ParentID > -1 rows unless _cmpNavIsExpanded is true).

Badge rendering

Each gallery row renders two badge controls: cntNavBadgeDot (8px circle, shown when BadgeDot=true) and cntNavBadge (pill with number, shown when BadgeDot=false). Both use BadgeColor for the fill, falling back to AccentColor when BadgeColor = RGBA(0,0,0,0). Badges are hidden in collapsed mode via their Visible property checking _cmpNavIsExpanded.

Footer context menu

cntFooterMenu sits inside the component at Y = Parent.Height - 73 - Self.Height - 8, floating above the footer row. Its Visible is tied to the _cmpNavFooterMenu app variable, which toggles on the three-dot button click and resets to false when any menu item is selected. A transparent btnFooterMenuCatchall behind all menu rows prevents click-throughs to the nav items below.

Icon lookup via the Icons table

Items reference icons by name string — e.g. Icon:"Grid". At render time, imgNavItemIcon.Image runs LookUp(cmpSidebar.Icons, Name = ThisItem.Icon, SVG) and wraps the result in a data:image/svg+xml, data URI via EncodeUrl(). All built-in SVGs use stroke='white' — the icon container's fill (AccentColor vs muted) provides active/inactive contrast so the icon always renders white on a colored tile. To add custom icons, extend the Icons input with additional rows — any Heroicons or Lucide SVG with stroke='white' works.

Examples

Dark theme — expanded

P
PowerAppsUI
Library
Components
Canvas
PCF
2
Starter Kits
3
Changelog
Account
Profile
Settings
RY
Rodas Yonass
rodas@powerappsui.com
Canvas
Active page content area
24
Components
8
Premium
16
Free
// Screen.OnVisible
Set(_cmpNavIsExpanded, true);
Set(_cmpNavSelID, 11);
ClearCollect(colNavExpanded, {ID:1});

// Component properties
cmpSidebar.Theme        = "Dark"
cmpSidebar.Expanded     = _cmpNavIsExpanded
cmpSidebar.AccentColor  = RGBA(79,142,247,1)
cmpSidebar.ShowHeader   = true
cmpSidebar.ShowToggle   = true
cmpSidebar.ShowUser     = true

Light theme — collapsed

P
PowerAppsUI
RY
Canvas
Active page content area
24
Components
8
Premium
16
Free
// Collapsed mode — 64px wide
// Only icons + tooltips on hover
Set(_cmpNavIsExpanded, false);

cmpSidebar.Theme    = "Light"
cmpSidebar.Expanded = _cmpNavIsExpanded

// Content offset
cntContent.X     = cmpSidebar.Width
cntContent.Width = App.Width - cmpSidebar.Width

Kiosk mode — no header, no user footer

Library
Components
Canvas
PCF
2
Starter Kits
3
Changelog
Account
Profile
Settings
Canvas
Active page content area
24
Components
8
Premium
16
Free
// Hide chrome for kiosk / embedded layouts
cmpSidebar.ShowHeader     = false
cmpSidebar.ShowToggle     = false
cmpSidebar.ShowUser       = false
cmpSidebar.ShowFooterMenu = false

// Nav fills from top to bottom with
// only the items list visible

With search bar

P
PowerAppsUI
Search...
Library
Components
Canvas
PCF
2
Starter Kits
3
Changelog
Account
Profile
Settings
RY
Rodas Yonass
rodas@powerappsui.com
Canvas
Active page content area
24
Components
8
Premium
16
Free
// Enable the search bar
cmpSidebar.ShowSearch = true

// The search input is only visible
// when the nav is expanded.
// Connect txtNavSearch.OnChange to
// filter your Items table:
cmpSidebar.Items = Filter(
    myNavItems,
    IsBlank(txtNavSearch.Text) ||
    Title in txtNavSearch.Text
)

Architecture

App-scoped variables (3)_cmpNavIsExpanded, _cmpNavSelID, _cmpNavFooterMenu, plus collection colNavExpanded. Initialize on each screen's OnVisible.

20 custom properties — 13 input, 2 output (IsExpanded, SelectedID), 5 events (OnNavSelect, OnToggle, OnFooterSettings, OnHelp, OnThemeToggle).

Width — snaps between 260px expanded and 64px collapsed via If(_cmpNavIsExpanded, 260, 64). Use cmpSidebar.Width to offset adjacent content containers.

cmpSidebar (Width = If(_cmpNavIsExpanded, 260, 64), Height = App.Height)
├── rctNavBg              — full-height background fill, Dark or Light
├── rctNavRightBorder     — 1px right border in accent tint
├── cntNavHeader          — 64px header, hidden when ShowHeader=false
│   ├── cntLogoMark       — 36×36 mark; Fill=AccentColor when AppLogo blank, transparent when set
│   │   ├── imgNavLogo        — AppLogo image, visible when AppLogo set
│   │   └── lblLogoInitial    — first letter of AppName, visible when AppLogo blank
│   ├── lblNavAppNameAccent — AppNameAccent in AccentColor
│   └── cntNavToggle      — 28×28 toggle pill (right-aligned)
│       ├── icoNavChevron — chevron icon, rotates on expand/collapse
│       └── btnNavToggle  — transparent hit target, fires OnToggle
├── rctHeaderDivider      — 1px horizontal divider below header
├── cntNavSearch          — 52px search bar container, ShowSearch only
│   └── cntSearchBox      — rounded search input
│       └── txtNavSearch  — Classic/TextInput
├── galNavItems           — vertical gallery, Items = Filter(...)
│   ├── lblNavSection     — section label row (IsSection=true)
│   ├── rctNavSectionLine — 1px divider inside section row
│   ├── rctNavItemBg      — selected item highlight background
│   ├── rctNavAccentBar   — 3×20 left accent bar (root selected only)
│   ├── rctTreeLine       — vertical line connector (child rows)
│   ├── cntTreeDot        — 8×8 dot connector (child rows)
│   ├── cntNavIconGlow    — 32×32 glow bloom (root selected only)
│   ├── cntNavIcon        — 28×28 icon container
│   │   ├── imgNavItemIcon    — SVG data URI image
│   │   └── lblNavIconFallback— letter fallback label
│   ├── lblNavItemTitle   — item label, hidden in collapsed mode
│   ├── icoNavParentChevron— expand/collapse chevron (parents only)
│   ├── cntNavBadgeDot    — 8px dot badge (BadgeDot=true)
│   ├── cntNavBadge       — pill badge (BadgeDot=false)
│   │   └── lblNavBadge   — badge number label
│   └── btnNavItem        — full-row transparent hit target
├── rctUserDivider        — 1px divider above footer
├── cntFooterMenu         — popup menu (3 rows + dividers), z-top
│   ├── btnFooterMenuCatchall — transparent backdrop
│   ├── cntFooterSettings → btnFooterSettings — fires OnFooterSettings
│   ├── cntFooterHelp     → btnFooterHelp     — fires OnHelp
│   └── cntFooterTheme    → btnFooterTheme    — fires OnThemeToggle
└── cntNavUser            — 64px user footer, ShowUser only
    ├── btnNavUserMenu    — opens/closes cntFooterMenu
    ├── cntUserAvatar     — 34×34 circle with user initials
    ├── lblUserName       — User().FullName
    ├── lblUserEmail      — User().Email
    └── icoFooterMenuDots — three-dot icon (expanded only)

Community

Use the toolbar to format · or type markdown directly