Files
aragrp/components/playground/agent-preview-panel.tsx
T
alirez.brandCursor a47ec493c5 feat: add version history drawer with release notes
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>
2026-07-02 02:46:20 +03:30

191 lines
6.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { FileText, Mail, Plus, X } from "lucide-react";
import { motion } from "motion/react";
import { Button } from "@/components/ui/button";
import {
AGENT_AUDIENCE_TAGS,
AGENT_PREVIEW_TAGS,
AGENT_WORKSPACE_TITLE,
} from "./playground-content";
import {
agentFadeUp,
agentLayoutTransition,
agentSlideInEnd,
agentStaggerContainer,
} from "./agent-motion";
import { cn } from "@/lib/utils";
import { type } from "@/lib/typography";
interface AgentPreviewPanelProps {
className?: string;
onClose?: () => void;
}
function TagChip({ label }: { label: string }) {
return (
<motion.span
className={cn(
"inline-flex items-center gap-1 rounded-md border bg-muted/60 px-2 py-1",
type.caption
)}
variants={agentFadeUp}
custom={index}
>
{label}
<X className="size-3 opacity-50" aria-hidden />
</motion.span>
);
}
function AudienceSection({
title,
tags,
}: {
title: string;
tags: readonly string[];
}) {
return (
<motion.div className="space-y-2" variants={agentFadeUp}>
<p className={cn(type.caption, "font-medium uppercase tracking-wide text-muted-foreground")}>
{title}
</p>
<motion.div
className="flex flex-wrap gap-1.5"
variants={agentStaggerContainer}
initial="hidden"
animate="visible"
>
{tags.map((tag, index) => (
<TagChip key={tag} label={tag} />
))}
<motion.button
type="button"
variants={agentFadeUp}
className="inline-flex size-7 items-center justify-center rounded-md border border-dashed text-muted-foreground hover:bg-muted/50"
aria-label={`افزودن ${title}`}
whileHover={{ scale: 1.06 }}
whileTap={{ scale: 0.94 }}
>
<Plus className="size-3.5" aria-hidden />
</motion.button>
</motion.div>
</motion.div>
);
}
export function AgentPreviewPanel({ className, onClose }: AgentPreviewPanelProps) {
return (
<motion.aside
layout
className={cn(
"flex w-full shrink-0 flex-col overflow-hidden border-s bg-card lg:w-72 xl:w-80",
className
)}
variants={agentSlideInEnd}
initial="hidden"
animate="visible"
exit="exit"
transition={agentLayoutTransition}
>
<div className="flex items-center justify-between border-b px-4 py-3">
<h2 className={type["card-title"]}>پیش‌نمایش سناریو</h2>
{onClose && (
<Button
type="button"
variant="ghost"
size="icon-sm"
onClick={onClose}
aria-label="بستن پیش‌نمایش"
>
<X className="size-4" aria-hidden />
</Button>
)}
</div>
<motion.div
className="flex-1 space-y-5 overflow-y-auto p-4"
variants={agentStaggerContainer}
initial="hidden"
animate="visible"
>
<motion.div className="space-y-2" variants={agentFadeUp}>
<p className={cn(type.caption, "font-medium uppercase tracking-wide text-muted-foreground")}>
سناریو
</p>
<h3 className={type.h4}>{AGENT_WORKSPACE_TITLE}</h3>
<p className={cn(type["body-sm"], "text-muted-foreground")}>
سناریوی آزمایشی برای طراحی workflow پشتیبانی و پاسخ‌گویی خودکار به
مشتریان.
</p>
<div className="flex flex-wrap gap-1.5 pt-1">
{AGENT_PREVIEW_TAGS.map((tag, index) => (
<motion.span
key={tag}
className={cn(
"rounded-md bg-primary/10 px-2 py-0.5 text-primary",
type.caption
)}
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ delay: 0.15 + index * 0.06 }}
>
{tag}
</motion.span>
))}
</div>
</motion.div>
<motion.div className="space-y-2" variants={agentFadeUp}>
<p className={cn(type.caption, "font-medium uppercase tracking-wide text-muted-foreground")}>
قالب
</p>
<div className="flex items-center justify-between rounded-xl border bg-muted/30 p-3">
<div className="flex items-center gap-2">
<FileText className="size-4 text-muted-foreground" aria-hidden />
<span className={type["body-sm"]}>پاسخ‌گویی خودکار</span>
</div>
<Button type="button" variant="ghost" size="sm" className="h-7 px-2 text-xs">
تغییر
</Button>
</div>
</motion.div>
<div className="space-y-4">
<p className={cn(type.caption, "font-medium uppercase tracking-wide text-muted-foreground")}>
نمای کلی مخاطب
</p>
<AudienceSection title="نوع شرکت" tags={AGENT_AUDIENCE_TAGS.companyType} />
<AudienceSection title="مرحله" tags={AGENT_AUDIENCE_TAGS.stage} />
<AudienceSection title="اندازه شرکت" tags={AGENT_AUDIENCE_TAGS.companySize} />
<AudienceSection title="منطقه" tags={AGENT_AUDIENCE_TAGS.region} />
</div>
<motion.div className="space-y-2" variants={agentFadeUp}>
<p className={cn(type.caption, "font-medium uppercase tracking-wide text-muted-foreground")}>
ساختار سناریو
</p>
<div className="flex items-center gap-2 rounded-xl border bg-muted/30 px-3 py-2.5">
<Mail className="size-4 text-muted-foreground" aria-hidden />
<span className={type["body-sm"]}>پیام ۱</span>
</div>
</motion.div>
</motion.div>
<motion.div
className="flex gap-2 border-t p-4"
initial={{ opacity: 0, y: 12 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.2 }}
>
<Button type="button" variant="outline" className="flex-1">
زمان‌بندی
</Button>
<Button type="button" className="flex-1">
اجرای سناریو
</Button>
</motion.div>
</motion.aside>
);
}