Header — Inline Search
blockmarketingNavbar with an inline search trigger that opens a command palette on click or ⌘K, listing grouped results with keyboard hints alongside the usual nav links and CTA.
Installation
$pnpm dlx uipkge-ng@latest add header-search-command$npx uipkge-ng@latest add header-search-command$yarn dlx uipkge-ng@latest add header-search-command$bunx uipkge-ng@latest add header-search-commandManifest:
https://uipkge.dev/r/angular/header-search-command.jsonInstalls to:src/app/components/blocks/header-search-command/Variants
Loading interactive previews…
Loading interactive previews…
Schema
Type aliases exported from this item's source. Use these to shape the data you pass in.
HeaderSearchLinkinterface HeaderSearchLink {
label: string
href: string
}HeaderSearchIteminterface HeaderSearchItem {
icon: LucideIconData
label: string
}HeaderSearchGroupinterface HeaderSearchGroup {
heading: string
items: HeaderSearchItem[]
}Files installed (2)
src/app/components/blocks/header-search-command/header-search-command.component.ts7 kB
// Navbar with an inline search trigger that opens a command palette on click or ⌘K, // listing grouped results with keyboard hints alongside nav links and CTA. // Port of the React block 1:1. import { ChangeDetectionStrategy, Component, Input, signal } from '@angular/core' import { BarChart3, BookOpen, Compass, FileText, History, LucideAngularModule, Menu, Search, Users, type LucideIconData, } from 'lucide-angular' import { cn } from '@/lib/utils' import { UiButtonComponent } from '@/ui/button/button.component' import { UiCommandDialogComponent, UiCommandEmptyComponent, UiCommandGroupComponent, UiCommandInputComponent, UiCommandItemComponent, UiCommandListComponent, } from '@/ui/command/command.component' import { UiKbdComponent } from '@/ui/kbd/kbd.component' import { UiSeparatorComponent } from '@/ui/separator/separator.component' import { UiSheetComponent, UiSheetContentComponent, UiSheetHeaderComponent, UiSheetTitleComponent, UiSheetTriggerComponent, } from '@/ui/sheet/sheet.component' interface HeaderSearchLink { label: string href: string } interface HeaderSearchItem { icon: LucideIconData label: string } interface HeaderSearchGroup { heading: string items: HeaderSearchItem[] } const links: HeaderSearchLink[] = [ { label: 'Product', href: '#product' }, { label: 'Pricing', href: '#pricing' }, { label: 'Docs', href: '#docs' }, ] const groups: HeaderSearchGroup[] = [ { heading: 'Documentation', items: [ { icon: BookOpen, label: 'Connect a warehouse' }, { icon: FileText, label: 'Define your first metric' }, { icon: BarChart3, label: 'Publish a dashboard' }, ], }, { heading: 'Company', items: [ { icon: Users, label: 'Customer stories' }, { icon: History, label: 'Changelog' }, ], }, ] @Component({ changeDetection: ChangeDetectionStrategy.Eager, selector: 'ui-header-search-command, [ui-header-search-command]', standalone: true, // React renders the root <header> itself: the host stays out of layout and `class` goes to the root. host: { '[attr.class]': '"contents"', '(window:keydown)': 'onKeydown($event)' }, imports: [ LucideAngularModule, UiButtonComponent, UiCommandDialogComponent, UiCommandEmptyComponent, UiCommandGroupComponent, UiCommandInputComponent, UiCommandItemComponent, UiCommandListComponent, UiKbdComponent, UiSeparatorComponent, UiSheetComponent, UiSheetContentComponent, UiSheetHeaderComponent, UiSheetTitleComponent, UiSheetTriggerComponent, ], template: ` <header data-slot="header-search-command" [class]="rootClass"> <div class="mx-auto flex h-16 max-w-6xl items-center gap-4 px-6"> <a href="#top" class="flex shrink-0 items-center gap-2 font-semibold tracking-tight"> <lucide-icon [img]="Compass" class="text-primary size-5" /> Halden </a> <nav class="hidden items-center gap-1 md:flex" aria-label="Primary"> @for (link of navLinks; track link.href) { <a [href]="link.href" class="text-muted-foreground hover:text-foreground hover:bg-muted focus-visible:ring-ring rounded-md px-3 py-1.5 text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none" > {{ link.label }} </a> } </nav> <!-- Trigger is a button, not an input: the real field lives in the dialog, so focus lands there and the shortcut hint stays visible until then. --> <button type="button" class="border-border bg-muted/40 text-muted-foreground hover:bg-muted focus-visible:ring-ring ml-auto flex h-9 w-full max-w-64 items-center gap-2 rounded-md border px-3 text-sm transition-colors focus-visible:ring-2 focus-visible:outline-none" (click)="open.set(true)" > <lucide-icon [img]="Search" class="size-4 shrink-0" /> <span class="truncate">Search docs…</span> <span ui-kbd class="ml-auto hidden sm:inline-flex">⌘K</span> </button> <ui-separator orientation="vertical" class="hidden h-5 md:block" /> <button ui-button size="sm" class="hidden shrink-0 sm:inline-flex">Start free</button> <div ui-sheet [open]="menuOpen()" (openChange)="menuOpen.set($event)"> <button ui-button ui-sheet-trigger variant="ghost" size="icon" class="shrink-0 md:hidden" aria-label="Open navigation menu" > <lucide-icon [img]="Menu" class="size-5" /> </button> <div ui-sheet-content side="right" class="w-72"> <div ui-sheet-header> <h2 ui-sheet-title>Menu</h2> </div> <nav class="mt-6 grid gap-1" aria-label="Mobile"> @for (link of navLinks; track link.href) { <a [href]="link.href" class="hover:bg-muted rounded-md px-3 py-2 text-sm font-medium transition-colors" (click)="menuOpen.set(false)" > {{ link.label }} </a> } </nav> <ui-separator class="my-5" /> <div class="grid gap-2"> <button ui-button variant="outline">Sign in</button> <button ui-button>Start free</button> </div> </div> </div> </div> <ui-command-dialog [open]="open()" (openChange)="open.set($event)" title="Search documentation" description="Search documentation, guides, and stories" > <ui-command-input placeholder="Search documentation, guides, and stories…" /> <ui-command-list> <ui-command-empty>No results.</ui-command-empty> @for (group of searchGroups; track group.heading) { <ui-command-group [heading]="group.heading"> @for (item of group.items; track item.label) { <ui-command-item [value]="item.label" (select)="open.set(false)"> <lucide-icon [img]="item.icon" class="text-muted-foreground mr-2 size-4" /> {{ item.label }} </ui-command-item> } </ui-command-group> } </ui-command-list> </ui-command-dialog> </header> `, }) export class UiHeaderSearchCommandComponent { protected readonly Compass = Compass protected readonly Menu = Menu protected readonly Search = Search protected readonly navLinks = links protected readonly searchGroups = groups @Input('class') className?: string readonly open = signal(false) readonly menuOpen = signal(false) get rootClass(): string { return cn('border-border bg-background/90 border-b backdrop-blur', this.className) } onKeydown(event: KeyboardEvent): void { if (event.key.toLowerCase() !== 'k' || !(event.metaKey || event.ctrlKey)) return event.preventDefault() this.open.update((v) => !v) } }src/app/components/blocks/header-search-command/index.ts0.1 kB
export { UiHeaderSearchCommandComponent } from './header-search-command.component'
Raw manifest:https://uipkge.dev/r/angular/header-search-command.json