Documentation Sidebar
blocklayoutDocs-style sidebar with a version switcher at the top, a search input below, and collapsible navigation groups. All sample data inlined so consumers edit routes in place.
Installation
$pnpm dlx uipkge-ng@latest add sidebar-03$npx uipkge-ng@latest add sidebar-03$yarn dlx uipkge-ng@latest add sidebar-03$bunx uipkge-ng@latest add sidebar-03Manifest:
https://uipkge.dev/r/angular/sidebar-03.jsonInstalls to:src/app/components/blocks/sidebar-03/Variants
Loading interactive previews…
Loading interactive previews…
npm dependencies
Files installed (4)
src/app/components/blocks/sidebar-03/sidebar-03.component.ts5.8 kB
// Docs-style sidebar: version switcher + search in the header, collapsible nav groups // below. All sample data inlined so consumers edit routes in place. // Port of the React block 1:1. import { ChangeDetectionStrategy, Component } from '@angular/core' import { ChevronRight, LucideAngularModule } from 'lucide-angular' import { UiCollapsibleComponent, UiCollapsibleContentComponent, UiCollapsibleTriggerComponent, } from '@/ui/collapsible/collapsible.component' import { UiSidebarComponent, UiSidebarContentComponent, UiSidebarGroupComponent, UiSidebarGroupContentComponent, UiSidebarGroupLabelComponent, UiSidebarHeaderComponent, UiSidebarMenuButtonComponent, UiSidebarMenuComponent, UiSidebarMenuItemComponent, UiSidebarRailComponent, } from '@/ui/sidebar/sidebar.component' import { Sidebar03SearchFormComponent } from './search-form.component' import { Sidebar03VersionSwitcherComponent } from './version-switcher.component' // This is sample data. const data: { versions: string[] navMain: { title: string url: string items: { title: string; url: string; isActive?: boolean }[] }[] } = { versions: ['1.0.1', '1.1.0-alpha', '2.0.0-beta1'], navMain: [ { title: 'Getting Started', url: '#', items: [ { title: 'Installation', url: '#' }, { title: 'Project Structure', url: '#' }, ], }, { title: 'Building Your Application', url: '#', items: [ { title: 'Routing', url: '#' }, { title: 'Data Fetching', url: '#', isActive: true }, { title: 'Rendering', url: '#' }, { title: 'Caching', url: '#' }, { title: 'Styling', url: '#' }, { title: 'Optimizing', url: '#' }, { title: 'Configuring', url: '#' }, { title: 'Testing', url: '#' }, { title: 'Authentication', url: '#' }, { title: 'Deploying', url: '#' }, { title: 'Upgrading', url: '#' }, { title: 'Examples', url: '#' }, ], }, { title: 'API Reference', url: '#', items: [ { title: 'Components', url: '#' }, { title: 'File Conventions', url: '#' }, { title: 'Functions', url: '#' }, { title: 'next.config.js Options', url: '#' }, { title: 'CLI', url: '#' }, { title: 'Edge Runtime', url: '#' }, ], }, { title: 'Architecture', url: '#', items: [ { title: 'Accessibility', url: '#' }, { title: 'Fast Refresh', url: '#' }, { title: 'Next.js Compiler', url: '#' }, { title: 'Supported Browsers', url: '#' }, { title: 'Turbopack', url: '#' }, ], }, { title: 'Community', url: '#', items: [{ title: 'Contribution Guide', url: '#' }], }, ], } /** * Sidebar03 -- the React block, 1:1: a default Sidebar with a VersionSwitcher + * SearchForm header and collapsible nav groups (all open). It reads the surrounding * <ui-sidebar-provider> (pair with <ui-sidebar-inset> + <ui-sidebar-trigger>). * Edit `data` to change versions and routes. */ @Component({ changeDetection: ChangeDetectionStrategy.Eager, selector: 'ui-sidebar-03, [ui-sidebar-03]', standalone: true, // React renders <Sidebar> itself: keep this wrapper out of the provider's flex layout. host: { class: 'contents' }, imports: [ LucideAngularModule, UiCollapsibleComponent, UiCollapsibleTriggerComponent, UiCollapsibleContentComponent, UiSidebarComponent, UiSidebarHeaderComponent, UiSidebarContentComponent, UiSidebarGroupComponent, UiSidebarGroupLabelComponent, UiSidebarGroupContentComponent, UiSidebarMenuComponent, UiSidebarMenuItemComponent, UiSidebarMenuButtonComponent, UiSidebarRailComponent, Sidebar03SearchFormComponent, Sidebar03VersionSwitcherComponent, ], template: ` <ui-sidebar> <ui-sidebar-header> <sidebar-03-version-switcher [versions]="data.versions" [defaultVersion]="data.versions[0]!" /> <sidebar-03-search-form /> </ui-sidebar-header> <ui-sidebar-content class="gap-0"> @for (item of data.navMain; track item.title) { <!-- Angular's group label has no asChild slot: the trigger carries the label's hover classes so the whole row stays clickable, like React's asChild. --> <div ui-collapsible [attr.title]="item.title" defaultOpen class="group/collapsible"> <ui-sidebar-group> <ui-sidebar-group-label class="group/label text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground text-sm" > <button type="button" ui-collapsible-trigger class="flex w-full items-center gap-2 text-left"> {{ item.title }} <lucide-icon [img]="ChevronRight" class="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-90" /> </button> </ui-sidebar-group-label> <ui-collapsible-content> <ui-sidebar-group-content> <ul ui-sidebar-menu> @for (childItem of item.items; track childItem.title) { <li ui-sidebar-menu-item> <a ui-sidebar-menu-button [href]="childItem.url" [isActive]="!!childItem.isActive"> <span>{{ childItem.title }}</span> </a> </li> } </ul> </ui-sidebar-group-content> </ui-collapsible-content> </ui-sidebar-group> </div> } </ui-sidebar-content> <button ui-sidebar-rail></button> </ui-sidebar> `, }) export class UiSidebar03Component { readonly data = data protected readonly ChevronRight = ChevronRight }src/app/components/blocks/sidebar-03/search-form.component.ts1.6 kB
// Docs search field: a labelled input with a search prefix and clear button. // Port of the React SearchForm 1:1 (which uses SidebarInput with prefix + allowClear; // the Angular sidebar input has no prefix slot, so ui-input carries the same styling). import { ChangeDetectionStrategy, Component } from '@angular/core' import { Search, LucideAngularModule } from 'lucide-angular' import { UiLabelComponent } from '@/ui/label/label.component' import { UiInputComponent } from '@/ui/input/input.component' import { UiSidebarGroupComponent, UiSidebarGroupContentComponent } from '@/ui/sidebar/sidebar.component' @Component({ changeDetection: ChangeDetectionStrategy.Eager, selector: 'sidebar-03-search-form', standalone: true, host: { class: 'contents' }, imports: [ LucideAngularModule, UiLabelComponent, UiInputComponent, UiSidebarGroupComponent, UiSidebarGroupContentComponent, ], template: ` <form data-slot="sidebar-03"> <ui-sidebar-group class="py-0"> <ui-sidebar-group-content> <label ui-label for="search" class="sr-only">Search</label> <ui-input id="search" type="text" placeholder="Search the docs..." allowClear [prefix]="searchPrefix" 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> </ui-sidebar-group-content> </ui-sidebar-group> </form> `, }) export class Sidebar03SearchFormComponent { protected readonly Search = Search }src/app/components/blocks/sidebar-03/version-switcher.component.ts3.2 kB
// Docs version picker: brand mark + name + selected version, opening a dropdown of // versions with a check on the active one. Port of the React VersionSwitcher 1:1. import { ChangeDetectionStrategy, Component, Input, OnInit, signal } from '@angular/core' import { Check, ChevronsUpDown, LucideAngularModule } from 'lucide-angular' import { UiDropdownMenuComponent, UiDropdownMenuContentComponent, UiDropdownMenuItemComponent, UiDropdownMenuTriggerComponent, } from '@/ui/dropdown-menu/dropdown-menu.component' import { UiSidebarMenuButtonComponent, UiSidebarMenuComponent, UiSidebarMenuItemComponent, } from '@/ui/sidebar/sidebar.component' @Component({ changeDetection: ChangeDetectionStrategy.Eager, selector: 'sidebar-03-version-switcher', standalone: true, host: { class: 'contents' }, imports: [ LucideAngularModule, UiDropdownMenuComponent, UiDropdownMenuTriggerComponent, UiDropdownMenuContentComponent, UiDropdownMenuItemComponent, UiSidebarMenuComponent, UiSidebarMenuItemComponent, UiSidebarMenuButtonComponent, ], template: ` <ul ui-sidebar-menu data-slot="sidebar-03"> <li ui-sidebar-menu-item> <ui-dropdown-menu> <button type="button" ui-sidebar-menu-button ui-dropdown-menu-trigger size="lg" class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground" > <div class="bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 items-center justify-center rounded-lg" > <svg viewBox="0 0 24 24" class="size-4" 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="flex flex-col gap-0.5 leading-none"> <span class="font-medium">uipkge</span> <span class="">v{{ selectedVersion() }}</span> </div> <lucide-icon [img]="ChevronsUpDown" class="ml-auto" /> </button> <ui-dropdown-menu-content class="w-(--radix-dropdown-menu-trigger-width)" align="start"> @for (version of versions; track version) { <ui-dropdown-menu-item (select)="selectedVersion.set(version)"> v{{ version }} @if (selectedVersion() === version) { <lucide-icon [img]="Check" class="ml-auto" /> } </ui-dropdown-menu-item> } </ui-dropdown-menu-content> </ui-dropdown-menu> </li> </ul> `, }) export class Sidebar03VersionSwitcherComponent implements OnInit { @Input() versions: string[] = [] @Input() defaultVersion = '' readonly selectedVersion = signal('') protected readonly Check = Check protected readonly ChevronsUpDown = ChevronsUpDown ngOnInit(): void { this.selectedVersion.set(this.defaultVersion) } }src/app/components/blocks/sidebar-03/index.ts0.2 kB
export { UiSidebar03Component } from './sidebar-03.component' export { Sidebar03SearchFormComponent } from './search-form.component' export { Sidebar03VersionSwitcherComponent } from './version-switcher.component'
Raw manifest:https://uipkge.dev/r/angular/sidebar-03.json