{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "public-header", "title": "Public Header", "description": "Public-facing header with government banner, navigation bar, and command palette search (Cmd+K)", "dependencies": [ "lucide-react" ], "registryDependencies": [ "gov-banner", "command", "popover" ], "files": [ { "path": "registry/blocks/public-header/page.tsx", "content": "import { PublicHeader } from \"@/registry/blocks/public-header/components/public-header\"\n\nexport default function PublicHeaderDemo() {\n return (\n
\n \n\n
\n

\n Public Header Demo\n

\n

\n This is a demo of the Public Header component with default configuration.\n The header includes a government banner, main logo header, navigation bar,\n and a command palette (press ⌘K or Ctrl+K to open).\n

\n\n
\n

\n Configurable Props\n

\n
    \n
  • title - Header title text
  • \n
  • logoSrc - Path to logo image
  • \n
  • homeHref - Home link destination
  • \n
  • navLinks - Array of navigation links
  • \n
  • commandGroups - Command palette groups
  • \n
\n
\n
\n
\n )\n}\n", "type": "registry:page", "target": "app/public-header-demo/page.tsx" }, { "path": "registry/blocks/public-header/components/public-header.tsx", "content": "\"use client\"\n\nimport { useEffect, useState } from \"react\"\nimport Link from \"next/link\"\nimport { useRouter } from \"next/navigation\"\nimport {\n Search,\n ExternalLink,\n FileText,\n Twitter,\n Github,\n Linkedin,\n Home,\n LayoutGrid,\n type LucideIcon,\n} from \"lucide-react\"\nimport { GovBanner } from \"@/registry/ui/gov-banner\"\nimport {\n CommandDialog,\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n} from \"@/registry/ui/command\"\n\n// Types\nexport interface NavLink {\n label: string\n href: string\n external?: boolean\n}\n\nexport interface CommandItemType {\n label: string\n icon?: LucideIcon\n href?: string\n action?: () => void\n external?: boolean\n}\n\nexport interface CommandGroupType {\n heading: string\n items: CommandItemType[]\n}\n\nconst DEFAULT_NAV_LINKS: NavLink[] = [\n { label: \"COMPONENTS\", href: \"/demo\", external: false },\n { label: \"CV\", href: \"https://www.gregjohns.dev\", external: true },\n { label: \"GITHUB\", href: \"https://github.com/gjohnsx\", external: true },\n { label: \"LINKEDIN\", href: \"https://linkedin.com/in/greg-johns\", external: true },\n { label: \"X\", href: \"https://x.com/gjohnsx\", external: true },\n]\n\ninterface PublicHeaderProps {\n title?: string\n logoSrc?: string\n logoAlt?: string\n homeHref?: string\n navLinks?: NavLink[]\n commandGroups?: CommandGroupType[]\n}\n\nexport function PublicHeader({\n title = \"TTB Label Verification\",\n logoSrc = \"/logo/app-seal/treasury.png\",\n logoAlt = \"Treasury\",\n homeHref = \"/\",\n navLinks = DEFAULT_NAV_LINKS,\n commandGroups,\n}: PublicHeaderProps) {\n const [open, setOpen] = useState(false)\n const router = useRouter()\n\n useEffect(() => {\n const down = (e: KeyboardEvent) => {\n if (e.key === \"k\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault()\n setOpen((open) => !open)\n }\n }\n\n document.addEventListener(\"keydown\", down)\n return () => document.removeEventListener(\"keydown\", down)\n }, [])\n\n const runCommand = (command: () => void) => {\n setOpen(false)\n command()\n }\n\n // Default command groups if not provided\n const defaultCommandGroups: CommandGroupType[] = [\n {\n heading: \"Navigation\",\n items: [\n {\n label: \"Home\",\n icon: Home,\n action: () => router.push(homeHref),\n },\n {\n label: \"Components\",\n icon: LayoutGrid,\n action: () => router.push(\"/demo\"),\n },\n ],\n },\n {\n heading: \"About Gregory Johns\",\n items: [\n {\n label: \"Portfolio / CV\",\n icon: FileText,\n href: \"https://www.gregjohns.dev\",\n external: true,\n },\n {\n label: \"X\",\n icon: Twitter,\n href: \"https://x.com/gjohnsx\",\n external: true,\n },\n {\n label: \"GitHub\",\n icon: Github,\n href: \"https://github.com/gjohnsx\",\n external: true,\n },\n {\n label: \"LinkedIn\",\n icon: Linkedin,\n href: \"https://linkedin.com/in/greg-johns\",\n external: true,\n },\n ],\n },\n ]\n\n const groups = commandGroups ?? defaultCommandGroups\n\n return (\n
\n \n\n {/* Main header - dark navy */}\n
\n
\n \n \n {title}\n \n
\n
\n\n {/* Nav bar - slightly lighter blue */}\n \n\n \n \n \n \n No results found.\n\n {groups.map((group, groupIndex) => (\n
\n {groupIndex > 0 && }\n \n {group.items.map((item) => (\n \n runCommand(() => {\n if (item.action) {\n item.action()\n } else if (item.href) {\n if (item.external) {\n window.open(item.href, \"_blank\")\n } else {\n router.push(item.href)\n }\n }\n })\n }\n >\n {item.icon && }\n {item.label}\n {item.external && (\n \n )}\n \n ))}\n \n
\n ))}\n
\n
\n
\n
\n )\n}\n", "type": "registry:component" } ], "type": "registry:block" }