{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "attachment",
  "title": "Attachment",
  "description": "The BRUT/UI Attachment component with the current shadcn behavior and API.",
  "dependencies": [
    "@base-ui/react",
    "class-variance-authority"
  ],
  "registryDependencies": [
    "@brut-ui/button",
    "utils"
  ],
  "files": [
    {
      "path": "registry/brutalist/ui/attachment.tsx",
      "content": "import * as React from \"react\"\nimport { mergeProps } from \"@base-ui/react/merge-props\"\nimport { useRender } from \"@base-ui/react/use-render\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/registry/brutalist/ui/button\"\n\nconst attachmentVariants = cva(\n  \"group/attachment relative flex w-fit max-w-full min-w-0 shrink-0 flex-wrap rounded-xl border bg-card text-card-foreground transition-colors focus-within:ring-1 focus-within:ring-ring/50 has-[>a,>button]:hover:bg-muted/50 data-[state=error]:border-destructive/30 data-[state=idle]:border-dashed\",\n  {\n    variants: {\n      size: {\n        default:\n          \"gap-2 text-sm has-data-[slot=attachment-content]:px-2.5 has-data-[slot=attachment-content]:py-2 has-data-[slot=attachment-media]:p-2\",\n        sm: \"gap-2.5 text-xs has-data-[slot=attachment-content]:px-2 has-data-[slot=attachment-content]:py-1.5 has-data-[slot=attachment-media]:p-1.5\",\n        xs: \"gap-1.5 rounded-lg text-xs has-data-[slot=attachment-content]:px-1.5 has-data-[slot=attachment-content]:py-1 has-data-[slot=attachment-media]:p-1\",\n      },\n      orientation: {\n        horizontal: \"min-w-40 items-center\",\n        vertical: \"w-24 flex-col has-data-[slot=attachment-content]:w-30\",\n      },\n    },\n  }\n)\n\nfunction Attachment({\n  className,\n  state = \"done\",\n  size = \"default\",\n  orientation = \"horizontal\",\n  ...props\n}: React.ComponentProps<\"div\"> &\n  VariantProps<typeof attachmentVariants> & {\n    state?: \"idle\" | \"uploading\" | \"processing\" | \"error\" | \"done\"\n  }) {\n  return (\n    <div\n      data-slot=\"attachment\"\n      data-state={state}\n      data-size={size}\n      data-orientation={orientation}\n      className={cn(attachmentVariants({ size, orientation }), className)}\n      {...props}\n    />\n  )\n}\n\nconst attachmentMediaVariants = cva(\n  \"relative flex aspect-square w-10 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-muted text-foreground group-data-[orientation=vertical]/attachment:w-full group-data-[size=sm]/attachment:w-8 group-data-[size=xs]/attachment:w-7 group-data-[size=xs]/attachment:rounded-md group-data-[state=error]/attachment:bg-destructive/10 group-data-[state=error]/attachment:text-destructive group-data-[orientation=vertical]/attachment:*:data-[slot=spinner]:size-6! [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 group-data-[orientation=vertical]/attachment:[&_svg:not([class*='size-'])]:size-6 group-data-[size=xs]/attachment:[&_svg:not([class*='size-'])]:size-3.5\",\n  {\n    variants: {\n      variant: {\n        icon: \"\",\n        image:\n          \"opacity-60 group-data-[state=done]/attachment:opacity-100 group-data-[state=idle]/attachment:opacity-100 *:[img]:aspect-square *:[img]:w-full *:[img]:object-cover\",\n      },\n    },\n    defaultVariants: {\n      variant: \"icon\",\n    },\n  }\n)\n\nfunction AttachmentMedia({\n  className,\n  variant = \"icon\",\n  ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof attachmentMediaVariants>) {\n  return (\n    <div\n      data-slot=\"attachment-media\"\n      data-variant={variant}\n      className={cn(attachmentMediaVariants({ variant }), className)}\n      {...props}\n    />\n  )\n}\n\nfunction AttachmentContent({\n  className,\n  ...props\n}: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"attachment-content\"\n      className={cn(\n        \"max-w-full min-w-0 flex-1 leading-tight group-data-[orientation=vertical]/attachment:px-1\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction AttachmentTitle({\n  className,\n  ...props\n}: React.ComponentProps<\"span\">) {\n  return (\n    <span\n      data-slot=\"attachment-title\"\n      className={cn(\n        \"block max-w-full min-w-0 truncate font-medium group-data-[state=processing]/attachment:shimmer group-data-[state=uploading]/attachment:shimmer\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction AttachmentDescription({\n  className,\n  ...props\n}: React.ComponentProps<\"span\">) {\n  return (\n    <span\n      data-slot=\"attachment-description\"\n      className={cn(\n        \"mt-0.5 block min-w-0 truncate text-xs text-muted-foreground group-data-[state=error]/attachment:text-destructive/80\",\n        \"max-w-full\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction AttachmentActions({\n  className,\n  ...props\n}: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"attachment-actions\"\n      className={cn(\n        \"relative z-20 flex shrink-0 items-center group-data-[orientation=vertical]/attachment:absolute group-data-[orientation=vertical]/attachment:top-3 group-data-[orientation=vertical]/attachment:right-3 group-data-[orientation=vertical]/attachment:gap-1\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction AttachmentAction({\n  className,\n  variant,\n  size = \"icon-xs\",\n  ...props\n}: React.ComponentProps<typeof Button>) {\n  return (\n    <Button\n      data-slot=\"attachment-action\"\n      variant={variant ?? \"ghost\"}\n      size={size}\n      className={cn(className)}\n      {...props}\n    />\n  )\n}\n\nfunction AttachmentTrigger({\n  className,\n  render,\n  type,\n  ...props\n}: useRender.ComponentProps<\"button\">) {\n  return useRender({\n    defaultTagName: \"button\",\n    props: mergeProps<\"button\">(\n      {\n        type: render ? type : (type ?? \"button\"),\n        className: cn(\"absolute inset-0 z-10 outline-none\", className),\n      },\n      props\n    ),\n    render,\n    state: {\n      slot: \"attachment-trigger\",\n    },\n  })\n}\n\nfunction AttachmentGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"attachment-group\"\n      className={cn(\n        \"flex min-w-0 scroll-fade-x snap-x snap-mandatory scroll-px-1 scrollbar-none gap-3 overflow-x-auto overscroll-x-contain py-1 *:data-[slot=attachment]:flex-none *:data-[slot=attachment]:snap-start\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport {\n  Attachment,\n  AttachmentGroup,\n  AttachmentMedia,\n  AttachmentContent,\n  AttachmentTitle,\n  AttachmentDescription,\n  AttachmentActions,\n  AttachmentAction,\n  AttachmentTrigger,\n}\n",
      "type": "registry:ui",
      "target": "@ui/attachment.tsx"
    },
    {
      "path": "registry/brutalist/styles/brutalist.css",
      "content": ":root,\n[data-brut-palette=\"paper\"] {\n  --background: oklch(0.985 0.004 95);\n  --foreground: oklch(0.15 0.01 65);\n  --card: oklch(1 0 0);\n  --card-foreground: var(--foreground);\n  --popover: oklch(1 0 0);\n  --popover-foreground: var(--foreground);\n  --primary: oklch(0.82 0.18 88);\n  --primary-foreground: oklch(0.13 0.01 70);\n  --secondary: oklch(0.88 0.105 210);\n  --secondary-foreground: oklch(0.13 0.01 70);\n  --muted: oklch(0.94 0.018 90);\n  --muted-foreground: oklch(0.38 0.02 65);\n  --accent: oklch(0.72 0.2 20);\n  --accent-foreground: oklch(0.99 0 0);\n  --destructive: oklch(0.61 0.24 28);\n  --border: oklch(0.15 0.01 65);\n  --input: oklch(0.15 0.01 65);\n  --ring: oklch(0.56 0.23 264);\n  --brut-shadow-color: oklch(0.15 0.01 65);\n}\n\n:root {\n  --chart-1: var(--primary);\n  --chart-2: var(--secondary);\n  --chart-3: var(--accent);\n  --chart-4: var(--destructive);\n  --chart-5: var(--muted-foreground);\n  --sidebar: var(--card);\n  --sidebar-foreground: var(--card-foreground);\n  --sidebar-primary: var(--primary);\n  --sidebar-primary-foreground: var(--primary-foreground);\n  --sidebar-accent: var(--accent);\n  --sidebar-accent-foreground: var(--accent-foreground);\n  --sidebar-border: var(--border);\n  --sidebar-ring: var(--ring);\n}\n\n[data-brut-palette=\"signal\"] {\n  --background: oklch(0.91 0.16 96);\n  --foreground: oklch(0.13 0.01 70);\n  --card: oklch(0.985 0.025 96);\n  --card-foreground: var(--foreground);\n  --popover: oklch(0.985 0.025 96);\n  --popover-foreground: var(--foreground);\n  --primary: oklch(0.15 0.01 70);\n  --primary-foreground: oklch(0.93 0.17 96);\n  --secondary: oklch(0.73 0.2 28);\n  --secondary-foreground: oklch(0.13 0.01 70);\n  --muted: oklch(0.86 0.11 96);\n  --muted-foreground: oklch(0.31 0.03 70);\n  --accent: oklch(0.75 0.13 222);\n  --accent-foreground: oklch(0.13 0.01 70);\n  --destructive: oklch(0.55 0.24 28);\n  --border: oklch(0.13 0.01 70);\n  --input: oklch(0.13 0.01 70);\n  --ring: oklch(0.55 0.24 28);\n  --brut-shadow-color: oklch(0.13 0.01 70);\n}\n\n[data-brut-palette=\"sky\"] {\n  --background: oklch(0.92 0.055 235);\n  --foreground: oklch(0.16 0.04 255);\n  --card: oklch(0.98 0.018 230);\n  --card-foreground: var(--foreground);\n  --popover: oklch(0.985 0.018 230);\n  --popover-foreground: var(--foreground);\n  --primary: oklch(0.52 0.2 255);\n  --primary-foreground: oklch(0.99 0 0);\n  --secondary: oklch(0.88 0.16 92);\n  --secondary-foreground: oklch(0.16 0.04 255);\n  --muted: oklch(0.86 0.045 235);\n  --muted-foreground: oklch(0.36 0.055 255);\n  --accent: oklch(0.71 0.18 28);\n  --accent-foreground: oklch(0.16 0.04 255);\n  --destructive: oklch(0.56 0.24 27);\n  --border: oklch(0.16 0.04 255);\n  --input: oklch(0.16 0.04 255);\n  --ring: oklch(0.67 0.2 28);\n  --brut-shadow-color: oklch(0.16 0.04 255);\n}\n\n:root,\n[data-brut-strength=\"soft\"] {\n  --brut-border: 1px;\n  --brut-shadow-x: 2px;\n  --brut-shadow-y: 2px;\n  --brut-panel-shadow-x: 4px;\n  --brut-panel-shadow-y: 4px;\n  --brut-slider-track: 2px;\n  --brut-hover: -1px;\n  --brut-press: 1px;\n  --brut-weight: 600;\n}\n\n[data-brut-strength=\"solid\"] {\n  --brut-border: 2px;\n  --brut-shadow-x: 4px;\n  --brut-shadow-y: 4px;\n  --brut-panel-shadow-x: 7px;\n  --brut-panel-shadow-y: 7px;\n  --brut-slider-track: 4px;\n  --brut-hover: -1px;\n  --brut-press: 2px;\n  --brut-weight: 700;\n}\n\n[data-brut-strength=\"loud\"] {\n  --brut-border: 3px;\n  --brut-shadow-x: 6px;\n  --brut-shadow-y: 6px;\n  --brut-panel-shadow-x: 9px;\n  --brut-panel-shadow-y: 9px;\n  --brut-slider-track: 6px;\n  --brut-hover: -2px;\n  --brut-press: 3px;\n  --brut-weight: 800;\n}\n\n:root,\n[data-brut-radius=\"cut\"] {\n  --radius: 0.375rem;\n}\n\n[data-brut-radius=\"sharp\"] {\n  --radius: 0rem;\n}\n\n[data-brut-radius=\"chunky\"] {\n  --radius: 0.875rem;\n}\n\n@layer base {\n  * {\n    border-color: var(--border);\n    outline-color: color-mix(in oklab, var(--ring) 60%, transparent);\n  }\n\n  html {\n    scroll-behavior: smooth;\n  }\n\n  body {\n    background-color: var(--background);\n    color: var(--foreground);\n  }\n\n  ::selection {\n    background: var(--primary);\n    color: var(--primary-foreground);\n  }\n}\n\n@layer components {\n  .brut-panel {\n    border: var(--brut-border) solid var(--border);\n    border-radius: var(--radius);\n    box-shadow: var(--brut-panel-shadow-x) var(--brut-panel-shadow-y) 0 var(--brut-shadow-color);\n  }\n\n  .brut-surface {\n    border: var(--brut-border) solid var(--border);\n    border-radius: var(--radius);\n    box-shadow: var(--brut-shadow-x) var(--brut-shadow-y) 0 var(--brut-shadow-color);\n  }\n\n  .brut-control {\n    border: var(--brut-border) solid var(--border);\n    border-radius: var(--radius);\n    box-shadow: var(--brut-shadow-x) var(--brut-shadow-y) 0 var(--brut-shadow-color);\n    font-weight: var(--brut-weight);\n    transition: transform 120ms ease, box-shadow 120ms ease, background-color 120ms ease;\n  }\n\n  .brut-control:hover:not(:disabled, [data-disabled]) {\n    transform: translate(var(--brut-hover), var(--brut-hover));\n    box-shadow: calc(var(--brut-shadow-x) - var(--brut-hover)) calc(var(--brut-shadow-y) - var(--brut-hover)) 0 var(--brut-shadow-color);\n  }\n\n  .brut-control:active:not(:disabled, [data-disabled]),\n  .brut-control[data-pressed] {\n    transform: translate(var(--brut-press), var(--brut-press));\n    box-shadow: 0 0 0 var(--brut-shadow-color);\n  }\n\n  .brut-quiet {\n    border: var(--brut-border) solid transparent;\n    border-radius: var(--radius);\n    box-shadow: none;\n    font-weight: var(--brut-weight);\n  }\n\n  .brut-quiet:hover {\n    border-color: var(--border);\n    background: var(--muted);\n  }\n\n  .brut-focus:focus-visible {\n    outline: 3px solid var(--ring);\n    outline-offset: 3px;\n  }\n\n  .brut-input {\n    border: var(--brut-border) solid var(--input);\n    border-radius: var(--radius);\n    background: var(--card);\n    box-shadow: var(--brut-shadow-x) var(--brut-shadow-y) 0 var(--brut-shadow-color);\n    font-weight: 600;\n    transition: box-shadow 120ms ease, transform 120ms ease;\n  }\n\n  .brut-input:focus-visible {\n    outline: 3px solid var(--ring);\n    outline-offset: 2px;\n    transform: translate(-1px, -1px);\n    box-shadow: calc(var(--brut-shadow-x) + 2px) calc(var(--brut-shadow-y) + 2px) 0 var(--brut-shadow-color);\n  }\n\n  .brut-input-group {\n    border: var(--brut-border) solid var(--input);\n    border-radius: var(--radius);\n    background: var(--card);\n    box-shadow: var(--brut-shadow-x) var(--brut-shadow-y) 0 var(--brut-shadow-color);\n    font-weight: 600;\n    transition: box-shadow 120ms ease, transform 120ms ease;\n  }\n\n  .brut-input-group:focus-within {\n    outline: 3px solid var(--ring);\n    outline-offset: 2px;\n    transform: translate(-1px, -1px);\n    box-shadow: calc(var(--brut-shadow-x) + 2px) calc(var(--brut-shadow-y) + 2px) 0 var(--brut-shadow-color);\n  }\n\n  .brut-input-group:has([aria-invalid=\"true\"]) {\n    border-color: var(--destructive);\n  }\n\n  .brut-input-group:has([aria-invalid=\"true\"]):focus-within {\n    outline-color: var(--destructive);\n  }\n\n  .brut-otp-group:has([data-active=\"true\"]) {\n    outline: 3px solid var(--ring);\n    outline-offset: 2px;\n    transform: translate(-1px, -1px);\n    box-shadow: calc(var(--brut-shadow-x) + 2px) calc(var(--brut-shadow-y) + 2px) 0 var(--brut-shadow-color);\n  }\n\n  .brut-otp-group:has([aria-invalid=\"true\"]) {\n    border-color: var(--destructive);\n  }\n\n  .brut-otp-group:has([aria-invalid=\"true\"]):has([data-active=\"true\"]) {\n    outline-color: var(--destructive);\n  }\n\n  .brut-chip {\n    border: var(--brut-border) solid var(--border);\n    border-radius: calc(var(--radius) * 0.75);\n    box-shadow: none;\n    font-weight: 800;\n    letter-spacing: 0.04em;\n    text-transform: uppercase;\n  }\n\n  .brut-toggle {\n    border: var(--brut-border) solid var(--border);\n    border-radius: var(--radius);\n    box-shadow: none;\n    font-weight: var(--brut-weight);\n  }\n\n  .brut-kbd {\n    border: var(--brut-border) solid var(--border);\n    border-radius: calc(var(--radius) * 0.6);\n    box-shadow: none;\n    font-weight: var(--brut-weight);\n  }\n\n  .brut-item {\n    border: var(--brut-border) solid var(--border);\n    border-radius: var(--radius);\n    box-shadow: none;\n  }\n\n  .brut-accordion-item:not(:last-child) {\n    border-bottom: var(--brut-border) solid var(--border);\n    box-shadow: none;\n  }\n\n  .brut-check {\n    border: var(--brut-border) solid var(--border);\n    border-radius: calc(var(--radius) * 0.5);\n    background: var(--card);\n    box-shadow: 2px 2px 0 var(--brut-shadow-color);\n  }\n\n  .brut-radio {\n    border: var(--brut-border) solid var(--input);\n  }\n\n  .brut-slider-thumb {\n    border: var(--brut-border) solid var(--ring);\n  }\n\n  .brut-menubar {\n    border: var(--brut-border) solid var(--border);\n  }\n\n  .brut-avatar {\n    border: var(--brut-border) solid var(--border);\n    background: var(--card);\n    box-shadow: calc(var(--brut-border) + 1px) calc(var(--brut-border) + 1px) 0 var(--brut-shadow-color);\n  }\n\n  .brut-separator {\n    background: var(--border);\n  }\n\n  .brut-dialog {\n    border: var(--brut-border) solid var(--border);\n    border-radius: var(--radius);\n    box-shadow: var(--brut-panel-shadow-x) var(--brut-panel-shadow-y) 0 var(--brut-shadow-color);\n  }\n\n  .brut-questionnaire-choice {\n    border: var(--brut-border) solid var(--input);\n    border-radius: var(--radius);\n  }\n\n  .brut-sheet[data-side=\"right\"] {\n    border-left: var(--brut-border) solid var(--border);\n    border-radius: var(--radius) 0 0 var(--radius);\n    box-shadow: calc(0px - var(--brut-panel-shadow-x)) 0 0 var(--brut-shadow-color);\n  }\n\n  .brut-sheet[data-side=\"left\"] {\n    border-right: var(--brut-border) solid var(--border);\n    border-radius: 0 var(--radius) var(--radius) 0;\n    box-shadow: var(--brut-panel-shadow-x) 0 0 var(--brut-shadow-color);\n  }\n\n  .brut-sheet[data-side=\"bottom\"] {\n    border-top: var(--brut-border) solid var(--border);\n    border-radius: var(--radius) var(--radius) 0 0;\n    box-shadow: 0 calc(0px - var(--brut-panel-shadow-y)) 0 var(--brut-shadow-color);\n  }\n\n  .brut-sheet[data-side=\"top\"] {\n    border-bottom: var(--brut-border) solid var(--border);\n    border-radius: 0 0 var(--radius) var(--radius);\n    box-shadow: 0 var(--brut-panel-shadow-y) 0 var(--brut-shadow-color);\n  }\n\n  .brut-drawer[data-swipe-direction=\"down\"] {\n    border-top: var(--brut-border) solid var(--border);\n    border-radius: var(--radius) var(--radius) 0 0;\n    box-shadow: 0 calc(0px - var(--brut-panel-shadow-y)) 0 var(--brut-shadow-color);\n  }\n\n  .brut-drawer[data-swipe-direction=\"up\"] {\n    border-bottom: var(--brut-border) solid var(--border);\n    border-radius: 0 0 var(--radius) var(--radius);\n    box-shadow: 0 var(--brut-panel-shadow-y) 0 var(--brut-shadow-color);\n  }\n\n  .brut-drawer[data-swipe-direction=\"left\"] {\n    border-right: var(--brut-border) solid var(--border);\n    border-radius: 0 var(--radius) var(--radius) 0;\n    box-shadow: var(--brut-panel-shadow-x) 0 0 var(--brut-shadow-color);\n  }\n\n  .brut-drawer[data-swipe-direction=\"right\"] {\n    border-left: var(--brut-border) solid var(--border);\n    border-radius: var(--radius) 0 0 var(--radius);\n    box-shadow: calc(0px - var(--brut-panel-shadow-x)) 0 0 var(--brut-shadow-color);\n  }\n\n  .brut-popover {\n    border: var(--brut-border) solid var(--border);\n    border-radius: var(--radius);\n    box-shadow: var(--brut-shadow-x) var(--brut-shadow-y) 0 var(--brut-shadow-color);\n  }\n\n  .brut-switch {\n    border: var(--brut-border) solid var(--border);\n    border-radius: var(--radius);\n    box-shadow: 3px 3px 0 var(--brut-shadow-color);\n  }\n\n  .brut-switch-thumb {\n    border-radius: calc(var(--radius) * 0.75);\n  }\n\n  .brut-progress {\n    border: var(--brut-border) solid var(--border);\n    border-radius: var(--radius);\n    background: var(--card);\n  }\n\n  .brut-resizable-group {\n    overflow: hidden;\n    border: var(--brut-border) solid var(--border);\n    border-radius: var(--radius);\n    background: var(--card);\n  }\n\n  .brut-resizable-handle {\n    width: var(--brut-border);\n    background: var(--border);\n  }\n\n  .brut-resizable-handle[aria-orientation=\"horizontal\"] {\n    width: 100%;\n    height: var(--brut-border);\n  }\n\n  .brut-resizable-grip {\n    border: var(--brut-border) solid var(--border);\n    border-radius: min(var(--radius), 0.375rem);\n    background: var(--card);\n  }\n}\n\n@media (prefers-reduced-motion: reduce) {\n  *,\n  *::before,\n  *::after {\n    scroll-behavior: auto !important;\n    transition-duration: 0.01ms !important;\n    animation-duration: 0.01ms !important;\n    animation-iteration-count: 1 !important;\n  }\n}\n",
      "type": "registry:file",
      "target": "@components/styles/brutalist.css"
    }
  ],
  "type": "registry:ui"
}
