# Attachments

> **Info:** This is release candidate documentation for **Stream Chat React Native SDK v10**. For the latest stable version, see the [latest version (v9)](https://getstream.io/chat/docs/sdk/react-native/).

A message's attachments render in its bubble, as parts of [`MessageContent`](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/message/message-ui/#messagecontent-props). `Message` sorts them by kind into the `MessageContext` values `images`, `videos`, `files` and `otherAttachments`, and each kind renders in its own part of `messageContentOrder`: `Gallery` for images and videos, `FileAttachmentGroup` for files, and `Attachment` for each of the others. Every component on this page is an override key of the same name, except `UrlPreview`, whose default is `URLPreview`, and `FileAttachmentIcon`, whose default is `FileIcon`. [Attachments and uploads](https://getstream.io/chat/docs/sdk/react-native/v10/features/rich-content/attachments-and-uploads/) covers the feature across the layers.

## Best practices

- Render a custom attachment type by overriding `Attachment`, and hand every other type to the default `Attachment`, as below. [Custom attachments](https://getstream.io/chat/docs/sdk/react-native/v10/ui-cookbook/message/custom-attachments/) builds a complete one.
- Replace one kind through its own key, such as `FileAttachment` or `UrlPreview`, rather than `Attachment` as a whole.
- Change what a tap on an attachment does with `onPressMessage` on `Channel`: the payload's `emitter` says which kind was pressed, and `additionalInfo` carries the attachment, the thumbnail or the URL. Call `defaultHandler()` to keep the SDK's behavior.
- Install a video player, an audio player and a document picker through the native handlers you need. Without a video player, videos render as files; without an audio player, audio attachments do.

## Basic usage

A message with an attachment of type `product`, sent from your backend, renders `UnsupportedAttachment` by default. This override renders it as a card and hands every other attachment to the default:

```tsx title="src/AttachmentWithProducts.tsx"
import { StyleSheet, Text, View } from "react-native";
import {
  Attachment,
  type AttachmentProps,
  WithComponents,
} from "stream-chat-react-native";

const AttachmentWithProducts = (props: AttachmentProps) => {
  const { attachment } = props;

  if (attachment?.type === "product") {
    return (
      <View style={styles.card}>
        <Text style={styles.title}>{attachment.title}</Text>
        {attachment.text ? <Text>{attachment.text}</Text> : null}
      </View>
    );
  }

  return <Attachment {...props} />;
};

const overrides = { Attachment: AttachmentWithProducts };

export const MessagesWithProducts = ({
  children,
}: {
  children: React.ReactNode;
}) => <WithComponents overrides={overrides}>{children}</WithComponents>;

const styles = StyleSheet.create({
  card: { borderRadius: 12, gap: 4, padding: 12, width: 240 },
  title: { fontWeight: "600" },
});
```

A custom type lands in `otherAttachments`, which renders only while the message has no file, image or video attachment.

## How attachments are sorted

| Attachment                                                 | `MessageContext` value | Renders                                                              |
| ---------------------------------------------------------- | ---------------------- | -------------------------------------------------------------------- |
| an image with an image URL, not a link preview             | `images`               | `Gallery`                                                            |
| a video, not a link preview, with a video player installed | `videos`               | `Gallery`, with `VideoThumbnail`                                     |
| a video without a video player                             | `files`                | `FileAttachment`                                                     |
| a file                                                     | `files`                | `FileAttachment`                                                     |
| audio or a voice recording                                 | `files`                | `AudioAttachment`, or `FileAttachment` without an audio player       |
| an image with `og_scrape_url` or `title_link`              | `files`                | `UrlPreview`, or `URLPreviewCompact` with `urlPreviewType="compact"` |
| Giphy or Imgur                                             | `otherAttachments`     | `Giphy`                                                              |
| a link preview of another type                             | `otherAttachments`     | `UrlPreview` or `URLPreviewCompact`                                  |
| any other type                                             | `otherAttachments`     | `UnsupportedAttachment`                                              |

A file, image or video attachment empties `otherAttachments`, so a message holds either those or the others. An image without an image URL isn't rendered.

## Attachment

Renders one attachment by its type, in this order: `Giphy` for a Giphy or Imgur attachment; `URLPreviewCompact` or `UrlPreview` for one with `og_scrape_url` or `title_link`; `Gallery` for an image or a playable video; `AudioAttachment` for audio or a voice recording, with its upload progress while it uploads; `FileAttachment` for a file; and `UnsupportedAttachment` otherwise. `FileAttachmentGroup` renders each file through the `Attachment` key too.

| Prop                | Type                                                                          | Default | Description                                              |
| ------------------- | ----------------------------------------------------------------------------- | ------- | -------------------------------------------------------- |
| `attachment`        | `AttachmentType`                                                              |         | The attachment to render. Without it, nothing renders.   |
| `index`             | `number`                                                                      |         | Not used, since `Attachment` doesn't pass it on.         |
| `isAttachmentEqual` | `(prevAttachment: AttachmentType, nextAttachment: AttachmentType) => boolean` |         | Not used. The component reads it from `MessagesContext`. |
| `message`           | `LocalMessage`                                                                |         | Not used. The component reads it from `MessageContext`.  |
| `myMessageTheme`    | `DeepPartial<Theme>`                                                          |         | Not used. The component reads it from `MessagesContext`. |
| `urlPreviewType`    | `"compact" \| "full"`                                                         |         | Not used. The component reads it from `MessagesContext`. |

`AttachmentType` is the `Attachment` type of `stream-chat`, imported under another name.

## Gallery

Renders images and videos as a grid of up to four thumbnails, with "+3" over the last one when there are more. Pressing a thumbnail reports the `gallery` emitter with the thumbnail as `additionalInfo`; by default it opens the image gallery at that image or video. A prop set here wins over its context value.

| Prop                       | Type                                                   | Default                | Description                                                                                                                        |
| -------------------------- | ------------------------------------------------------ | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `additionalPressableProps` | `Omit<PressableProps, "style">`                        | from `MessagesContext` | Props for each thumbnail's `Pressable`, applied after its handlers.                                                                |
| `alignment`                | `Alignment`                                            | from `MessageContext`  | Aligns the grid left or right.                                                                                                     |
| `channelId`                | `string`                                               |                        | Not used.                                                                                                                          |
| `imageGalleryStateStore`   | `ImageGalleryStateStore`                               |                        | Not used. The component reads it from `ImageGalleryContext`.                                                                       |
| `images`                   | `Attachment[]`                                         | from `MessageContext`  | The images to show.                                                                                                                |
| `message`                  | `LocalMessage`                                         | from `MessageContext`  | The message the image gallery opens with.                                                                                          |
| `messageContentOrder`      | `MessageContentType[]`                                 | from `MessageContext`  | With the gallery as the only part and one image or video, the thumbnail's bottom corners are square, so the bubble's corners show. |
| `messageHasOnlyOneMedia`   | `boolean`                                              |                        | Not used. `Gallery` works it out from `messageContentOrder`.                                                                       |
| `myMessageTheme`           | `DeepPartial<Theme>`                                   | from `MessagesContext` | The grid re-renders when it changes.                                                                                               |
| `onLongPress`              | `(payload: PressableHandlerPayload) => void`           | from `MessageContext`  | Called on a long press on a thumbnail.                                                                                             |
| `onPress`                  | `(payload: MessagePressableHandlerPayload) => void`    | from `MessageContext`  | Called on a press on a thumbnail.                                                                                                  |
| `onPressIn`                | `((payload: PressableHandlerPayload) => void) \| null` | from `MessageContext`  | Called when a press on a thumbnail starts.                                                                                         |
| `preventPress`             | `boolean`                                              | from `MessageContext`  | Turns off presses.                                                                                                                 |
| `setOverlay`               | `React.Dispatch<React.SetStateAction<Overlay>>`        | from `OverlayContext`  | Shows the image gallery overlay.                                                                                                   |
| `videos`                   | `Attachment[]`                                         | from `MessageContext`  | The videos to show.                                                                                                                |

The sizes of the grid come from `theme.messageItemView.gallery`.

### VideoThumbnail

Renders a video's thumbnail with a play icon, inside a `Gallery`. Without `thumb_url` it renders only its container.

| Prop         | Type                    | Default | Description                                                     |
| ------------ | ----------------------- | ------- | --------------------------------------------------------------- |
| `imageStyle` | `StyleProp<ImageStyle>` |         | Style of the image.                                             |
| `localId`    | `string`                |         | The ID of a pending upload, whose progress the thumbnail shows. |
| `style`      | `StyleProp<ViewStyle>`  |         | Style of the container.                                         |
| `thumb_url`  | `string`                |         | The URL of the thumbnail image.                                 |

## Giphy

Renders a Giphy or Imgur attachment. A Giphy preview from the `/giphy` command, which has actions, shows "Only visible to you" and the action buttons, such as **Send**, **Shuffle** and **Cancel**; pressing one calls `handleAction`. A sent Giphy renders the image, and pressing it reports the `giphy` emitter. It renders nothing without `image_url` or `thumb_url`. A prop set here wins over its context value.

| Prop                       | Type                                                   | Default                | Description                              |
| -------------------------- | ------------------------------------------------------ | ---------------------- | ---------------------------------------- |
| `additionalPressableProps` | `Omit<PressableProps, "style">`                        | from `MessagesContext` | Props for the image's `Pressable`.       |
| `attachment`               | `Attachment`                                           | required               | The Giphy or Imgur attachment.           |
| `giphyVersion`             | `keyof Images`                                         | from `MessagesContext` | The Giphy rendition to show.             |
| `handleAction`             | `ActionHandler`                                        | from `MessageContext`  | Sends the action of a pressed button.    |
| `isMyMessage`              | `boolean`                                              | from `MessageContext`  | Picks the background color.              |
| `onLongPress`              | `(payload: PressableHandlerPayload) => void`           | from `MessageContext`  | Called on a long press on the image.     |
| `onPress`                  | `(payload: MessagePressableHandlerPayload) => void`    | from `MessageContext`  | Called on a press on the image.          |
| `onPressIn`                | `((payload: PressableHandlerPayload) => void) \| null` | from `MessageContext`  | Called when a press on the image starts. |
| `preventPress`             | `boolean`                                              | from `MessageContext`  | Turns off presses on the image.          |

`GiphyImage` renders the image itself, and is exported for a Giphy component of your own.

## FileAttachmentGroup

Renders the message's `files`, each through the `Attachment` override, in a column.

| Prop      | Type                                                                                       | Default               | Description                                                                                                            |
| --------- | ------------------------------------------------------------------------------------------ | --------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `files`   | `Attachment[]`                                                                             | from `MessageContext` | The attachments to render.                                                                                             |
| `message` | `LocalMessage`                                                                             |                       | Not used. The component reads it from `MessageContext`.                                                                |
| `styles`  | `Partial<{ attachmentContainer: StyleProp<ViewStyle>; container: StyleProp<ViewStyle>; }>` |                       | Not used, since the component doesn't pass it on. Style the group through `theme.messageItemView.fileAttachmentGroup`. |

## FileAttachment

Renders a file through the `FilePreview` override, with the file's icon and title, and its upload progress while it uploads. Pressing it reports the `fileAttachment` emitter with the attachment as `additionalInfo`; by default it opens the file's `asset_url`. A prop set here wins over its context value.

| Prop                       | Type                                                                                                                                    | Default                    | Description                                                               |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | ------------------------------------------------------------------------- |
| `additionalPressableProps` | `Omit<PressableProps, "style">`                                                                                                         | from `MessagesContext`     | Props for the `Pressable`, applied after its handlers.                    |
| `attachment`               | `Attachment`                                                                                                                            | required                   | The file.                                                                 |
| `attachmentIconSize`       | `"sm" \| "md" \| "lg"`                                                                                                                  | `'md'`                     | The size of the file's icon.                                              |
| `onLongPress`              | `(payload: PressableHandlerPayload) => void`                                                                                            | from `MessageContext`      | Called on a long press.                                                   |
| `onPress`                  | `(payload: MessagePressableHandlerPayload) => void`                                                                                     | from `MessageContext`      | Called on a press.                                                        |
| `onPressIn`                | `((payload: PressableHandlerPayload) => void) \| null`                                                                                  | from `MessageContext`      | Called when a press starts.                                               |
| `preventPress`             | `boolean`                                                                                                                               | from `MessageContext`      | Turns off presses.                                                        |
| `styles`                   | `Partial<{ container: StyleProp<ViewStyle>; details: StyleProp<ViewStyle>; size: StyleProp<TextStyle>; title: StyleProp<TextStyle>; }>` | the component's own styles | Styles passed to `FilePreview`. A value replaces the defaults as a whole. |

### FilePreview

Renders the `FileAttachmentIcon` override for the file's `custom.mime_type`, the title, and under it `indicator`, or the size or the duration when there's no `indicator`. It isn't exported; replace it with the `FilePreview` key.

| Prop                 | Type                                                                                                                                    | Default  | Description                                                                                       |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------- |
| `attachment`         | `Attachment`                                                                                                                            | required | The file.                                                                                         |
| `attachmentIconSize` | `"sm" \| "md" \| "lg"`                                                                                                                  | `'md'`   | The size of the icon.                                                                             |
| `indicator`          | `React.ReactNode`                                                                                                                       |          | Rendered in place of the size or duration line. `FileAttachment` passes its upload progress here. |
| `styles`             | `Partial<{ container: StyleProp<ViewStyle>; details: StyleProp<ViewStyle>; size: StyleProp<TextStyle>; title: StyleProp<TextStyle>; }>` |          | Styles merged after the theme's.                                                                  |
| `titleNumberOfLines` | `number`                                                                                                                                | `2`      | The number of lines of the title.                                                                 |

### FileIcon

Renders the icon for a MIME type, from the `icons` override map: `PDF`, `DOC`, `SpreadSheet`, `Presentation`, `ZIP`, `Audio`, `Video`, `Code`, or `OtherFileIcon` for any other type. It's the default of the `FileAttachmentIcon` key.

| Prop       | Type                   | Default | Description                                                  |
| ---------- | ---------------------- | ------- | ------------------------------------------------------------ |
| `mimeType` | `string`               |         | The file's MIME type.                                        |
| `size`     | `"sm" \| "md" \| "lg"` | `'md'`  | `'sm'` is 19 by 24 points, `'md'` 32 by 40, `'lg'` 40 by 48. |

## AudioAttachment

Plays an audio attachment or a voice recording: a play button, the remaining time, a waveform for a voice recording with `waveform_data` or a progress bar otherwise, which the user can drag to seek, and a speed button. Each message's attachment has its own player; [Voice recordings and audio playback](https://getstream.io/chat/docs/sdk/react-native/v10/features/rich-content/voice-recordings-and-audio-playback/) explains how players are shared and when they stop. In a message, `Attachment` renders it with `showTitle={false}` and `showSpeedSettings`.

| Prop                | Type                                                                                                                                                                                                   | Default  | Description                                                                                                                             |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `containerStyle`    | `StyleProp<ViewStyle>`                                                                                                                                                                                 |          | Style of the container.                                                                                                                 |
| `hideProgressBar`   | `boolean`                                                                                                                                                                                              | `false`  | Hides the waveform or progress bar.                                                                                                     |
| `indicator`         | `React.ReactNode`                                                                                                                                                                                      |          | Rendered in place of the time and progress, and hides the speed button. `Attachment` passes the upload progress while the file uploads. |
| `isPreview`         | `boolean`                                                                                                                                                                                              | `false`  | Set when the attachment shows in the composer. The player is released when the preview unmounts.                                        |
| `item`              | `AudioAttachmentType`                                                                                                                                                                                  | required | The attachment, with an `id` and `type: 'audio' \| 'voiceRecording'`.                                                                   |
| `message`           | `LocalMessage`                                                                                                                                                                                         |          | The message, which identifies the attachment's player.                                                                                  |
| `showSpeedSettings` | `boolean`                                                                                                                                                                                              | `false`  | Shows the playback speed button.                                                                                                        |
| `showTitle`         | `boolean`                                                                                                                                                                                              | `true`   | Shows the title, or "Voice Message" for a voice recording.                                                                              |
| `styles`            | `{ container?: StyleProp<ViewStyle>; playPauseButton?: StyleProp<ViewStyle>; speedSettingsButton?: StyleProp<ViewStyle>; durationText?: StyleProp<TextStyle>; leftContainer?: StyleProp<TextStyle>; }` |          | Styles of the parts.                                                                                                                    |
| `testID`            | `string`                                                                                                                                                                                               |          | The container's `testID`.                                                                                                               |

## URLPreview and URLPreviewCompact

`URLPreview`, the default of the `UrlPreview` key, renders a link preview as a card: the image, with a play icon for a video link, the title, the description and the URL. `URLPreviewCompact` renders the same in a smaller layout, and `urlPreviewType="compact"` on `Channel` picks it. Pressing either reports the `urlPreview` emitter with the URL as `additionalInfo`; by default it opens `og_scrape_url`. Both remount when the message updates. [Link previews](https://getstream.io/chat/docs/sdk/react-native/v10/features/rich-content/link-previews/) covers the feature.

| Prop                       | Type                                                                                                                                                                                                                                                          | Default                       | Description                                                                                            |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------ |
| `additionalPressableProps` | `Omit<PressableProps, "style">`                                                                                                                                                                                                                               | from `MessagesContext`        | Props for the card's `Pressable`, applied after its handlers.                                          |
| `attachment`               | `Attachment`                                                                                                                                                                                                                                                  | required                      | The link preview.                                                                                      |
| `channelId`                | `string`                                                                                                                                                                                                                                                      |                               | Not used.                                                                                              |
| `ImageComponent`           | `React.ComponentType<ImageProps>`                                                                                                                                                                                                                             | the `ImageComponent` override | Renders the image.                                                                                     |
| `isAttachmentEqual`        | `(prevAttachment: Attachment, nextAttachment: Attachment) => boolean`                                                                                                                                                                                         | from `MessagesContext`        | When set, decides whether the card re-renders once the SDK's own check finds the attachment unchanged. |
| `messageId`                | `string`                                                                                                                                                                                                                                                      |                               | Not used.                                                                                              |
| `myMessageTheme`           | `DeepPartial<Theme>`                                                                                                                                                                                                                                          | from `MessagesContext`        | The card re-renders when it changes.                                                                   |
| `onLongPress`              | `(payload: PressableHandlerPayload) => void`                                                                                                                                                                                                                  | from `MessageContext`         | Called on a long press.                                                                                |
| `onPress`                  | `(payload: MessagePressableHandlerPayload) => void`                                                                                                                                                                                                           | from `MessageContext`         | Called on a press.                                                                                     |
| `onPressIn`                | `((payload: PressableHandlerPayload) => void) \| null`                                                                                                                                                                                                        | from `MessageContext`         | Called when a press starts.                                                                            |
| `preventPress`             | `boolean`                                                                                                                                                                                                                                                     | from `MessageContext`         | Turns off presses.                                                                                     |
| `styles`                   | `Partial<{ cardCover: StyleProp<ImageStyle>; cardFooter: StyleProp<ViewStyle>; container: StyleProp<ViewStyle>; description: StyleProp<TextStyle>; linkPreview: StyleProp<ViewStyle>; linkPreviewText: StyleProp<TextStyle>; title: StyleProp<TextStyle>; }>` |                               | Styles of the parts.                                                                                   |

`URLPreviewCompact` takes the same props without `isAttachmentEqual`:

| Prop                       | Type                                                                                                                                                                                                                                                          | Default                       | Description                                                   |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ------------------------------------------------------------- |
| `additionalPressableProps` | `Omit<PressableProps, "style">`                                                                                                                                                                                                                               | from `MessagesContext`        | Props for the card's `Pressable`, applied after its handlers. |
| `attachment`               | `Attachment`                                                                                                                                                                                                                                                  | required                      | The link preview.                                             |
| `channelId`                | `string`                                                                                                                                                                                                                                                      |                               | Not used.                                                     |
| `ImageComponent`           | `React.ComponentType<ImageProps>`                                                                                                                                                                                                                             | the `ImageComponent` override | Renders the image.                                            |
| `messageId`                | `string`                                                                                                                                                                                                                                                      |                               | Not used.                                                     |
| `myMessageTheme`           | `DeepPartial<Theme>`                                                                                                                                                                                                                                          | from `MessagesContext`        | The card re-renders when it changes.                          |
| `onLongPress`              | `(payload: PressableHandlerPayload) => void`                                                                                                                                                                                                                  | from `MessageContext`         | Called on a long press.                                       |
| `onPress`                  | `(payload: MessagePressableHandlerPayload) => void`                                                                                                                                                                                                           | from `MessageContext`         | Called on a press.                                            |
| `onPressIn`                | `((payload: PressableHandlerPayload) => void) \| null`                                                                                                                                                                                                        | from `MessageContext`         | Called when a press starts.                                   |
| `preventPress`             | `boolean`                                                                                                                                                                                                                                                     | from `MessageContext`         | Turns off presses.                                            |
| `styles`                   | `Partial<{ cardCover: StyleProp<ImageStyle>; cardFooter: StyleProp<ViewStyle>; container: StyleProp<ViewStyle>; description: StyleProp<TextStyle>; linkPreview: StyleProp<ViewStyle>; linkPreviewText: StyleProp<TextStyle>; title: StyleProp<TextStyle>; }>` |                               | Styles of the parts.                                          |

## UnsupportedAttachment

Renders an attachment of a type the SDK doesn't know: the `FileAttachmentIcon` override for its `custom.mime_type`, and its title, or "Unsupported Attachment". It isn't exported; replace it with the `UnsupportedAttachment` key, or render your type from an `Attachment` override as above.

| Prop                 | Type                   | Default  | Description                                             |
| -------------------- | ---------------------- | -------- | ------------------------------------------------------- |
| `attachment`         | `Attachment`           | required | The attachment.                                         |
| `attachmentIconSize` | `"sm" \| "md" \| "lg"` | `'md'`   | The size of the icon.                                   |
| `isMyMessage`        | `boolean`              |          | Not used. The component reads it from `MessageContext`. |

## Related hooks

- `useMessageContext()` returns the message's attachments by kind: `images`, `videos`, `files` and `otherAttachments`.
- `useAudioPlayer()` returns the player of an audio attachment, for a player of your own. See [Voice recordings and audio playback](https://getstream.io/chat/docs/sdk/react-native/v10/features/rich-content/voice-recordings-and-audio-playback/#a-player-of-your-own).
- `buildGallery()` computes the grid `Gallery` lays out.

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/message/attachments/](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/message/attachments/).