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 Type | UI Component | File type(s) (non-exhaustive) |
---|---|---|
audio | Audio | MP3, WAV, M4A, FLAC, AAC |
file | File | DOC, DOCX, PDF, PPT, PPTX, TXT, XLS, XLSX |
gallery | Gallery | when a message has more than 1 'image' type attachment |
image | Image | HEIC, GIF, JPEG, JPG, PNG, TIFF, BMP |
video | ReactPlayer | MP4, 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:
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:
- 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
Example 2 - message with multiple lines of text - image is cropped
- in Safari, images/videos with portrait orientation are stretched to
max-width
Example 3 - portrait images in Safari - image is cropped
- if the image/video can't be rendered with the original aspect ratio given the
max-width
andmax-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
Required 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.
Type | Default |
---|---|
component | AttachmentActions |
Audio
Custom UI component for displaying an audio type attachment.
Type | Default |
---|---|
component | Audio |
Card
Custom UI component for displaying a card type attachment.
Type | Default |
---|---|
component | Card |
File
Custom UI component for displaying a file type attachment.
Type | Default |
---|---|
component | File |
Gallery
Custom UI component for displaying a gallery of image type attachments.
Type | Default |
---|---|
component | Gallery |
Image
Custom UI component for displaying an image type attachment.
Type | Default |
---|---|
component | Image |
Media
Custom UI component for displaying a video type attachment, defaults to use the react-player
dependency.
Type | Default |
---|---|
component | ReactPlayer |