Introduce a footer-triggered Version History drawer with categorized release notes, hardcoded release data, and semver tracking at v0.3.0. Also ships blog blockquote/table styling, site-wide typography, home page image updates, header refinements, and related bug fixes. Co-authored-by: Cursor <cursoragent@cursor.com>
97 lines
2.9 KiB
TypeScript
97 lines
2.9 KiB
TypeScript
"use client";
|
|
|
|
import { motion, useReducedMotion } from "motion/react";
|
|
import { AGENT_FEATURE_CARDS, AGENT_WELCOME } from "./playground-content";
|
|
import { AgentSphere } from "./agent-sphere";
|
|
import {
|
|
agentCardVariant,
|
|
agentEase,
|
|
agentFadeUp,
|
|
agentStaggerContainer,
|
|
} from "./agent-motion";
|
|
import { FeatureCardIcon } from "./agent-thread";
|
|
import { cn } from "@/lib/utils";
|
|
import { type } from "@/lib/typography";
|
|
|
|
interface ChatEmptyStateProps {
|
|
onSelectStarter: (id: string, prompt: string) => void;
|
|
disabled?: boolean;
|
|
className?: string;
|
|
}
|
|
|
|
export function ChatEmptyState({
|
|
onSelectStarter,
|
|
disabled = false,
|
|
className,
|
|
}: ChatEmptyStateProps) {
|
|
const reduceMotion = useReducedMotion();
|
|
|
|
return (
|
|
<motion.div
|
|
className={cn(
|
|
"flex flex-1 flex-col items-center overflow-y-auto px-4 py-6 sm:px-6 sm:py-8",
|
|
className
|
|
)}
|
|
variants={agentStaggerContainer}
|
|
initial="hidden"
|
|
animate="visible"
|
|
exit="exit"
|
|
>
|
|
<AgentSphere />
|
|
|
|
<motion.h2
|
|
className={cn(type.h3, "mt-5 text-center")}
|
|
variants={agentFadeUp}
|
|
>
|
|
{AGENT_WELCOME.greeting}
|
|
</motion.h2>
|
|
<motion.p
|
|
className={cn(type["body-sm"], "mt-1.5 max-w-md text-center text-muted-foreground")}
|
|
variants={agentFadeUp}
|
|
>
|
|
{AGENT_WELCOME.subtitle}
|
|
</motion.p>
|
|
|
|
<motion.div
|
|
className="mt-8 grid w-full max-w-2xl gap-3 sm:grid-cols-2 lg:max-w-3xl"
|
|
variants={agentStaggerContainer}
|
|
>
|
|
{AGENT_FEATURE_CARDS.map((card) => (
|
|
<motion.button
|
|
key={card.id}
|
|
type="button"
|
|
disabled={disabled}
|
|
variants={agentCardVariant}
|
|
onClick={() => onSelectStarter(card.id, card.prompt)}
|
|
whileHover={
|
|
reduceMotion
|
|
? undefined
|
|
: { y: -3, scale: 1.015, transition: { duration: 0.22, ease: agentEase } }
|
|
}
|
|
whileTap={
|
|
reduceMotion
|
|
? undefined
|
|
: { scale: 0.97, transition: { duration: 0.14 } }
|
|
}
|
|
className={cn(
|
|
"group rounded-2xl border bg-card p-4 text-start shadow-sm",
|
|
"hover:border-primary/30 hover:shadow-md disabled:opacity-50",
|
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
)}
|
|
>
|
|
<motion.div
|
|
className="flex size-8 items-center justify-center rounded-lg bg-muted text-foreground"
|
|
whileHover={reduceMotion ? undefined : { scale: 1.08 }}
|
|
transition={{ type: "spring", stiffness: 400, damping: 22 }}
|
|
>
|
|
<FeatureCardIcon icon={card.icon} />
|
|
</motion.div>
|
|
<h3 className={cn(type["card-title"], "mt-3")}>{card.title}</h3>
|
|
<p className={cn(type["card-desc"], "mt-1")}>{card.description}</p>
|
|
</motion.button>
|
|
))}
|
|
</motion.div>
|
|
</motion.div>
|
|
);
|
|
}
|