shadcn.io is not affiliated with official shadcn/ui
Shadcn Attachment for React
File or image attachment with media, metadata, upload state, and actions.
workspace.pngPNG · 820 KB
desk-reference.jpgJPG · 1.1 MB
office-reference.jpgJPG · 940 KB
sales-dashboard.pdfUploading · 64%
message-renderer.tsxTypeScript · 12 KB
Installation
bunx --bun shadcn@latest add https://kit.dev/r/base/attachment.jsonnpx shadcn@latest add https://kit.dev/r/base/attachment.jsonpnpm dlx shadcn@latest add https://kit.dev/r/base/attachment.jsonyarn shadcn@latest add https://kit.dev/r/base/attachment.jsonThis component depends on Button. Install it first if you haven't already.
Install the following dependencies:
bun add @base-ui/react tailwind-variantsnpm install @base-ui/react tailwind-variantspnpm add @base-ui/react tailwind-variantsyarn add @base-ui/react tailwind-variantsCopy and paste the following code into your project.
"use client";
import { mergeProps } from "@base-ui/react/merge-props";
import { useRender } from "@base-ui/react/use-render";
import type * as React from "react";
import { tv, type VariantProps } from "tailwind-variants";
import { cn } from "@/lib/utils";
import { Button } from "@/registry/base/components/button";
const attachmentVariants = tv({
base: "cn-attachment group/attachment relative flex min-w-0 max-w-full shrink-0 flex-wrap border bg-card text-card-foreground transition-colors has-[>a,>button]:hover:bg-muted/50 data-[state=error]:border-destructive/30 data-[state=idle]:border-dashed",
variants: {
orientation: {
horizontal: "cn-attachment-orientation-horizontal items-center",
vertical: "cn-attachment-orientation-vertical flex-col",
},
size: {Update the import paths to match your project setup.
Anatomy
Attachment
├── AttachmentMedia
├── AttachmentContent
│ ├── AttachmentTitle
│ └── AttachmentDescription
├── AttachmentActions
│ └── AttachmentAction
└── AttachmentTriggerUse AttachmentGroup to lay out multiple attachments in a scrollable row.
AttachmentGroup
├── Attachment
└── AttachmentUsage
import {
Attachment,
AttachmentAction,
AttachmentActions,
AttachmentContent,
AttachmentDescription,
AttachmentMedia,
AttachmentTitle,
} from "@/components/ui/attachment";<Attachment className="max-w-full min-w-0">
<AttachmentMedia>
<FileTextIcon aria-hidden="true" className="size-4" />
</AttachmentMedia>
<AttachmentContent className="max-w-full min-w-0">
<AttachmentTitle>sales-dashboard.pdf</AttachmentTitle>
<AttachmentDescription>PDF · 2.4 MB</AttachmentDescription>
</AttachmentContent>
<AttachmentActions>
<AttachmentAction aria-label="Remove sales-dashboard.pdf">
<XIcon aria-hidden="true" className="size-4" />
</AttachmentAction>
</AttachmentActions>
</Attachment>Demos
Image
Set variant="image" on AttachmentMedia and render an <img> inside it.
States
Set state to reflect the upload lifecycle.
Sizes
Use size to switch between default, sm, and xs.
Group
Wrap attachments in AttachmentGroup for a horizontally scrollable row.
Trigger
Add an AttachmentTrigger to make the whole card open a link or dialog.