add empty screen and external links
This commit is contained in:
parent
f14e73ac8f
commit
398b671300
5 changed files with 136 additions and 10 deletions
|
|
@ -5,6 +5,7 @@ import { type Message } from "@prisma/client";
|
|||
import { ChatMessage } from "./chat-message";
|
||||
import { NextChatLogo } from "@/components/ui/nextchat-logo";
|
||||
import { Plus } from "lucide-react";
|
||||
import { EmptyScreen } from "./empty";
|
||||
|
||||
export interface ChatList {
|
||||
messages: Message[];
|
||||
|
|
@ -36,7 +37,9 @@ export function ChatList({ messages }: ChatList) {
|
|||
/>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
) : (
|
||||
<EmptyScreen />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
56
app/empty.tsx
Normal file
56
app/empty.tsx
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import { cn } from "@/lib/utils";
|
||||
import { ExternalLink } from "./external-link";
|
||||
import { fontMessage } from "@/lib/fonts";
|
||||
|
||||
function ExampleBubble({ children }: { children?: React.ReactNode }) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"flex-1 flex items-start justify-between p-4 rounded-lg relative bg-zinc-100 text-sm font-medium group hover:bg-zinc-200 hover transition-colors cursor-pointer select-none",
|
||||
fontMessage.className
|
||||
)}
|
||||
style={{}}
|
||||
>
|
||||
<div
|
||||
className="bg-zinc-100 group-hover:bg-zinc-200 w-9 h-6 absolute left-0 top-full -mt-[1px] scale-75 origin-top-left transition-colors"
|
||||
style={{
|
||||
clipPath:
|
||||
'path("M31.1838 0C24.9593 10.7604 13.3251 18 0 18C9.94113 18 18 9.94113 18 0H31.1838Z")',
|
||||
}}
|
||||
></div>
|
||||
<p>{children}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function EmptyScreen() {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"w-full h-full flex items-center justify-center pt-4 pb-8 pr-0 lg:pr-[260px] lg:pl-16"
|
||||
)}
|
||||
>
|
||||
<div className="p-8 rounded-lg flex flex-col items-center justify-center gap-8 max-w-2xl">
|
||||
<div className="flex items-center justify-center gap-6">
|
||||
<div className="text-zinc-500 font-medium">
|
||||
<p>Welcome to Next.js Chatbot!</p>
|
||||
<p className="mt-2">
|
||||
This is an open source AI chatbot app built with{" "}
|
||||
<ExternalLink href="https://nextjs.org">Next.js</ExternalLink> and{" "}
|
||||
<ExternalLink href="https://vercel.com/storage/postgres">
|
||||
Vercel Postgres
|
||||
</ExternalLink>
|
||||
. You can start a conversation here or try the following examples:
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid gap-x-4 gap-y-6 grid-cols-2 w-full">
|
||||
<ExampleBubble>Explain technical concepts</ExampleBubble>
|
||||
<ExampleBubble>Summarize article</ExampleBubble>
|
||||
<ExampleBubble>Get assistance</ExampleBubble>
|
||||
<ExampleBubble>Draft an email</ExampleBubble>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
29
app/external-link.tsx
Normal file
29
app/external-link.tsx
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
export function ExternalLink({
|
||||
href,
|
||||
children,
|
||||
}: {
|
||||
href: string;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<a
|
||||
href={href}
|
||||
target="_blank"
|
||||
className="inline-flex gap-1 hover:underline flex-1 justify-center leading-4"
|
||||
>
|
||||
<span>{children}</span>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
height="7"
|
||||
viewBox="0 0 6 6"
|
||||
width="7"
|
||||
className="opacity-70"
|
||||
>
|
||||
<path
|
||||
d="M1.25215 5.54731L0.622742 4.9179L3.78169 1.75597H1.3834L1.38936 0.890915H5.27615V4.78069H4.40513L4.41109 2.38538L1.25215 5.54731Z"
|
||||
fill="currentColor"
|
||||
></path>
|
||||
</svg>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import { Plus } from "lucide-react";
|
|||
import Link from "next/link";
|
||||
import { unstable_cache } from "next/cache";
|
||||
import { SidebarItem } from "./sidebar-item";
|
||||
import { ExternalLink } from "./external-link";
|
||||
|
||||
export interface SidebarProps {
|
||||
session?: Session;
|
||||
|
|
@ -48,6 +49,33 @@ export function Sidebar({ session, newChat }: SidebarProps) {
|
|||
<SidebarList session={session} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="flex gap-4 items-center justify-center text-sm font-medium leading-4 whitespace-nowrap">
|
||||
<a
|
||||
href="https://github.com/vercel/nextjs-ai-chatbot/"
|
||||
target="_blank"
|
||||
className="inline-flex gap-2 px-3 py-2 items-center border border-zinc-300 rounded-md hover:border-zinc-600 transition-colors"
|
||||
>
|
||||
<svg
|
||||
aria-label="Vercel logomark"
|
||||
height="13"
|
||||
role="img"
|
||||
className="w-auto overflow-hidden"
|
||||
viewBox="0 0 74 64"
|
||||
>
|
||||
<path
|
||||
d="M37.5896 0.25L74.5396 64.25H0.639648L37.5896 0.25Z"
|
||||
fill="var(--geist-foreground)"
|
||||
></path>
|
||||
</svg>
|
||||
<span>Deploy</span>
|
||||
</a>
|
||||
<ExternalLink href="https://github.com/vercel/nextjs-ai-chatbot/">
|
||||
View on GitHub
|
||||
</ExternalLink>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { useId } from "react";
|
||||
|
||||
export function NextChatLogo(props: JSX.IntrinsicElements["svg"]) {
|
||||
export function NextChatLogo(
|
||||
props: JSX.IntrinsicElements["svg"] & { inverted?: boolean }
|
||||
) {
|
||||
const id = useId();
|
||||
return (
|
||||
<svg
|
||||
|
|
@ -20,8 +22,12 @@ export function NextChatLogo(props: JSX.IntrinsicElements["svg"]) {
|
|||
y2="14.2667"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor="black" />
|
||||
<stop offset={1} stopColor="black" stopOpacity={0} />
|
||||
<stop stopColor={props.inverted ? "white" : "black"} />
|
||||
<stop
|
||||
offset={1}
|
||||
stopColor={props.inverted ? "white" : "black"}
|
||||
stopOpacity={0}
|
||||
/>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id={`gradient-${id}-2`}
|
||||
|
|
@ -31,14 +37,18 @@ export function NextChatLogo(props: JSX.IntrinsicElements["svg"]) {
|
|||
y2="9.50002"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor="black" />
|
||||
<stop offset={1} stopColor="black" stopOpacity={0} />
|
||||
<stop stopColor={props.inverted ? "white" : "black"} />
|
||||
<stop
|
||||
offset={1}
|
||||
stopColor={props.inverted ? "white" : "black"}
|
||||
stopOpacity={0}
|
||||
/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path
|
||||
d="M1 16L2.58314 11.2506C1.83084 9.74642 1.63835 8.02363 2.04013 6.39052C2.4419 4.75741 3.41171 3.32057 4.776 2.33712C6.1403 1.35367 7.81003 0.887808 9.4864 1.02289C11.1628 1.15798 12.7364 1.8852 13.9256 3.07442C15.1148 4.26363 15.842 5.83723 15.9771 7.5136C16.1122 9.18997 15.6463 10.8597 14.6629 12.224C13.6794 13.5883 12.2426 14.5581 10.6095 14.9599C8.97637 15.3616 7.25358 15.1692 5.74942 14.4169L1 16Z"
|
||||
fill="white"
|
||||
stroke="white"
|
||||
fill={props.inverted ? "black" : "white"}
|
||||
stroke={props.inverted ? "black" : "white"}
|
||||
strokeWidth={2}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
|
|
@ -52,10 +62,10 @@ export function NextChatLogo(props: JSX.IntrinsicElements["svg"]) {
|
|||
width={16}
|
||||
height={16}
|
||||
>
|
||||
<circle cx={9} cy={8} r={8} fill="white" />
|
||||
<circle cx={9} cy={8} r={8} fill={props.inverted ? "black" : "white"} />
|
||||
</mask>
|
||||
<g mask="url(#mask0_91_2047)">
|
||||
<circle cx={9} cy={8} r={8} fill="white" />
|
||||
<circle cx={9} cy={8} r={8} fill={props.inverted ? "black" : "white"} />
|
||||
<path
|
||||
d="M14.2896 14.0018L7.146 4.8H5.80005V11.1973H6.87681V6.16743L13.4444 14.6529C13.7407 14.4545 14.0231 14.2369 14.2896 14.0018Z"
|
||||
fill={`url(#gradient-${id}-1)`}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue