Menu

Change language

GitHub repo

Toolbar Action Sidebar

blocklayout

App 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

$npx uipkge-ng@latest add sidebar-07
Manifest:https://uipkge.dev/r/angular/sidebar-07.jsonInstalls to:src/app/components/blocks/sidebar-07/

Variants

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>&#8984;</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

Raw manifest:https://uipkge.dev/r/angular/sidebar-07.json