In today’s digital landscape, users expect more than just text-based
communication. The ability to share files, images, and other media with
colleagues is essential for a complete collaborative experience, and without it,
users will fall back to email, Slack, or other file-sharing tools.

## Overview

- [Out of the box attachments](#out-of-the-box-attachments) - Enabled in our
  React components by default.
- [Build attachments your way](#build-attachments-your-way) - Use primitives to
  create custom attachment UIs.
- [Attachments in the dashboard](#attachments-in-the-dashboard) - Inspect users’
  attachments on our website.

## Out of the box attachments [#out-of-the-box-attachments]

Our React components in [Comments](/comments) and [Text Editor](/text-editor)
now allow you to attach files to comments, and this is enabled by default. Users
can upload files using the file picker, or by dragging/pasting files into the
composer.

<Figure>
  <video autoPlay loop muted playsInline>
    <source
      src="/images/blog/introducing-attachments/attachments.mp4"
      type="video/mp4"
    />
  </video>
</Figure>

All files types are supported, and our [Pro plan](/pricing) allows individual
files up to 50MB in size. When clicking on attachments, each type of file uses
its default browser behavior—usually opening media in a new tab, or downloading
the file.

<Figure>
  <video autoPlay loop muted playsInline>
    <source
      src="/images/blog/introducing-attachments/attachments-opening.mp4"
      type="video/mp4"
    />
  </video>
</Figure>

It’s possible to customize this behavior using the `onAttachmentClick` prop on
[`Thread`](/docs/api-reference/liveblocks-react-ui#Thread-props). For example
below, we’re cancelling the default behaviour, and instead calling custom
methods to download the file and display a toast notification.

```tsx highlight="4-9"
<Thread
  key={thread.id}
  thread={thread}
  onAttachmentClick={({ attachment, url }, e) => {
    e.preventDefault();

    // Custom behavior on click
    __downloadFile__(url);
    __toast__(`${attachment.name} has been downloaded`);
  }}
/>
```

Attachments are optional and can also be disabled, make sure to read our
[upgrade guide](/docs/platform/upgrading/2.8) to learn more.

## Build attachments your way [#build-attachments-your-way]

Along with our default components, we’ve also made it possible to build
attachments using new primitive components. For example, below we’re showing a
completely custom Comments setup with attachments.

<Figure>
  <video autoPlay loop muted playsInline>
    <source
      src="/images/blog/introducing-attachments/attachments-primitive.mp4"
      type="video/mp4"
    />
  </video>
</Figure>

Our two new components,
[`Composer.AttachFiles`](/docs/api-reference/liveblocks-react-ui#primitives-Composer.AttachFiles),
which opens a file upload dialog and
[`Composer.AttachmentsDropArea`](/docs/api-reference/liveblocks-react-ui#primitives-Composer.AttachmentsDropArea),
which allows you to drop files into the composer, both help enable this,.

```tsx highlight="15-16"
function MyComposer() {
  const createThread = useCreateThread();

  return (
    <Composer.Form
      onComposerSubmit={({ body, attachments }) => {
        const thread = createThread({
          body,
          attachments,
          metadata: {},
        });
      }}
    >
      <Composer.Editor components={/* ... */} />
      <Composer.AttachFiles>Attach Files</Composer.AttachFiles>
      <Composer.AttachmentsDropArea />
      <Composer.Submit>Submit</Composer.Submit>
    </Composer.Form>
  );
}
```

To render each attached file in the composer,
[`useComposer`](/docs/api-reference/liveblocks-react-ui#useComposer) provides
you with information to render. For example, here’s how to list each attachment
in a composer.

```tsx
function MyComposerAttachments() {
  const { attachments, removeAttachment } = useComposer();

  return (
    <>
      {attachments.map((attachment) => (
        <div key={attachment.id}>
          {attachment.name} ({attachment.status})
          <button onClick={() => removeAttachment(attachment.id)}>Remove</button>
        </div>
      )}
    </>
  );
}
```

Learn more about
[handling attachments](/docs/api-reference/liveblocks-react-ui#Handle-attachments)
in our docs, or try our
[Next.js Comments Primitives example](/examples/comments-primitives/nextjs-comments-primitives)
to test and modify a live demo.

## Attachments in the dashboard [#attachments-in-the-dashboard]

In addition to our packages, we’ve also added attachments to our dashboard,
meaning you can inspect which files your users are uploading.

<Figure>
  <Image
    src="/images/blog/introducing-attachments/attachments-dashboard.jpg"
    alt=""
    width={672}
    height={448}
    quality={95}
  />
</Figure>

## Get started with attachments

To use the latest features, update now by following our
[upgrade guide](/docs/platform/upgrading/2.8).

## Contributors

<Contributors
  gitHubUsernames={[
    "flowflorent",
    "ofoucherot",
    "marcbouchenoire",
    "adigau",
    "ctnicholas",
    "pierrelevaillant",
  ]}
/>