Attachments

The Attachment component takes a list of message attachments and conditionally renders the UI of each individual attachment based upon its type. The following table shows the attachment UI components that will be rendered for various attachment types:

Attachment TypeUI ComponentFile type(s) (non-exhaustive)
audioAudioMP3, WAV, M4A, FLAC, AAC
fileFileDOC, DOCX, PDF, PPT, PPTX, TXT, XLS, XLSX
galleryGallerywhen a message has more than 1 ‘image’ type attachment
imageImageHEIC, GIF, JPEG, JPG, PNG, TIFF, BMP
videoReactPlayerMP4, OGG, WEBM, Quicktime(QTFF, QT, or MOV)

Message attachment objects that do not conform to one of the above types are considered to contain scraped content and should contain at least og_scrape_url or title_link to be rendered with the Card component. Otherwise, the attachment is not rendered.

Basic Usage

By default, the Attachment component is included within MessageSimple. To render message attachment UI within a custom Message UI component, import the Attachment component and render it conditionally based upon the presence of message attachments.

const CustomMessage = () => {
  // consume `MessageContext`
  const { message } = useMessageContext();

  const hasAttachments = message.attachments && message.attachments.length > 0;

  return (
    <div>
      {hasAttachments && <Attachment attachments={message.attachments} />}
      // render remaining custom Message UI
    </div>
  );
};

<Chat client={client}>
  <Channel channel={channel} Message={CustomMessage}>
    <MessageList />
    <MessageInput />
  </Channel>
</Chat>;

UI Customization

Attachment accepts component override props for each attachment UI component. Building upon the previous example, the below snippets show how to customize one of the individual attachment UI components with either custom Message UI component:

const CustomImage = (props) => {
  // render custom image component here
};

const CustomMessage = () => {
  // consume `MessageContext`
  const { message } = useMessageContext();

  const hasAttachments = message.attachments && message.attachments.length > 0;

  return (
    <div>
      {hasAttachments && <Attachment attachments={message.attachments} Image={CustomImage} />}
      {/* render remaining custom Message UI */}
    </div>
  );
};

<Chat client={client}>
  <Channel channel={channel} Message={CustomMessage}>
    <MessageList />
    <MessageInput />
  </Channel>
</Chat>;

or using wrapped Attachment component:

const CustomAudioAttachment = (props) => {
  // you can add any custom data (such as "customType" in this case)
  if (props.og?.customType === 'voice-memo') return <div>my custom voice-memo component</div>;
  return <Audio {...props} />;
};

const CustomAttachment = (props) => {
  return <Attachment {...props} Audio={CustomAudioAttachment} />;
};

<Chat client={client}>
  <Channel channel={channel} Attachment={CustomAttachment}>
    <MessageList />
    <MessageInput />
  </Channel>
</Chat>;

Image and video sizing

The following section details how the width and height of images and videos uploaded from files are computed.

Maximum size

You can control the maximum width and height of images and videos with the --str-chat__attachment-max-width CSS variable. The value of this variable must be a value that can be computed to a valid pixel value using the getComputedStyle method (for example: 300px, 10rem, calc(300px - var(--margin)), but not 100%). If you provide an invalid value, the image and video sizing can break, which can lead to scrolling issues inside the message list (for example the message list isn’t scrolled to the bottom when you open a channel).

If you set an invalid value to the variable, you’ll see a warning on the browser’s console:

AttachmentSizeWarning

File size optimization

Based on the CSS settings provided for images and videos (see Maximum size section), the SDK will load an image (or thumbnail image in case of a video file) with a reduced file size while still providing sufficient image quality for the given dimensions. This will result in less network traffic and faster image load for users.

For example if an image has max-width and max-height set to 300px and the original image has the following dimensions: 965 × 1280 it’s enough to load an image with a reduced file size, file size reduction is done by Stream’s CDN.

Aspect ratio

The SDK will try to display images and videos with their original aspect ratio, however this isn’t always guaranteed (in those cases a cropped image will be displayed). Three notable exceptions are:

  1. if a message contains multiple lines of texts and/or multiple attachments, the image/video might be stretched to its max-width

Example 1 - message with one line of text - image is displayed with original aspect ratio

ImageSizing1

Example 2 - message with multiple lines of text - image is cropped

ImageSizing2

  1. in Safari, images/videos with portrait orientation are stretched to max-width

Example 3 - portrait images in Safari - image is cropped

ImageSizing3

  1. if the image/video can’t be rendered with the original aspect ratio given the max-width and max-height constraints of the host HTML element

File size optimization and maintaining aspect ratio uses features provided by Stream’s CDN. If you’re using your own CDN you’ll likely have to provide your own implementation for this. You can do this using the imageAttachmentSizeHandler and videoAttachmentSizeHandler props.

If you’re planning to rewrite attachment sizing with your own CSS code it’s important to note that:

The sizing logic for images and videos (the imageAttachmentSizeHandler and videoAttachmentSizeHandler) requires that host elements of images and videos (ususally img and video elements) have max-height/height and max-width properties defined and that these values can be computed to a valid pixel value using the getComputedStyle (for more information refer to the Maximum size section).

Props

attachments

The message attachments to render, see Attachment Format in the general JavaScript docs.

Type
array

actionHandler

The handler function to call when an action is performed on an attachment, examples include canceling a /giphy command or shuffling the results.

Type
(dataOrName?: string | FormData, value?: string, event?: React.BaseSyntheticEvent) => Promise<void>

AttachmentActions

Custom UI component for displaying attachment actions.

TypeDefault
componentAttachmentActions

Audio

Custom UI component for displaying an audio type attachment.

TypeDefault
componentAudio

Card

Custom UI component for displaying a card type attachment.

TypeDefault
componentCard

File

Custom UI component for displaying a file type attachment.

TypeDefault
componentFile

Custom UI component for displaying a gallery of image type attachments.

TypeDefault
componentGallery

Image

Custom UI component for displaying an image type attachment.

TypeDefault
componentImage

Media

Custom UI component for displaying a video type attachment, defaults to use the react-player dependency.

TypeDefault
componentReactPlayer
© Getstream.io, Inc. All Rights Reserved.