| 'use client'; | |
| import Link from 'next/link'; | |
| import { useRouter } from 'next/navigation'; | |
| import { useWindowSize } from 'usehooks-ts'; | |
| import { ModelSelector } from '@/components/model-selector'; | |
| import { SidebarToggle } from '@/components/sidebar-toggle'; | |
| import { Button } from '@/components/ui/button'; | |
| import { PlusIcon, VercelIcon } from './icons'; | |
| import { useSidebar } from './ui/sidebar'; | |
| import { memo } from 'react'; | |
| import { Tooltip, TooltipContent, TooltipTrigger } from './ui/tooltip'; | |
| import { type VisibilityType, VisibilitySelector } from './visibility-selector'; | |
| import type { Session } from 'next-auth'; | |
| function PureChatHeader({ | |
| chatId, | |
| selectedModelId, | |
| selectedVisibilityType, | |
| isReadonly, | |
| session, | |
| }: { | |
| chatId: string; | |
| selectedModelId: string; | |
| selectedVisibilityType: VisibilityType; | |
| isReadonly: boolean; | |
| session: Session; | |
| }) { | |
| const router = useRouter(); | |
| const { open } = useSidebar(); | |
| const { width: windowWidth } = useWindowSize(); | |
| return ( | |
| <header className="flex sticky top-0 bg-background py-3 items-center px-4 gap-2 border-b"> | |
| <SidebarToggle /> | |
| <div className="flex items-center ml-auto gap-2"> | |
| {(!open || windowWidth < 768) && ( | |
| <Tooltip> | |
| <TooltipTrigger asChild> | |
| <Button | |
| variant="outline" | |
| size="icon" | |
| className="size-9" | |
| onClick={() => { | |
| router.push('/'); | |
| router.refresh(); | |
| }} | |
| > | |
| <PlusIcon size={16} /> | |
| <span className="sr-only">New Chat</span> | |
| </Button> | |
| </TooltipTrigger> | |
| <TooltipContent>New Chat</TooltipContent> | |
| </Tooltip> | |
| )} | |
| {!isReadonly && ( | |
| <ModelSelector | |
| session={session} | |
| selectedModelId={selectedModelId} | |
| className="h-9" | |
| /> | |
| )} | |
| {!isReadonly && ( | |
| <VisibilitySelector | |
| chatId={chatId} | |
| selectedVisibilityType={selectedVisibilityType} | |
| className="h-9" | |
| /> | |
| )} | |
| <Button | |
| className="hidden md:flex h-9 px-3 text-sm bg-zinc-900 dark:bg-zinc-100 hover:bg-zinc-800 dark:hover:bg-zinc-200 text-zinc-50 dark:text-zinc-900" | |
| asChild | |
| > | |
| <Link | |
| href={`https://vercel.com/new/clone?repository-url=https://github.com/vercel/ai-chatbot&env=AUTH_SECRET&envDescription=Learn more about how to get the API Keys for the application&envLink=https://github.com/vercel/ai-chatbot/blob/main/.env.example&demo-title=AI Chatbot&demo-description=An Open-Source AI Chatbot Template Built With Next.js and the AI SDK by Vercel.&demo-url=https://chat.vercel.ai&products=[{"type":"integration","protocol":"ai","productSlug":"grok","integrationSlug":"xai"},{"type":"integration","protocol":"storage","productSlug":"neon","integrationSlug":"neon"},{"type":"integration","protocol":"storage","productSlug":"upstash-kv","integrationSlug":"upstash"},{"type":"blob"}]`} | |
| target="_noblank" | |
| > | |
| <VercelIcon size={14} className="mr-2" /> | |
| Deploy | |
| </Link> | |
| </Button> | |
| </div> | |
| </header> | |
| ); | |
| } | |
| export const ChatHeader = memo(PureChatHeader, (prevProps, nextProps) => { | |
| return prevProps.selectedModelId === nextProps.selectedModelId; | |
| }); | |