{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "assistant",
  "type": "registry:component",
  "title": "Assistant panel",
  "description": "Frames an assistant exchange with a user message, reply, suggestion, and input row.",
  "registryDependencies": [
    "https://vlak.dev/r/vlak-base.json",
    "https://vlak.dev/r/inter.json",
    "https://vlak.dev/r/vlak-lib.json"
  ],
  "dependencies": [
    "@stylexjs/stylex"
  ],
  "devDependencies": [
    "@stylexjs/babel-plugin"
  ],
  "docs": "Vlak leaves are StyleX. Compile them with @stylexjs/babel-plugin (Vite: @stylexjs/unplugin, Next: @stylexjs/nextjs-plugin). If you would rather not run a compiler, import @noorddev/vlak-react instead: it ships precompiled with one stylesheet.",
  "files": [
    {
      "path": "vlak/assistant.tsx",
      "content": "import * as React from \"react\";\nimport * as stylex from \"@stylexjs/stylex\";\nimport { vlak } from \"./tokens.stylex\";\nimport { rs } from \"./rs\";\n\nexport interface AssistantProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nconst styles = stylex.create({\n  ai: {\n    display: \"flex\",\n    flexDirection: \"column\",\n    gap: \"1rem\",\n    maxWidth: \"35rem\",\n    borderWidth: vlak.hairline,\n    borderStyle: \"solid\",\n    borderColor: vlak.divider,\n    borderRadius: vlak.radius,\n    padding: \"1.25rem\",\n  },\n  head: {\n    display: \"flex\",\n    justifyContent: \"space-between\",\n    alignItems: \"center\",\n  },\n  title: {\n    fontSize: \"0.8125rem\",\n    fontWeight: 600,\n    letterSpacing: \"-0.01em\",\n    color: \"var(--text)\",\n  },\n  status: {\n    display: \"flex\",\n    alignItems: \"center\",\n    gap: \"0.375rem\",\n    fontSize: \"0.75rem\",\n    fontWeight: 500,\n    color: vlak.gray,\n    letterSpacing: \"-0.01em\",\n  },\n  statusDot: {\n    width: \"0.375rem\",\n    height: \"0.375rem\",\n    borderRadius: \"50%\",\n    backgroundColor: \"var(--text)\",\n  },\n  msg: {\n    display: \"flex\",\n    width: \"100%\",\n  },\n  user: {\n    justifyContent: \"flex-end\",\n  },\n  userBlock: {\n    backgroundColor: \"var(--table-alt)\",\n    borderWidth: vlak.hairline,\n    borderStyle: \"solid\",\n    borderColor: vlak.divider,\n    borderRadius: vlak.radius,\n    paddingTop: \"0.625rem\",\n    paddingBottom: \"0.625rem\",\n    paddingInlineStart: \"0.875rem\",\n    paddingInlineEnd: \"0.875rem\",\n    fontSize: \"0.84375rem\",\n    color: \"var(--text)\",\n    letterSpacing: \"-0.01em\",\n    maxWidth: \"85%\",\n  },\n  reply: {\n    fontSize: \"0.84375rem\",\n    lineHeight: 1.45,\n    color: \"var(--text)\",\n    letterSpacing: \"-0.01em\",\n    margin: 0,\n  },\n  card: {\n    borderWidth: vlak.hairline,\n    borderStyle: \"solid\",\n    borderColor: vlak.divider,\n    borderRadius: vlak.radius,\n    padding: \"0.875rem\",\n    display: \"flex\",\n    flexDirection: \"column\",\n    alignItems: \"flex-start\",\n  },\n  tag: {\n    fontSize: \"0.65625rem\",\n    fontWeight: 600,\n    letterSpacing: \"0.02em\",\n    color: \"var(--text)\",\n    borderWidth: vlak.hairline,\n    borderStyle: \"solid\",\n    borderColor: vlak.divider,\n    borderRadius: vlak.radiusSm,\n    paddingBlock: 2,\n    paddingInline: \"0.5rem\",\n    marginBottom: \"0.625rem\",\n  },\n  text: {\n    fontSize: \"0.8125rem\",\n    color: \"var(--text)\",\n    lineHeight: 1.45,\n    margin: 0,\n  },\n  done: {\n    display: \"flex\",\n    alignItems: \"baseline\",\n    gap: \"0.5rem\",\n    marginTop: \"0.75rem\",\n    fontSize: \"0.78125rem\",\n    lineHeight: 1.45,\n    color: vlak.gray,\n  },\n  input: {\n    marginTop: 2,\n    borderWidth: vlak.hairline,\n    borderStyle: \"solid\",\n    borderColor: vlak.divider,\n    borderRadius: vlak.radiusSm,\n    backgroundColor: \"var(--bg)\",\n    paddingTop: \"0.625rem\",\n    paddingBottom: \"0.625rem\",\n    paddingInlineStart: \"0.75rem\",\n    paddingInlineEnd: \"0.75rem\",\n    fontSize: \"0.78125rem\",\n    color: vlak.gray,\n    display: \"flex\",\n    justifyContent: \"space-between\",\n    alignItems: \"center\",\n  },\n  send: {\n    color: \"var(--text)\",\n    fontWeight: 600,\n  },\n});\n\n/** Chat panel: user block, reply, suggestion card, input row. */\nexport const Assistant = React.forwardRef<HTMLDivElement, AssistantProps>(function Assistant(\n  { className, style, ...props },\n  ref,\n) {\n  const sx = rs([\"rs-ai\", className], styles.ai);\n  return <div ref={ref} {...props} className={sx.className} style={{ ...sx.style, ...style }} />;\n});\n\nexport const AssistantHead = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(function AssistantHead(\n  { className, style, ...props },\n  ref,\n) {\n  const sx = rs([\"rs-ai-head\", className], styles.head);\n  return <div ref={ref} {...props} className={sx.className} style={{ ...sx.style, ...style }} />;\n});\n\nexport const AssistantTitle = React.forwardRef<HTMLSpanElement, React.HTMLAttributes<HTMLSpanElement>>(function AssistantTitle(\n  { className, style, ...props },\n  ref,\n) {\n  const sx = rs([\"rs-ai-title\", className], styles.title);\n  return <span ref={ref} {...props} className={sx.className} style={{ ...sx.style, ...style }} />;\n});\n\nexport const AssistantStatus = React.forwardRef<HTMLSpanElement, React.HTMLAttributes<HTMLSpanElement>>(function AssistantStatus(\n  { className, style, children, ...props },\n  ref,\n) {\n  const sx = rs([\"rs-ai-status\", className], styles.status);\n  const dot = rs([\"rs-ai-status-dot\"], styles.statusDot);\n  return (\n    <span ref={ref} {...props} className={sx.className} style={{ ...sx.style, ...style }}>\n      <i className={dot.className} style={dot.style} />\n      {children}\n    </span>\n  );\n});\n\nexport const AssistantMsg = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement> & { user?: boolean }>(function AssistantMsg({\n  user,\n  className,\n  style,\n  ...props\n}, ref) {\n  const sx = rs([\"rs-ai-msg\", user && \"rs-ai-user\", className], styles.msg, user && styles.user);\n  return <div ref={ref} {...props} className={sx.className} style={{ ...sx.style, ...style }} />;\n});\n\nexport const AssistantUserBlock = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(function AssistantUserBlock(\n  { className, style, ...props },\n  ref,\n) {\n  const sx = rs([\"rs-ai-user-block\", className], styles.userBlock);\n  return <div ref={ref} {...props} className={sx.className} style={{ ...sx.style, ...style }} />;\n});\n\nexport const AssistantReply = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(function AssistantReply(\n  { className, style, ...props },\n  ref,\n) {\n  const sx = rs([\"rs-ai-reply\", className], styles.reply);\n  return <p ref={ref} {...props} className={sx.className} style={{ ...sx.style, ...style }} />;\n});\n\nexport const AssistantCard = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(function AssistantCard(\n  { className, style, ...props },\n  ref,\n) {\n  const sx = rs([\"rs-ai-card\", className], styles.card);\n  return <div ref={ref} {...props} className={sx.className} style={{ ...sx.style, ...style }} />;\n});\n\nexport const AssistantTag = React.forwardRef<HTMLSpanElement, React.HTMLAttributes<HTMLSpanElement>>(function AssistantTag(\n  { className, style, ...props },\n  ref,\n) {\n  const sx = rs([\"rs-ai-tag\", className], styles.tag);\n  return <span ref={ref} {...props} className={sx.className} style={{ ...sx.style, ...style }} />;\n});\n\nexport const AssistantText = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(function AssistantText(\n  { className, style, ...props },\n  ref,\n) {\n  const sx = rs([\"rs-ai-text\", className], styles.text);\n  return <p ref={ref} {...props} className={sx.className} style={{ ...sx.style, ...style }} />;\n});\n\nexport const AssistantDone = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(function AssistantDone(\n  { className, style, ...props },\n  ref,\n) {\n  const sx = rs([\"rs-ai-done\", className], styles.done);\n  return <div ref={ref} {...props} className={sx.className} style={{ ...sx.style, ...style }} />;\n});\n\nexport const AssistantInput = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(function AssistantInput(\n  { className, style, ...props },\n  ref,\n) {\n  const sx = rs([\"rs-ai-input\", className], styles.input);\n  return <div ref={ref} {...props} className={sx.className} style={{ ...sx.style, ...style }} />;\n});\n\nexport const AssistantSend = React.forwardRef<HTMLSpanElement, React.HTMLAttributes<HTMLSpanElement>>(function AssistantSend(\n  { className, style, ...props },\n  ref,\n) {\n  const sx = rs([\"rs-ai-send\", className], styles.send);\n  return <span ref={ref} {...props} className={sx.className} style={{ ...sx.style, ...style }} />;\n});\n",
      "type": "registry:component",
      "target": "components/vlak/assistant.tsx"
    },
    {
      "path": "vlak/styles/assistant.css",
      "content": "/* ── assistant: generated from packages/react/src/components/assistant.tsx ── */\n.rs-ai{display:flex;flex-direction:column;gap:1rem;max-width:35rem;border-width:1px;border-style:solid;border-color:var(--divider);border-radius:var(--radius);padding:1.25rem}\n.rs-ai-head{display:flex;justify-content:space-between;align-items:center}\n.rs-ai-title{font-size:0.8125rem;font-weight:600;letter-spacing:-0.01em;color:var(--text)}\n.rs-ai-status{display:flex;align-items:center;gap:0.375rem;font-size:0.75rem;font-weight:500;color:var(--text-secondary);letter-spacing:-0.01em}\n.rs-ai-status-dot{width:0.375rem;height:0.375rem;border-radius:50%;background-color:var(--text)}\n.rs-ai-msg{display:flex;width:100%}\n.rs-ai-user{justify-content:flex-end}\n.rs-ai-user-block{background-color:var(--table-alt);border-width:1px;border-style:solid;border-color:var(--divider);border-radius:var(--radius);padding-top:0.625rem;padding-bottom:0.625rem;padding-inline-start:0.875rem;padding-inline-end:0.875rem;font-size:0.84375rem;color:var(--text);letter-spacing:-0.01em;max-width:85%}\n.rs-ai-reply{font-size:0.84375rem;line-height:1.45;color:var(--text);letter-spacing:-0.01em;margin:0}\n.rs-ai-card{border-width:1px;border-style:solid;border-color:var(--divider);border-radius:var(--radius);padding:0.875rem;display:flex;flex-direction:column;align-items:flex-start}\n.rs-ai-tag{font-size:0.65625rem;font-weight:600;letter-spacing:0.02em;color:var(--text);border-width:1px;border-style:solid;border-color:var(--divider);border-radius:var(--radius-sm);padding-block:2px;padding-inline:0.5rem;margin-bottom:0.625rem}\n.rs-ai-text{font-size:0.8125rem;color:var(--text);line-height:1.45;margin:0}\n.rs-ai-done{display:flex;align-items:baseline;gap:0.5rem;margin-top:0.75rem;font-size:0.78125rem;line-height:1.45;color:var(--text-secondary)}\n.rs-ai-input{margin-top:2px;border-width:1px;border-style:solid;border-color:var(--divider);border-radius:var(--radius-sm);background-color:var(--bg);padding-top:0.625rem;padding-bottom:0.625rem;padding-inline-start:0.75rem;padding-inline-end:0.75rem;font-size:0.78125rem;color:var(--text-secondary);display:flex;justify-content:space-between;align-items:center}\n.rs-ai-send{color:var(--text);font-weight:600}\n",
      "type": "registry:file",
      "target": "styles/vlak/assistant.css"
    }
  ],
  "meta": {
    "vlak": {
      "category": "patterns",
      "classes": [
        "rs-ai",
        "rs-ai-head",
        "rs-ai-title",
        "rs-ai-status",
        "rs-ai-msg",
        "rs-ai-user",
        "rs-ai-user-block",
        "rs-ai-reply",
        "rs-ai-card",
        "rs-ai-tag",
        "rs-ai-text",
        "rs-ai-done",
        "rs-ai-input",
        "rs-ai-send",
        "rs-ai-status-dot"
      ],
      "snippet": "<div class=\"rs-ai\"><div class=\"rs-ai-msg rs-ai-user\"><div class=\"rs-ai-user-block\">Make the intro tighter.</div></div><p class=\"rs-ai-reply\">Done. Two sentences, same claim.</p></div>",
      "cssOnly": false,
      "registryDependencies": [
        "vlak-lib"
      ],
      "aliases": [
        "Assistant",
        "Chat panel",
        "AI chat",
        "Conversation",
        "Copilot panel"
      ],
      "example": "import { Assistant, AssistantHead, AssistantMsg, AssistantReply, AssistantStatus, AssistantTitle, AssistantUserBlock, MessageComposer } from \"@noorddev/vlak-react\";\n\n<Assistant>\n  <AssistantHead>\n    <AssistantTitle>Assistant</AssistantTitle>\n    <AssistantStatus>Ready</AssistantStatus>\n  </AssistantHead>\n  <AssistantMsg user>\n    <AssistantUserBlock>Make the intro tighter.</AssistantUserBlock>\n  </AssistantMsg>\n  <AssistantReply>Done. Two sentences, same claim.</AssistantReply>\n  <MessageComposer onSend={sendMessage} />\n</Assistant>",
      "usage": {
        "use": [
          "A chat panel with a head, a message thread, and an input row.",
          "AssistantCard and AssistantTag for a suggestion the reply proposes."
        ],
        "avoid": [
          "Long transcripts without a ScrollArea.",
          "Notifications; use toast."
        ]
      },
      "a11y": [
        "Layout parts only. Give the thread aria-live=\"polite\" if replies stream in, and make the input a real <input> with a name and the send a <button>."
      ]
    }
  }
}
