Files
ar.badieiandCursor c2376b3b9e
Build & Push Docker Image / build (push) Has been cancelled
feat: redesign landing page with brand system and section blocks
Refresh the homepage around new hero/services/roadmap sections, shared design tokens, and updated brand assets.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 17:00:55 +03:30

157 lines
4.8 KiB
TypeScript

"use client";
import {
AtSign,
CheckSquare,
Mic,
Paperclip,
Play,
Shield,
} from "lucide-react";
import { motion, useReducedMotion } from "motion/react";
import { Button } from "@/components/ui/button";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import { agentEase, agentPanelTransition } from "./agent-motion";
import { cn } from "@/lib/utils";
import { type } from "@/lib/typography";
interface ChatComposerProps {
value: string;
onChange: (value: string) => void;
onSubmit: () => void;
disabled?: boolean;
isSending?: boolean;
className?: string;
}
export function ChatComposer({
value,
onChange,
onSubmit,
disabled = false,
isSending = false,
className,
}: ChatComposerProps) {
const canSubmit = value.trim().length > 0 && !disabled && !isSending;
const reduceMotion = useReducedMotion();
function handleKeyDown(event: React.KeyboardEvent<HTMLTextAreaElement>) {
if (event.key === "Enter" && !event.shiftKey) {
event.preventDefault();
if (canSubmit) onSubmit();
}
}
return (
<motion.div
className={cn("shrink-0 p-3 sm:p-4", className)}
initial={{ opacity: 0, y: 12 }}
animate={{ opacity: 1, y: 0 }}
transition={agentPanelTransition}
>
<motion.div
className="rounded-2xl border bg-card p-3 shadow-md sm:p-4"
layout
transition={agentPanelTransition}
whileHover={
reduceMotion ? undefined : { boxShadow: "0 8px 30px -8px rgba(1, 121, 111, 0.12)" }
}
>
<Textarea
value={value}
onChange={(event) => onChange(event.target.value)}
onKeyDown={handleKeyDown}
placeholder="امتحان کنید: «یک سناریو پاسخ‌گویی خودکار برای مشتریان طراحی کن»..."
disabled={disabled || isSending}
rows={2}
className={cn(
"min-h-[4.5rem] resize-none border-0 bg-transparent px-1 py-1 text-start shadow-none transition-[min-height] duration-300 ease-out focus-visible:ring-0",
type["body-sm"]
)}
aria-label="دستور عامل"
/>
<div className="mt-2 flex items-center justify-between gap-2 border-t pt-2">
<div className="flex items-center gap-0.5 sm:gap-1">
<Button
type="button"
variant="ghost"
size="icon-sm"
className="text-muted-foreground"
aria-label="پیوست"
>
<Paperclip className="size-4" aria-hidden />
</Button>
<Button
type="button"
variant="ghost"
size="icon-sm"
className="text-muted-foreground"
aria-label="اشاره"
>
<AtSign className="size-4" aria-hidden />
</Button>
<Button
type="button"
variant="ghost"
size="icon-sm"
className="text-muted-foreground"
aria-label="وظایف"
>
<CheckSquare className="size-4" aria-hidden />
</Button>
<Select defaultValue="overall">
<SelectTrigger
size="sm"
className="h-8 gap-1 border-0 bg-transparent px-2 shadow-none"
>
<Shield className="size-3.5 text-muted-foreground" aria-hidden />
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="overall">کلی</SelectItem>
<SelectItem value="focused">متمرکز</SelectItem>
<SelectItem value="creative">خلاقانه</SelectItem>
</SelectContent>
</Select>
</div>
<div className="flex items-center gap-1.5">
<Button
type="button"
variant="ghost"
size="icon-sm"
className="text-muted-foreground"
aria-label="ضبط صدا"
>
<Mic className="size-4" aria-hidden />
</Button>
<motion.div
whileHover={reduceMotion ? undefined : { scale: 1.04 }}
whileTap={reduceMotion ? undefined : { scale: 0.96 }}
transition={{ duration: 0.18, ease: agentEase }}
>
<Button
type="button"
onClick={onSubmit}
disabled={!canSubmit}
size="sm"
>
<Play className="fill-current" aria-hidden />
اجرا
</Button>
</motion.div>
</div>
</div>
</motion.div>
</motion.div>
);
}