Skip to content

Attachments

Attachment renders the attachments for a message and chooses the UI based on each attachment shape.

Best Practices

  • Keep custom attachment logic focused on the types you actually use.
  • Prefer the supported override points on Attachment instead of customizing low-level attachment containers directly.
  • Combine message.shared_location with message.attachments when you render Attachment inside a fully custom message UI.
  • Use CDN-backed sizing and the SDK sizing handlers for images and videos whenever possible.
  • Treat native giphy messages as their own attachment surface; they render through Giphy, not ModalGallery.
  • Test messages with mixed attachment types so your custom layout still behaves well.

Default Rendering

Attachment groups message attachments before rendering them. The default UI surface is:

Attachment shape Default UI
audio attachment Audio
scraped content / OG attachment Card
file attachment FileAttachment
giphy attachment Giphy
shared location Geolocation
single image attachment Image
single video attachment VideoPlayer
multiple image/video attachments ModalGallery
voice recording attachment VoiceRecording
unsupported attachment UnsupportedAttachment

Attachments with og_scrape_url or title_link are rendered as scraped content cards. Shared location is read from message.shared_location, not from message.attachments.

Native giphy attachments render inline through Giphy. They do not open ModalGallery; the gallery viewer is used for image and mixed image/video gallery content. If you want a modal or fullscreen experience for sent giphies, override Giphy directly.

Unsupported attachments

When the SDK cannot map an attachment to a supported renderer (for example an empty object, an unknown type, or a custom shape you have not wired through your own Attachment override), it uses UnsupportedAttachment.

Basic Usage

The default SDK message UI already renders Attachment for you. If you build your own message component, render it with the current message attachments:

import { Attachment, MessageText, useMessageContext } from "stream-chat-react";

const CustomMessage = () => {
  const { message } = useMessageContext();
  const attachments = [
    ...(message.shared_location ? [message.shared_location] : []),
    ...(message.attachments ?? []),
  ];

  return (
    <div>
      <MessageText />
      {attachments.length ? <Attachment attachments={attachments} /> : null}
    </div>
  );
};

UI Customization

The supported media override points are:

  • Image for a single image attachment
  • Media for a single video attachment
  • ModalGallery for multi-image or mixed image/video galleries

You can also replace AttachmentActions, Audio, Card, File, Geolocation, Giphy, UnsupportedAttachment, and VoiceRecording.

Customizing Attachment inside your own message UI

If you render Attachment directly, pass the custom subcomponents you need:

import {
  Attachment,
  type AttachmentProps,
  type ModalGalleryProps,
  type VideoPlayerProps,
} from "stream-chat-react";

const CustomVideoPlayer = ({ thumbnailUrl, videoUrl }: VideoPlayerProps) => (
  <video controls poster={thumbnailUrl} src={videoUrl} />
);

const CustomModalGallery = ({ items }: ModalGalleryProps) => (
  <div className="custom-gallery-grid">
    {items.map((item, index) => {
      const previewUrl = item.imageUrl ?? item.videoThumbnailUrl;
      if (!previewUrl) return null;

      return (
        <button key={index}>
          <img alt={item.alt ?? "attachment"} src={previewUrl} />
        </button>
      );
    })}
  </div>
);

const CustomAttachment = (props: AttachmentProps) => (
  <Attachment
    {...props}
    Media={CustomVideoPlayer}
    ModalGallery={CustomModalGallery}
  />
);

Replacing the SDK attachment renderer

If you want the SDK Message, VirtualMessage, and thread surfaces to use your attachment renderer, register it with WithComponents:

import {
  Channel,
  MessageComposer,
  MessageList,
  WithComponents,
} from "stream-chat-react";

const App = () => (
  <WithComponents overrides={{ Attachment: CustomAttachment }}>
    <Channel>
      <MessageList />
      <MessageComposer />
    </Channel>
  </WithComponents>
);
Tip:

If you customized low-level attachment containers in earlier versions, prefer these v14-supported surfaces first: Attachment, Image, Media, ModalGallery, File, Card, Giphy, Geolocation, VoiceRecording, UnsupportedAttachment, and AttachmentActions.

Image And Video Sizing

The SDK computes image and video dimensions from CSS and the channel sizing handlers.

Maximum size

Use --str-chat__attachment-max-width to control the maximum width and height used by image and video attachments. The value must resolve to pixels through getComputedStyle, for example 300px, 10rem, or calc(300px - var(--margin)).

If the value does not resolve to a pixel value, attachment sizing can break and message-list scroll behavior can become inaccurate.

File size optimization

The default image and video renderers use the attachment dimensions together with Stream's CDN so the SDK can request a smaller asset when possible.

Aspect ratio

The SDK preserves aspect ratio when it can, but cropping can still happen when:

  1. the message layout forces the attachment to fill the available width
  2. Safari stretches portrait media to the configured max width
  3. the host element's size constraints cannot fit the source without cropping
Tip:

If you use your own CDN or custom media sizing rules, provide your own imageAttachmentSizeHandler and videoAttachmentSizeHandler on Channel.

Props

Prop Description Type
actionHandler Attachment action handler. (dataOrName?: string | FormData, value?: string, event?: React.BaseSyntheticEvent) => Promise<void>
AttachmentActions Component used to render attachment actions. Defaults to AttachmentActions. component
attachmentActionsDefaultFocus Controls the default focused action per attachment type. Defaults to { giphy: "send" }. AttachmentActionsDefaultFocusByType
attachments Message attachments to render. (Attachment | SharedLocationResponse)[]
Audio Component used to render audio attachments. Defaults to Audio. component
Card Component used to render link-preview cards. Defaults to Card. component
File Component used to render file attachments. Defaults to FileAttachment. component
Geolocation Component used to render geolocation attachments. Defaults to Geolocation. component
Giphy Component used to render giphy attachments. Defaults to Giphy. component
Image Component used to render image attachments. Defaults to Image. component
isQuoted Renders the attachment in quoted-message mode. boolean
Media Component used to render media attachments. Defaults to VideoPlayer. component
ModalGallery Component used to render the attachment gallery modal. Defaults to ModalGallery. component
UnsupportedAttachment Component used when the SDK cannot choose a more specific attachment renderer. Defaults to UnsupportedAttachment; uses AttachmentFileIcon from ComponentContext for the icon (same as File). component
VoiceRecording Component used to render voice-recording attachments. Defaults to VoiceRecording. component