{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "textarea-toolbar",
  "title": "Toolbar textarea",
  "description": "Styled textarea: the Toolbar set. 5 decorative textarea variations (FormatTextarea, ActionsTextarea, FooterTextarea, HeaderTextarea, SplitTextarea) on the ai2 token system, driven by CSS token transitions and sized sm to xl. Part of the free styled layer.",
  "dependencies": [
    "lucide-react@^1.23.0"
  ],
  "registryDependencies": [
    "@ai2/tokens"
  ],
  "files": [
    {
      "path": "registry/ai2/styled/textarea-toolbar.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { AtSign, Bold, Italic, Link2, ListOrdered, Paperclip, Send, Smile } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* Toolbar textarea family: 5 multi-line fields that change the shell around the\n   field. The difference is only the chrome: a formatting bar on top, actions below,\n   an info footer, a titled top bar and a two-part bar.\n\n   NOTE: the bar buttons in this family are a VISUAL AFFORDANCE. This is NOT a rich\n   text editor and the buttons do not format the text; to avoid imitating a broken\n   editor, no fake behavior is wired up. The buttons are focusable and have\n   accessible names, so they are ready to be connected to a real editor. Bind onClick\n   to supply your own behavior.\n\n   The effects are pure CSS (focus-within/hover + token transitions), so motion/react\n   is not needed. Color comes ONLY from tokens; transparency via color-mix or the\n   Tailwind alpha. Every field has an accessible name (the ids are produced with\n   React.useId). Each one wraps a real <textarea> and passes through all the native\n   props. */\n\nexport type StyledSize = \"sm\" | \"md\" | \"lg\" | \"xl\"\n\nconst height: Record<StyledSize, string> = {\n  sm: \"min-h-16 text-sm\",\n  md: \"min-h-20 text-sm\",\n  lg: \"min-h-24 text-base\",\n  xl: \"min-h-28 text-base\",\n}\n\nconst shellBase =\n  \"flex w-72 max-w-full flex-col overflow-hidden rounded-xl border border-field-border bg-transparent transition-colors focus-within:border-ring focus-within:ring-[3px] focus-within:ring-ring/50\"\n\nconst areaBase =\n  \"w-full resize-y bg-transparent px-3 py-2 text-foreground outline-none placeholder:text-muted-foreground focus-visible:ring-0 disabled:cursor-not-allowed disabled:opacity-50\"\n\nconst barBase = \"flex items-center gap-0.5 border-border bg-surface-2 px-1.5 py-1\"\n\n/* Cubuk butonu: gorsel affordance, davranis tuketiciye ait. */\nconst barBtn =\n  \"inline-flex size-7 shrink-0 items-center justify-center rounded-md text-muted-foreground outline-none transition-colors hover:bg-[color-mix(in_oklab,var(--color-foreground)_8%,transparent)] hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0 [&>i]:text-base [&>i]:leading-none [&>i]:shrink-0\"\n\nconst sendBtn =\n  \"inline-flex h-7 shrink-0 select-none items-center justify-center gap-1.5 whitespace-nowrap rounded-md bg-primary px-2.5 text-xs font-medium text-primary-foreground outline-none transition-colors hover:bg-[color-mix(in_oklab,var(--color-primary)_88%,var(--color-foreground))] focus-visible:ring-[3px] focus-visible:ring-ring/50 [&>svg]:size-3.5 [&>svg]:shrink-0 [&>i]:text-xs [&>i]:leading-none [&>i]:shrink-0\"\n\ntype Props = React.ComponentProps<\"textarea\"> & {\n  size?: StyledSize\n  /** The top bar heading. NOT `title`: a native textarea's title is a string. */\n  heading?: string\n}\n\n/* Tracks the entered value whether controlled or uncontrolled (for the counter). */\nfunction useTrackedValue(props: Pick<Props, \"value\" | \"defaultValue\" | \"onChange\">) {\n  const [internal, setInternal] = React.useState(\n    props.defaultValue != null ? String(props.defaultValue) : \"\"\n  )\n  const value = props.value != null ? String(props.value) : internal\n  const onChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n    setInternal(e.target.value)\n    props.onChange?.(e)\n  }\n  return { value, onChange }\n}\n\n/* Format: ustte bicimlendirme cubugu (kalin, italik, baglanti, liste). */\nexport function FormatTextarea({ className, size = \"md\", ...props }: Props) {\n  const id = React.useId()\n  return (\n    <span data-slot=\"styled-textarea\" className={cn(shellBase, className)}>\n      <span role=\"toolbar\" aria-label=\"Formatting\" aria-controls={id} className={cn(barBase, \"border-b\")}>\n        <button type=\"button\" aria-label=\"Bold\" className={barBtn}>\n          <Bold />\n        </button>\n        <button type=\"button\" aria-label=\"Italic\" className={barBtn}>\n          <Italic />\n        </button>\n        <button type=\"button\" aria-label=\"Insert link\" className={barBtn}>\n          <Link2 />\n        </button>\n        <button type=\"button\" aria-label=\"Numbered list\" className={barBtn}>\n          <ListOrdered />\n        </button>\n      </span>\n      <textarea id={id} aria-label=\"Message\" {...props} className={cn(areaBase, height[size])} />\n    </span>\n  )\n}\n\n/* Actions: altta eylem cubugu; ek ikonlari solda, gonder butonu sagda. */\nexport function ActionsTextarea({ className, size = \"md\", ...props }: Props) {\n  const id = React.useId()\n  return (\n    <span data-slot=\"styled-textarea\" className={cn(shellBase, className)}>\n      <textarea id={id} aria-label=\"Message\" {...props} className={cn(areaBase, height[size])} />\n      <span className={cn(barBase, \"border-t justify-between\")}>\n        <span className=\"flex items-center gap-0.5\">\n          <button type=\"button\" aria-label=\"Attach a file\" className={barBtn}>\n            <Paperclip />\n          </button>\n          <button type=\"button\" aria-label=\"Mention someone\" className={barBtn}>\n            <AtSign />\n          </button>\n          <button type=\"button\" aria-label=\"Add an emoji\" className={barBtn}>\n            <Smile />\n          </button>\n        </span>\n        <button type=\"button\" className={sendBtn}>\n          <Send />\n          Send\n        </button>\n      </span>\n    </span>\n  )\n}\n\n/* Footer: altta bilgi altligi; canli karakter sayaci + ipucu metni. */\nexport function FooterTextarea({ className, size = \"md\", maxLength = 280, ...props }: Props) {\n  const id = React.useId()\n  const { value, onChange } = useTrackedValue(props)\n  const count = value.length\n  const near = count >= maxLength * 0.9\n  return (\n    <span data-slot=\"styled-textarea\" className={cn(shellBase, className)}>\n      <textarea\n        id={id}\n        aria-label=\"Message\"\n        maxLength={maxLength}\n        {...props}\n        onChange={onChange}\n        className={cn(areaBase, height[size])}\n      />\n      <span className={cn(barBase, \"border-t justify-between px-3 text-xs text-muted-foreground\")}>\n        <span>Markdown is not rendered here.</span>\n        <span className={cn(\"tabular-nums\", near ? \"text-warning\" : \"text-muted-foreground\")}>\n          {count}/{maxLength}\n        </span>\n      </span>\n    </span>\n  )\n}\n\n/* Header: ustte baslikli bar; baslik alanin gorunur etiketi olarak baglanir. */\nexport function HeaderTextarea({ className, size = \"md\", heading = \"Message\", ...props }: Props) {\n  const id = React.useId()\n  const headingId = `${id}-heading`\n  return (\n    <span data-slot=\"styled-textarea\" className={cn(shellBase, className)}>\n      <span className={cn(barBase, \"border-b justify-between px-3 py-1.5\")}>\n        <label id={headingId} htmlFor={id} className=\"text-xs font-medium text-foreground\">\n          {heading}\n        </label>\n        <span className=\"text-xs text-muted-foreground\">Optional</span>\n      </span>\n      <textarea id={id} {...props} className={cn(areaBase, height[size])} />\n    </span>\n  )\n}\n\n/* Split: ust cubuk iki parcaya bolunur; solda bicim ikonlari, sagda gonder. */\nexport function SplitTextarea({ className, size = \"md\", ...props }: Props) {\n  const id = React.useId()\n  return (\n    <span data-slot=\"styled-textarea\" className={cn(shellBase, className)}>\n      <span className={cn(barBase, \"border-b justify-between\")}>\n        <span role=\"toolbar\" aria-label=\"Formatting\" aria-controls={id} className=\"flex items-center gap-0.5\">\n          <button type=\"button\" aria-label=\"Bold\" className={barBtn}>\n            <Bold />\n          </button>\n          <button type=\"button\" aria-label=\"Italic\" className={barBtn}>\n            <Italic />\n          </button>\n          <span aria-hidden=\"true\" className=\"mx-1 h-4 w-px bg-border\" />\n          <button type=\"button\" aria-label=\"Insert link\" className={barBtn}>\n            <Link2 />\n          </button>\n        </span>\n        <button type=\"button\" className={sendBtn}>\n          Send\n        </button>\n      </span>\n      <textarea id={id} aria-label=\"Message\" {...props} className={cn(areaBase, height[size])} />\n    </span>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/ui/textarea-toolbar.tsx"
    }
  ],
  "categories": [
    "styled",
    "textarea"
  ],
  "type": "registry:component"
}