{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "messenger-shadcnui",
  "type": "registry:component",
  "title": "Messenger",
  "description": "Glassmorphism messenger workspace with accessible motion and quick replies",
  "registryDependencies": [
    "button"
  ],
  "dependencies": [
    "framer-motion",
    "react"
  ],
  "files": [
    {
      "path": "@uitripled/react-shadcn/src/components/components/chat/messenger.tsx",
      "content": "\"use client\";\n\nimport { Avatar, AvatarFallback } from \"@/components/ui/avatar\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport { cn } from \"@/lib/utils\";\nimport { AnimatePresence, motion, useReducedMotion } from \"framer-motion\";\nimport {\n  CheckCheck,\n  MoreVertical,\n  Paperclip,\n  Phone,\n  Search,\n  Send,\n  Video,\n} from \"lucide-react\";\nimport { FormEvent, useEffect, useMemo, useRef, useState } from \"react\";\n\ntype Message = {\n  id: string;\n  sender: \"user\" | \"contact\";\n  author: string;\n  text: string;\n  timestamp: string;\n};\n\ntype Conversation = {\n  id: string;\n  name: string;\n  title: string;\n  status: \"online\" | \"offline\";\n  unread: number;\n  initials: string;\n  messages: Message[];\n  quickReplies: string[];\n  autoReplies: string[];\n};\n\nconst initialConversations: Conversation[] = [\n  {\n    id: \"product-updates\",\n    name: \"Morgan James\",\n    title: \"Product Strategy\",\n    status: \"online\",\n    unread: 2,\n    initials: \"MJ\",\n    messages: [\n      {\n        id: \"product-1\",\n        sender: \"contact\",\n        author: \"Morgan\",\n        text: \"Thanks for the recap on the CashFlow release. The beta cohort loves the motion work.\",\n        timestamp: \"09:18\",\n      },\n      {\n        id: \"product-2\",\n        sender: \"user\",\n        author: \"You\",\n        text: \"Amazing to hear. Do we have a decision on the new Messenger surface?\",\n        timestamp: \"09:21\",\n      },\n      {\n        id: \"product-3\",\n        sender: \"contact\",\n        author: \"Morgan\",\n        text: \"Almost there. Design asked for one more pass on the animation timings - soft ease on expand.\",\n        timestamp: \"09:24\",\n      },\n    ],\n    quickReplies: [\n      \"I can share a timing proposal.\",\n      \"Let me know if you need a demo recording.\",\n      \"We can add an onboarding tooltip.\",\n    ],\n    autoReplies: [\n      \"That would help so much - a short clip would be perfect.\",\n      \"Can we confirm the handoff checklist by tomorrow?\",\n      \"Love the attention to accessibility details here.\",\n    ],\n  },\n  {\n    id: \"customer-success\",\n    name: \"Leah Patel\",\n    title: \"Customer Success\",\n    status: \"offline\",\n    unread: 0,\n    initials: \"LP\",\n    messages: [\n      {\n        id: \"success-1\",\n        sender: \"contact\",\n        author: \"Leah\",\n        text: \"Morning! Enterprise users keep mentioning how clear the summary cards feel.\",\n        timestamp: \"08:05\",\n      },\n      {\n        id: \"success-2\",\n        sender: \"user\",\n        author: \"You\",\n        text: \"Great sign. Do we need any follow-up education for folks migrating from the legacy dashboard?\",\n        timestamp: \"08:08\",\n      },\n      {\n        id: \"success-3\",\n        sender: \"contact\",\n        author: \"Leah\",\n        text: \"Maybe a guided walkthrough. I can draft the outline if you can provide the animation cues.\",\n        timestamp: \"08:11\",\n      },\n    ],\n    quickReplies: [\n      \"Happy to add cues for the walkthrough.\",\n      \"Let us sync after the support standup.\",\n      \"We can capture a Loom covering the flows.\",\n    ],\n    autoReplies: [\n      \"Perfect. Support will love a beat-by-beat cue list.\",\n      \"Thanks - I will drop a doc in the shared folder shortly.\",\n      \"Appreciate you keeping motion accessible throughout.\",\n    ],\n  },\n  {\n    id: \"engineering-handoff\",\n    name: \"Build Squad\",\n    title: \"Engineering Handoff\",\n    status: \"offline\",\n    unread: 1,\n    initials: \"BS\",\n    messages: [\n      {\n        id: \"build-1\",\n        sender: \"contact\",\n        author: \"Carson\",\n        text: \"Do you have the reduced-motion variants for Messenger handy?\",\n        timestamp: \"Yesterday\",\n      },\n      {\n        id: \"build-2\",\n        sender: \"user\",\n        author: \"You\",\n        text: \"Yep - exporting now with notes on keyboard focus states.\",\n        timestamp: \"Yesterday\",\n      },\n    ],\n    quickReplies: [\n      \"Uploading the reduced-motion recording now.\",\n      \"Focus ring spec is ready if you need it.\",\n      \"We can pair on the final QA pass.\",\n    ],\n    autoReplies: [\n      \"Legend - the team will plug that into the Storybook build tonight.\",\n      \"Appreciate the extra detail on focus management.\",\n      \"We will ping if anything else blocks us.\",\n    ],\n  },\n];\n\ntype ReplyCursorState = Record<string, number>;\n\nexport function Messenger() {\n  const [selectedConversationId, setSelectedConversationId] = useState<string>(\n    initialConversations[0]?.id ?? \"\"\n  );\n  const [conversations, setConversations] =\n    useState<Conversation[]>(initialConversations);\n  const [draft, setDraft] = useState(\"\");\n  const [replyCursor, setReplyCursor] = useState<ReplyCursorState>(() => {\n    const cursor: ReplyCursorState = {};\n    initialConversations.forEach((conversation) => {\n      cursor[conversation.id] = 0;\n    });\n    return cursor;\n  });\n  const shouldReduceMotion = useReducedMotion();\n  const messagesContainerRef = useRef<HTMLDivElement | null>(null);\n  const liveRegionRef = useRef<HTMLDivElement | null>(null);\n  const selectedConversationRef = useRef<string>(selectedConversationId);\n  const replyTimeoutRef = useRef<number | null>(null);\n\n  const activeConversation = useMemo(() => {\n    return conversations.find(\n      (conversation) => conversation.id === selectedConversationId\n    );\n  }, [conversations, selectedConversationId]);\n\n  useEffect(() => {\n    selectedConversationRef.current = selectedConversationId;\n    setConversations((prev) =>\n      prev.map((conversation) =>\n        conversation.id === selectedConversationId\n          ? { ...conversation, unread: 0 }\n          : conversation\n      )\n    );\n  }, [selectedConversationId]);\n\n  useEffect(() => {\n    if (!messagesContainerRef.current) {\n      return;\n    }\n    const container = messagesContainerRef.current;\n    const behavior = shouldReduceMotion ? \"auto\" : \"smooth\";\n\n    const scrollToBottom = () => {\n      container.scrollTo({ top: container.scrollHeight, behavior });\n    };\n\n    if (behavior === \"smooth\") {\n      requestAnimationFrame(scrollToBottom);\n    } else {\n      scrollToBottom();\n    }\n  }, [\n    activeConversation?.messages,\n    activeConversation?.id,\n    shouldReduceMotion,\n  ]);\n\n  useEffect(() => {\n    return () => {\n      if (replyTimeoutRef.current) {\n        window.clearTimeout(replyTimeoutRef.current);\n      }\n    };\n  }, []);\n\n  useEffect(() => {\n    if (!liveRegionRef.current || !activeConversation) {\n      return;\n    }\n    const lastMessage =\n      activeConversation.messages[activeConversation.messages.length - 1];\n    if (!lastMessage) {\n      return;\n    }\n    liveRegionRef.current.textContent =\n      lastMessage.author +\n      \" at \" +\n      lastMessage.timestamp +\n      \": \" +\n      lastMessage.text;\n  }, [activeConversation?.messages, activeConversation]);\n\n  const handleSelectConversation = (conversationId: string) => {\n    setSelectedConversationId(conversationId);\n  };\n\n  const handleSubmit = (event: FormEvent<HTMLFormElement>) => {\n    event.preventDefault();\n    if (!draft.trim() || !activeConversation) {\n      return;\n    }\n\n    const conversationId = activeConversation.id;\n    const timestamp = new Date().toLocaleTimeString(\"en-US\", {\n      hour: \"2-digit\",\n      minute: \"2-digit\",\n    });\n    const outgoing: Message = {\n      id: \"outgoing-\" + Date.now().toString(),\n      sender: \"user\",\n      author: \"You\",\n      text: draft.trim(),\n      timestamp,\n    };\n\n    setConversations((prev) =>\n      prev.map((conversation) =>\n        conversation.id === conversationId\n          ? {\n              ...conversation,\n              messages: [...conversation.messages, outgoing],\n              unread: 0,\n            }\n          : conversation\n      )\n    );\n    setDraft(\"\");\n\n    const autoReplies = activeConversation.autoReplies;\n    if (!autoReplies.length) {\n      return;\n    }\n\n    const cursor = replyCursor[conversationId] ?? 0;\n    const nextReply = autoReplies[cursor % autoReplies.length];\n    const delay = shouldReduceMotion ? 0 : 900;\n\n    replyTimeoutRef.current = window.setTimeout(() => {\n      const safeTimestamp = new Date().toLocaleTimeString(\"en-US\", {\n        hour: \"2-digit\",\n        minute: \"2-digit\",\n      });\n      const incoming: Message = {\n        id: \"incoming-\" + Date.now().toString(),\n        sender: \"contact\",\n        author: activeConversation.name,\n        text: nextReply,\n        timestamp: safeTimestamp,\n      };\n\n      const currentSelected = selectedConversationRef.current;\n      setConversations((prev) =>\n        prev.map((conversation) => {\n          if (conversation.id !== conversationId) {\n            return conversation;\n          }\n          const isActive = currentSelected === conversationId;\n          return {\n            ...conversation,\n            messages: [...conversation.messages, incoming],\n            unread: isActive ? 0 : conversation.unread + 1,\n          };\n        })\n      );\n\n      setReplyCursor((prev) => ({\n        ...prev,\n        [conversationId]: cursor + 1,\n      }));\n    }, delay);\n  };\n\n  if (!activeConversation) {\n    return null;\n  }\n\n  const statusDotColor: Record<Conversation[\"status\"], string> = {\n    online: \"bg-green-500\",\n    offline: \"bg-red-500\",\n  };\n\n  return (\n    <section className=\"relative w-full py-6 sm:py-8 md:py-12 lg:py-16\">\n      <div className=\"relative grid min-h-[500px] max-h-[calc(100vh-3rem)] grid-rows-[auto,1fr] gap-4 overflow-hidden rounded-[30px] border border-border/50 bg-background/70 p-4 backdrop-blur-xl sm:min-h-[600px] sm:max-h-[calc(100vh-4rem)] sm:gap-6 sm:p-6 md:min-h-[650px] md:max-h-[calc(100vh-5rem)] lg:h-[760px] lg:max-h-[calc(100vh-6rem)] lg:grid-rows-[1fr] lg:gap-8 lg:p-8 lg:[grid-template-columns:30%_1fr]\">\n        <div className=\"flex flex-col gap-3 rounded-2xl border border-border/40 bg-background/75 p-3 backdrop-blur sm:gap-4 sm:rounded-3xl sm:p-4 lg:hidden\">\n          <div className=\"flex items-center justify-between gap-2 sm:gap-3\">\n            <div>\n              <p className=\"text-xs font-semibold text-foreground sm:text-sm\">\n                Messenger\n              </p>\n              <p className=\"text-[0.65rem] text-muted-foreground sm:text-xs\">\n                {conversations.length} active conversation\n                {conversations.length === 1 ? \"\" : \"s\"}\n              </p>\n            </div>\n            <Badge\n              variant=\"outline\"\n              className=\"rounded-full border border-border/50 bg-primary/15 px-2 py-0.5 text-[0.65rem] uppercase tracking-[0.2em] text-primary hover:bg-primary/15 hover:text-primary sm:px-3 sm:py-1 sm:text-[0.7rem] sm:tracking-[0.24em]\"\n            >\n              Live\n            </Badge>\n          </div>\n          <div className=\"space-y-1.5 sm:space-y-2\">\n            <label\n              htmlFor=\"messenger-conversation\"\n              className=\"text-[0.65rem] font-medium text-muted-foreground sm:text-xs\"\n            >\n              Conversation\n            </label>\n            <select\n              id=\"messenger-conversation\"\n              value={selectedConversationId}\n              onChange={(event) => handleSelectConversation(event.target.value)}\n              className=\"w-full rounded-xl border border-border/40 bg-background/70 px-2.5 py-1.5 text-xs text-foreground focus:border-primary/40 focus:outline-none focus:ring-2 focus:ring-primary/30 sm:rounded-2xl sm:px-3 sm:py-2 sm:text-sm\"\n            >\n              {conversations.map((conversation) => (\n                <option key={conversation.id} value={conversation.id}>\n                  {conversation.name}\n                </option>\n              ))}\n            </select>\n          </div>\n        </div>\n\n        <div className=\"hidden h-full flex-col gap-5 overflow-hidden rounded-3xl border border-border/40 bg-background/75 p-4 backdrop-blur lg:flex lg:col-start-1 lg:col-end-2\">\n          <div className=\"flex items-center justify-between gap-3\">\n            <div>\n              <p className=\"text-sm font-semibold text-foreground\">Messenger</p>\n              <p className=\"text-xs text-muted-foreground\">\n                {conversations.length} active conversation\n                {conversations.length === 1 ? \"\" : \"s\"}\n              </p>\n            </div>\n            <Badge\n              variant=\"outline\"\n              className=\"rounded-full border border-border/50 bg-primary/15 px-3 py-1 text-[0.7rem] uppercase tracking-[0.24em] text-primary hover:bg-primary/15 hover:text-primary\"\n            >\n              Live\n            </Badge>\n          </div>\n\n          <label htmlFor=\"messenger-search\" className=\"sr-only\">\n            Search conversations\n          </label>\n          <div className=\"relative\">\n            <Search\n              className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground/70\"\n              aria-hidden=\"true\"\n            />\n            <Input\n              id=\"messenger-search\"\n              type=\"search\"\n              placeholder=\"Search teammates or channels\"\n              className=\"w-full rounded-2xl border-border/40 bg-background/60 pl-10 text-sm text-foreground placeholder:text-muted-foreground/70 focus-visible:ring-2 focus-visible:ring-primary/40\"\n            />\n          </div>\n\n          <div\n            className=\"flex-1 space-y-2 overflow-y-auto pr-1\"\n            aria-label=\"Conversation list\"\n            role=\"list\"\n          >\n            {conversations.map((conversation) => {\n              const isActive = conversation.id === selectedConversationId;\n              const lastMessage =\n                conversation.messages[conversation.messages.length - 1];\n              return (\n                <motion.button\n                  key={conversation.id}\n                  type=\"button\"\n                  onClick={() => handleSelectConversation(conversation.id)}\n                  aria-pressed={isActive}\n                  className={cn(\n                    \"group relative flex w-full items-start gap-3 rounded-2xl border border-transparent p-3 text-left transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n                    isActive\n                      ? \"border-primary/40 bg-primary/10\"\n                      : \"bg-background/70 hover:border-border/40 hover:bg-muted/40\"\n                  )}\n                  role=\"listitem\"\n                >\n                  <div className=\"relative shrink-0\">\n                    <Avatar className=\"h-10 w-10 rounded-2xl border border-border/40 bg-background/80 text-foreground\">\n                      <AvatarFallback className=\"rounded-2xl bg-primary/15 text-sm font-medium text-primary\">\n                        {conversation.initials}\n                      </AvatarFallback>\n                    </Avatar>\n                    <span\n                      className={cn(\n                        \"absolute bottom-0 right-0 inline-flex h-3 w-3 rounded-full border-2 border-background\",\n                        statusDotColor[conversation.status]\n                      )}\n                      aria-label={\n                        conversation.status === \"online\" ? \"Online\" : \"Offline\"\n                      }\n                    />\n                  </div>\n                  <div className=\"min-w-0 flex-1 space-y-1\">\n                    <div className=\"flex flex-wrap items-center justify-between gap-2\">\n                      <div className=\"flex-1\">\n                        <p className=\"text-sm font-semibold text-foreground\">\n                          {conversation.name}\n                        </p>\n                        <p className=\"text-xs text-muted-foreground\">\n                          {conversation.title}\n                        </p>\n                      </div>\n                    </div>\n                    {lastMessage ? (\n                      <p className=\"line-clamp-2 text-xs text-muted-foreground\">\n                        {lastMessage.author}: {lastMessage.text}\n                      </p>\n                    ) : (\n                      <p className=\"text-xs text-muted-foreground\">\n                        No messages yet\n                      </p>\n                    )}\n                  </div>\n                  {conversation.unread > 0 && (\n                    <span className=\"ml-2 inline-flex min-h-[1.5rem] min-w-[1.5rem] items-center justify-center rounded-full bg-primary text-[0.7rem] font-semibold text-primary-foreground shadow-lg\">\n                      {conversation.unread}\n                    </span>\n                  )}\n                </motion.button>\n              );\n            })}\n          </div>\n        </div>\n\n        <AnimatePresence initial={false} mode=\"wait\">\n          <motion.div\n            key={activeConversation.id}\n            initial={\n              shouldReduceMotion ? { opacity: 1 } : { opacity: 0, y: 12 }\n            }\n            animate={shouldReduceMotion ? { opacity: 1 } : { opacity: 1, y: 0 }}\n            exit={shouldReduceMotion ? { opacity: 0 } : { opacity: 0, y: -12 }}\n            transition={{ duration: 0.32, ease: \"easeOut\" }}\n            className=\"flex min-h-0 flex-col gap-4 overflow-hidden rounded-3xl border border-border/40 bg-background/80 p-4 backdrop-blur sm:gap-5 sm:p-5 md:gap-6 md:p-6 lg:col-start-2 lg:col-end-3\"\n          >\n            <header className=\"flex flex-wrap items-center justify-between gap-3 sm:gap-4\">\n              <div className=\"flex items-center gap-2 sm:gap-3\">\n                <div className=\"relative\">\n                  <Avatar className=\"h-10 w-10 rounded-2xl border border-border/40 bg-card/80 text-foreground sm:h-12 sm:w-12 sm:rounded-3xl\">\n                    <AvatarFallback className=\"rounded-2xl bg-primary/20 text-sm font-semibold text-primary sm:rounded-3xl sm:text-base\">\n                      {activeConversation.initials}\n                    </AvatarFallback>\n                  </Avatar>\n                  <span\n                    className={cn(\n                      \"absolute bottom-0 right-0 inline-flex h-3 w-3 rounded-full border-2 border-background sm:h-3.5 sm:w-3.5\",\n                      statusDotColor[activeConversation.status]\n                    )}\n                    aria-label={\n                      activeConversation.status === \"online\"\n                        ? \"Online\"\n                        : \"Offline\"\n                    }\n                  />\n                </div>\n                <div>\n                  <p className=\"text-sm font-semibold text-foreground sm:text-base\">\n                    {activeConversation.name}\n                  </p>\n                  <p className=\"text-xs text-muted-foreground sm:text-sm\">\n                    {activeConversation.title}\n                  </p>\n                </div>\n              </div>\n\n              <div className=\"flex items-center gap-1.5 sm:gap-2\">\n                <Button\n                  type=\"button\"\n                  variant=\"ghost\"\n                  size=\"icon\"\n                  className=\"size-8 rounded-full border border-border/40 bg-background/60 text-muted-foreground transition hover:bg-muted/60 focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 focus-visible:ring-offset-background sm:size-10\"\n                  aria-label=\"Start audio call\"\n                >\n                  <Phone className=\"h-3.5 w-3.5 sm:h-4 sm:w-4\" />\n                </Button>\n                <Button\n                  type=\"button\"\n                  variant=\"ghost\"\n                  size=\"icon\"\n                  className=\"size-8 rounded-full border border-border/40 bg-background/60 text-muted-foreground transition hover:bg-muted/60 focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 focus-visible:ring-offset-background sm:size-10\"\n                  aria-label=\"Start video call\"\n                >\n                  <Video className=\"h-3.5 w-3.5 sm:h-4 sm:w-4\" />\n                </Button>\n                <Button\n                  type=\"button\"\n                  variant=\"ghost\"\n                  size=\"icon\"\n                  className=\"size-8 rounded-full border border-border/40 bg-background/60 text-muted-foreground transition hover:bg-muted/60 focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 focus-visible:ring-offset-background sm:size-10\"\n                  aria-label=\"Open conversation menu\"\n                >\n                  <MoreVertical className=\"h-3.5 w-3.5 sm:h-4 sm:w-4\" />\n                </Button>\n              </div>\n            </header>\n\n            <div\n              ref={messagesContainerRef}\n              className=\"relative flex-1 min-h-0 space-y-3 overflow-y-auto pr-2 sm:space-y-4 [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-muted\"\n              aria-live=\"off\"\n              aria-label={\"Message thread with \" + activeConversation.name}\n            >\n              <AnimatePresence initial={false}>\n                {activeConversation.messages.map((message) => (\n                  <motion.div\n                    key={message.id}\n                    initial={\n                      shouldReduceMotion\n                        ? false\n                        : { opacity: 0, y: 12, scale: 0.98 }\n                    }\n                    animate={\n                      shouldReduceMotion\n                        ? { opacity: 1 }\n                        : { opacity: 1, y: 0, scale: 1 }\n                    }\n                    exit={{ opacity: 0, y: 0 }}\n                    transition={{ duration: 0.28, ease: \"easeOut\" }}\n                    className=\"flex flex-col gap-1\"\n                    role=\"group\"\n                    aria-label={message.author + \" at \" + message.timestamp}\n                  >\n                    <div\n                      className={cn(\n                        \"relative max-w-[85%] rounded-xl border border-border/40 bg-background/80 px-3 py-2 text-xs leading-relaxed text-foreground backdrop-blur sm:max-w-[82%] sm:rounded-2xl sm:px-4 sm:py-3 sm:text-sm\",\n                        message.sender === \"user\" &&\n                          \"ml-auto border-primary/40 bg-primary text-primary-foreground\"\n                      )}\n                    >\n                      <p className=\"font-medium text-foreground/80 sm:text-sm\">\n                        {message.author}\n                      </p>\n                      <p\n                        className={cn(\n                          \"mt-1 text-[0.875rem] sm:text-[0.95rem]\",\n                          message.sender === \"user\"\n                            ? \"text-primary-foreground/90\"\n                            : \"text-foreground/90\"\n                        )}\n                      >\n                        {message.text}\n                      </p>\n                      <div className=\"mt-2 flex items-center justify-end gap-1.5 text-[0.65rem] sm:mt-3 sm:gap-2 sm:text-[0.7rem]\">\n                        <span\n                          className={cn(\n                            \"text-muted-foreground\",\n                            message.sender === \"user\" &&\n                              \"text-primary-foreground/80\"\n                          )}\n                        >\n                          {message.timestamp}\n                        </span>\n                        {message.sender === \"user\" && (\n                          <CheckCheck\n                            className=\"h-3 w-3 text-primary-foreground/80 sm:h-3.5 sm:w-3.5\"\n                            aria-hidden=\"true\"\n                          />\n                        )}\n                      </div>\n                    </div>\n                  </motion.div>\n                ))}\n              </AnimatePresence>\n            </div>\n\n            <form\n              onSubmit={handleSubmit}\n              className=\"space-y-2 sm:space-y-3\"\n              aria-label=\"Reply composer\"\n            >\n              <label htmlFor=\"messenger-editor\" className=\"sr-only\">\n                Write a message\n              </label>\n              <div className=\"flex items-end gap-2 rounded-2xl border border-border/40 bg-background/80 p-3 backdrop-blur sm:gap-3 sm:rounded-3xl sm:p-4\">\n                <div className=\"flex-1 min-w-0\">\n                  <Textarea\n                    id=\"messenger-editor\"\n                    value={draft}\n                    onChange={(event) => setDraft(event.target.value)}\n                    placeholder={\"Message \" + activeConversation.name}\n                    rows={2}\n                    className=\"min-h-[3rem] w-full resize-none border-none bg-transparent text-xs text-foreground placeholder:text-muted-foreground/70 focus-visible:ring-0 focus-visible:outline-none sm:min-h-[4rem] sm:text-sm\"\n                    aria-label={\"Message \" + activeConversation.name}\n                  />\n                  <div className=\"mt-2 flex flex-wrap gap-1.5 sm:mt-3 sm:gap-2\">\n                    {activeConversation.quickReplies.map((reply) => (\n                      <button\n                        key={reply}\n                        type=\"button\"\n                        onClick={() => setDraft(reply)}\n                        className=\"rounded-full border border-border/50 bg-background/70 px-2.5 py-0.5 text-[0.65rem] text-muted-foreground transition hover:border-primary/40 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 focus-visible:ring-offset-background sm:px-3 sm:py-1 sm:text-xs\"\n                      >\n                        {reply}\n                      </button>\n                    ))}\n                  </div>\n                </div>\n                <div className=\"flex shrink-0 flex-col items-end gap-1.5 sm:w-24 sm:gap-2\">\n                  <Button\n                    type=\"button\"\n                    variant=\"ghost\"\n                    size=\"icon\"\n                    className=\"size-8 rounded-full border border-border/40 bg-background/70 text-muted-foreground transition hover:bg-muted/50 focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 focus-visible:ring-offset-background sm:size-10\"\n                    aria-label=\"Attach a file\"\n                  >\n                    <Paperclip className=\"h-3.5 w-3.5 sm:h-4 sm:w-4\" />\n                  </Button>\n                  <Button\n                    type=\"submit\"\n                    size=\"icon\"\n                    className=\"size-8 rounded-full bg-primary text-primary-foreground shadow-lg transition hover:bg-primary/90 focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-60 sm:size-10\"\n                    disabled={!draft.trim()}\n                    aria-label=\"Send message\"\n                  >\n                    <Send\n                      className=\"h-3.5 w-3.5 sm:h-4 sm:w-4\"\n                      aria-hidden=\"true\"\n                    />\n                  </Button>\n                </div>\n              </div>\n            </form>\n          </motion.div>\n        </AnimatePresence>\n      </div>\n      <div\n        ref={liveRegionRef}\n        className=\"sr-only\"\n        aria-live=\"polite\"\n        aria-atomic=\"true\"\n      />\n    </section>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/uitripled/messenger-shadcnui.tsx"
    }
  ]
}