Toolbar Action Sidebar
blocklayoutApp sidebar with a bottom action bar -- workspace pill, ⌘K search, grouped nav with section labels (Dashboard / Management / Content), badge counts, user pill above an icon toolbar (Settings, Help, Notifications, Command, Log out). Built on sidebar-01.
Installation
$pnpm dlx uipkge-ng@latest add sidebar-07$npx uipkge-ng@latest add sidebar-07$yarn dlx uipkge-ng@latest add sidebar-07$bunx uipkge-ng@latest add sidebar-07Manifest:
https://uipkge.dev/r/angular/sidebar-07.jsonInstalls to:src/app/components/blocks/sidebar-07/Variants
Loading interactive previews…
Loading interactive previews…
npm dependencies
Files installed (2)
src/app/components/blocks/sidebar-07/sidebar-07.component.ts13.1 kB
// App sidebar with a bottom action bar. Workspace pill + search at the top, // three grouped nav sections, user pill above an icon toolbar (Settings, // Help, Notifications, Command palette, theme toggle) anchored at the very // bottom. Every row is spelled out inline so you can edit in place. // Port of the Vue/React block 1:1. import { ChangeDetectionStrategy, Component, computed, signal } from '@angular/core' import { Bell, ChartBar, ChevronsUpDown, Command, CreditCard, FileText, HelpCircle, LineChart, LucideAngularModule, Mail, Moon, Package, Plus, Search, Settings as SettingsIcon, ShoppingCart, Sun, Users, } from 'lucide-angular' import { injectTheme } from '@/lib/use-theme' import { UiAvatarComponent, UiAvatarFallbackComponent } from '@/ui/avatar/avatar.component' import { UiInputComponent } from '@/ui/input/input.component' import { UiSidebarComponent, UiSidebarContentComponent, UiSidebarFooterComponent, UiSidebarGroupActionComponent, UiSidebarGroupComponent, UiSidebarGroupContentComponent, UiSidebarGroupLabelComponent, UiSidebarHeaderComponent, UiSidebarMenuBadgeComponent, UiSidebarMenuButtonComponent, UiSidebarMenuComponent, UiSidebarMenuItemComponent, UiSidebarRailComponent, UiSidebarSeparatorComponent, UiSidebarTriggerComponent, injectSidebar, } from '@/ui/sidebar/sidebar.component' @Component({ changeDetection: ChangeDetectionStrategy.Eager, selector: 'ui-sidebar-07, [ui-sidebar-07]', standalone: true, // React renders <Sidebar> itself: keep this wrapper out of the provider's flex layout. host: { class: 'contents' }, imports: [ LucideAngularModule, UiAvatarComponent, UiAvatarFallbackComponent, UiSidebarComponent, UiSidebarContentComponent, UiSidebarFooterComponent, UiSidebarGroupActionComponent, UiSidebarGroupComponent, UiSidebarGroupContentComponent, UiSidebarGroupLabelComponent, UiSidebarHeaderComponent, UiInputComponent, UiSidebarMenuBadgeComponent, UiSidebarMenuButtonComponent, UiSidebarMenuComponent, UiSidebarMenuItemComponent, UiSidebarRailComponent, UiSidebarSeparatorComponent, UiSidebarTriggerComponent, ], template: ` <ui-sidebar data-slot="sidebar-07" collapsible="icon"> <ui-sidebar-header> <ul ui-sidebar-menu> <li ui-sidebar-menu-item> <button ui-sidebar-menu-button size="lg" tooltip="uipkge" class="group-data-[collapsible=icon]:!justify-center" > <div class="bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 shrink-0 items-center justify-center rounded-lg group-data-[collapsible=icon]:size-6" > <svg viewBox="0 0 24 24" class="size-4 group-data-[collapsible=icon]:size-3.5" fill="currentColor" aria-hidden="true" > <rect x="2" y="2" width="9" height="9" rx="1.5" /> <rect x="13" y="2" width="9" height="9" rx="1.5" opacity="0.55" /> <rect x="2" y="13" width="9" height="9" rx="1.5" opacity="0.55" /> <rect x="13" y="13" width="9" height="9" rx="1.5" /> </svg> </div> <div class="grid flex-1 text-left text-sm leading-tight group-data-[collapsible=icon]:hidden"> <span class="font-display truncate font-semibold">uipkge</span> <span class="text-muted-foreground truncate text-xs">uipkge.dev</span> </div> </button> </li> </ul> <div class="px-1 pt-1 group-data-[collapsible=icon]:hidden"> <ui-input type="text" placeholder="Search..." allowClear [prefix]="searchPrefix" [suffix]="searchSuffix" class="bg-background h-8 w-full shadow-none" /> <ng-template #searchPrefix> <lucide-icon [img]="Search" class="text-muted-foreground size-3.5" /> </ng-template> <ng-template #searchSuffix> <kbd class="bg-muted text-muted-foreground pointer-events-none inline-flex h-5 items-center gap-0.5 rounded border px-1 font-mono text-xs font-medium select-none" > <span>⌘</span>K </kbd> </ng-template> </div> </ui-sidebar-header> <ui-sidebar-content> <ui-sidebar-group> <ui-sidebar-group-label>Dashboard</ui-sidebar-group-label> <ui-sidebar-group-content> <ul ui-sidebar-menu> <li ui-sidebar-menu-item> <!-- Active row gets a subtle success-tinted treatment to mark it without competing with the rest of the nav. --> <button ui-sidebar-menu-button [isActive]="true" tooltip="Analytics" class="data-[active=true]:!bg-success/20 data-[active=true]:!text-foreground" > <lucide-icon [img]="ChartBar" class="size-4" /> <span>Analytics</span> </button> </li> <li ui-sidebar-menu-item> <button ui-sidebar-menu-button tooltip="Performance"> <lucide-icon [img]="LineChart" class="size-4" /> <span>Performance</span> </button> </li> </ul> </ui-sidebar-group-content> </ui-sidebar-group> <ui-sidebar-group> <ui-sidebar-group-label>Management</ui-sidebar-group-label> <ui-sidebar-group-content> <ul ui-sidebar-menu> <li ui-sidebar-menu-item> <button ui-sidebar-menu-button tooltip="Products"> <lucide-icon [img]="Package" class="size-4" /> <span>Products</span> </button> </li> <li ui-sidebar-menu-item> <button ui-sidebar-menu-button tooltip="Orders"> <lucide-icon [img]="ShoppingCart" class="size-4" /> <span>Orders</span> </button> </li> <li ui-sidebar-menu-item> <button ui-sidebar-menu-button tooltip="Subscribers"> <lucide-icon [img]="Users" class="size-4" /> <span>Subscribers</span> </button> </li> <li ui-sidebar-menu-item> <button ui-sidebar-menu-button tooltip="Transactions"> <lucide-icon [img]="CreditCard" class="size-4" /> <span>Transactions</span> </button> </li> </ul> </ui-sidebar-group-content> </ui-sidebar-group> <ui-sidebar-group> <ui-sidebar-group-label>Content</ui-sidebar-group-label> <button ui-sidebar-group-action aria-label="Add content"> <lucide-icon [img]="Plus" class="size-4" /> </button> <ui-sidebar-group-content> <ul ui-sidebar-menu> <li ui-sidebar-menu-item> <button ui-sidebar-menu-button tooltip="Posts"> <lucide-icon [img]="FileText" class="size-4" /> <span>Posts</span> </button> <span ui-sidebar-menu-badge class="bg-destructive text-white">10</span> </li> <li ui-sidebar-menu-item> <button ui-sidebar-menu-button tooltip="Pages"> <lucide-icon [img]="Mail" class="size-4" /> <span>Pages</span> </button> </li> </ul> </ui-sidebar-group-content> </ui-sidebar-group> </ui-sidebar-content> <ui-sidebar-footer> <ul ui-sidebar-menu> <li ui-sidebar-menu-item> <button ui-sidebar-menu-button size="lg" class="group-data-[collapsible=icon]:!justify-center"> <ui-avatar class="size-8 rounded-lg group-data-[collapsible=icon]:size-6"> <ui-avatar-fallback class="bg-sidebar-accent text-sidebar-accent-foreground rounded-lg text-xs"> SW </ui-avatar-fallback> </ui-avatar> <div class="grid flex-1 text-left text-sm leading-tight group-data-[collapsible=icon]:hidden"> <span class="truncate font-medium">Sarah Wilson</span> <span class="text-muted-foreground truncate text-xs">Admin Account</span> </div> <lucide-icon [img]="ChevronsUpDown" class="ml-auto size-4 group-data-[collapsible=icon]:hidden" /> </button> </li> </ul> @if (sidebar.state === 'expanded') { <ui-sidebar-separator class="my-1" /> <!-- Action toolbar -- evenly spaced quick icons. Last button is the SidebarTrigger collapse toggle. Replace others with router links / (click) handlers as needed. --> <div class="flex items-center justify-between px-1 pb-1"> <button type="button" aria-label="Settings" class="text-muted-foreground hover:bg-sidebar-accent hover:text-foreground flex aspect-square size-8 items-center justify-center rounded-md transition-colors" > <lucide-icon [img]="SettingsIcon" class="size-4" /> </button> <button type="button" aria-label="Help" class="text-muted-foreground hover:bg-sidebar-accent hover:text-foreground flex aspect-square size-8 items-center justify-center rounded-md transition-colors" > <lucide-icon [img]="HelpCircle" class="size-4" /> </button> <button type="button" aria-label="Notifications" class="text-muted-foreground hover:bg-sidebar-accent hover:text-foreground flex aspect-square size-8 items-center justify-center rounded-md transition-colors" > <lucide-icon [img]="Bell" class="size-4" /> </button> <button type="button" aria-label="Command palette" class="text-muted-foreground hover:bg-sidebar-accent hover:text-foreground flex aspect-square size-8 items-center justify-center rounded-md transition-colors" > <lucide-icon [img]="Command" class="size-4" /> </button> <button type="button" [attr.aria-label]="isDark() ? 'Switch to light theme' : 'Switch to dark theme'" class="text-muted-foreground hover:bg-sidebar-accent hover:text-foreground flex aspect-square size-8 items-center justify-center rounded-md transition-colors" (click)="toggleTheme()" > @if (isDark()) { <lucide-icon [img]="Sun" class="size-4" /> } @else { <lucide-icon [img]="Moon" class="size-4" /> } </button> <button ui-sidebar-trigger class="text-muted-foreground hover:bg-sidebar-accent hover:text-foreground size-8 rounded-md" ></button> </div> } @else { <!-- Collapsed-state: surface the trigger on its own so the rail always has an expand affordance. --> <div class="flex items-center justify-center pb-1"> <button ui-sidebar-trigger class="text-muted-foreground hover:bg-sidebar-accent hover:text-foreground size-8 rounded-md" ></button> </div> } </ui-sidebar-footer> <ui-sidebar-rail /> </ui-sidebar> `, }) export class UiSidebar07Component { protected readonly Bell = Bell protected readonly ChartBar = ChartBar protected readonly ChevronsUpDown = ChevronsUpDown protected readonly Command = Command protected readonly CreditCard = CreditCard protected readonly FileText = FileText protected readonly HelpCircle = HelpCircle protected readonly LineChart = LineChart protected readonly Mail = Mail protected readonly Moon = Moon protected readonly Package = Package protected readonly Plus = Plus protected readonly Search = Search protected readonly SettingsIcon = SettingsIcon protected readonly ShoppingCart = ShoppingCart protected readonly Sun = Sun protected readonly Users = Users protected readonly sidebar = injectSidebar() private readonly theme = injectTheme() private readonly mounted = signal(false) readonly isDark = computed(() => { if (!this.mounted()) return false if (typeof window === 'undefined') return this.theme.resolvedTheme() === 'dark' const t = this.theme.theme() return t === 'dark' || (t === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches) }) constructor() { // Flip after first render so SSR + first client paint agree on the Sun/Moon icon. queueMicrotask(() => this.mounted.set(true)) } toggleTheme(): void { this.theme.setTheme(this.isDark() ? 'light' : 'dark') } }src/app/components/blocks/sidebar-07/index.ts0.1 kB
export { UiSidebar07Component } from './sidebar-07.component'
Raw manifest:https://uipkge.dev/r/angular/sidebar-07.json