### Plain messages
Note that timestamp and status can be hidden with the `collapseMetadata` boolean property.
```jsx
console.log('onDownload')}
onReply={() => console.log('onReply')}
onShowDetail={() => console.log('onShowDetail')}
onDelete={() => console.log('onDelete')}
/>
console.log('onDownload')}
onReply={() => console.log('onReply')}
onShowDetail={() => console.log('onShowDetail')}
onDelete={() => console.log('onDelete')}
/>
console.log('onDownload')}
onReply={() => console.log('onReply')}
onShowDetail={() => console.log('onShowDetail')}
onDelete={() => console.log('onDelete')}
/>
console.log('onDownload')}
onReply={() => console.log('onReply')}
onShowDetail={() => console.log('onShowDetail')}
onDelete={() => console.log('onDelete')}
/>
console.log('onDownload')}
onReply={() => console.log('onReply')}
onShowDetail={() => console.log('onShowDetail')}
onDelete={() => console.log('onDelete')}
/>
console.log('onDownload')}
onReply={() => console.log('onReply')}
onShowDetail={() => console.log('onShowDetail')}
onDelete={() => console.log('onDelete')}
/>
console.log('onDownload')}
onReply={() => console.log('onReply')}
onShowDetail={() => console.log('onShowDetail')}
onDelete={() => console.log('onDelete')}
/>
console.log('onDownload')}
onReply={() => console.log('onReply')}
onShowDetail={() => console.log('onShowDetail')}
onDelete={() => console.log('onDelete')}
/>
console.log('onDownload')}
onReply={() => console.log('onReply')}
onShowDetail={() => console.log('onShowDetail')}
onDelete={() => console.log('onDelete')}
/>
console.log('onDownload')}
onReply={() => console.log('onReply')}
onShowDetail={() => console.log('onShowDetail')}
onDelete={() => console.log('onDelete')}
/>
```
### Status
```jsx
console.log('onRetrySend')}
/>
console.log('onRetrySend')}
/>
console.log('onRetrySend')}
/>
console.log('onRetrySend')}
/>
```
### All colors
```jsx
```
### Long data
```jsx
```
### Pending long message download
```jsx
```
### With an attachment
#### Image with caption
```jsx
console.log('showVisualAttachment')}
onDownload={() => console.log('onDownload')}
onReply={() => console.log('onReply')}
/>
console.log('showVisualAttachment')}
onDownload={() => console.log('onDownload')}
onReply={() => console.log('onReply')}
/>
console.log('showVisualAttachment')}
onDownload={() => console.log('onDownload')}
onReply={() => console.log('onReply')}
/>
console.log('showVisualAttachment')}
onDownload={() => console.log('onDownload')}
onReply={() => console.log('onReply')}
/>
```
#### Image
First, showing the metadata overlay on dark and light images, then a message with `collapseMetadata` set.
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Sticker
Stickers have no background, but they have all the standard message bubble features.
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Sticker with collapsed metadata
First set is in a 1:1 conversation, second set is in a group.
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Sticker with pending image
A sticker with no attachments (what our selectors produce for a pending sticker) is not displayed at all.
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Multiple images
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Multiple images with caption
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Outgoing image with status
Note that the delivered indicator is always Signal Blue, not the conversation color.
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Pending images
```
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Image with portrait aspect ratio
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Image with portrait aspect ratio and caption
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
expirationLength={5 * 60 * 1000}
expirationTimestamp={Date.now() + 5 * 60 * 1000}
/>
console.log('showVisualAttachment')}
expirationLength={5 * 60 * 1000}
expirationTimestamp={Date.now() + 5 * 60 * 1000}
/>
```
#### Image with landscape aspect ratio
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Image with landscape aspect ratio and caption
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Video with caption
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Video
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Missing images and videos
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Broken source URL images and videos
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Image/video which is too big
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Image/video missing height/width
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Audio with caption
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Audio
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Voice message
Voice notes are not shown any differently from audio attachments.
#### Other file type with caption
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Other file type
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Other file type pending
```jsx
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
console.log('showVisualAttachment')}
/>
```
#### Dangerous file type
```jsx
console.log('showVisualAttachment - isDangerous:', isDangerous)
}
/>
console.log('showVisualAttachment - isDangerous:', isDangerous)
}
/>
```
#### Link previews, full-size image
```jsx
console.log('onClickLinkPreview', url)}
/>
console.log('onClickLinkPreview', url)}
/>
console.log('onClick'),
}}
text="Pretty sweet link: https://instagram.com/something"
previews={[
{
title: 'This is a really sweet post',
domain: 'instagram.com',
image: {
url: util.pngObjectUrl,
contentType: 'image/png',
width: 800,
height: 1200,
},
},
]}
onClickLinkPreview={url => console.log('onClickLinkPreview', url)}
/>
console.log('onClick'),
}}
text="Pretty sweet link: https://instagram.com/something"
previews={[
{
title: 'This is a really sweet post',
domain: 'instagram.com',
image: {
url: util.pngObjectUrl,
contentType: 'image/png',
width: 800,
height: 1200,
},
},
]}
onClickLinkPreview={url => console.log('onClickLinkPreview', url)}
/>
```
#### Link previews, stickers url
Sticker link previews are forced to use the small link preview form, no matter the image size.
```jsx
console.log('onClickLinkPreview', url)}
/>
console.log('onClickLinkPreview', url)}
/>
```
#### Link previews, small image
```jsx
console.log('onClickLinkPreview', url)}
/>
console.log('onClickLinkPreview', url)}
/>
console.log('onClick'),
}}
text="Pretty sweet link: https://instagram.com/something"
previews={[
{
title:
'This is a really sweet post with a really long name. Gotta restrict that to just two lines, you know how that goes...',
domain: 'instagram.com',
image: {
url: util.pngObjectUrl,
contentType: 'image/png',
width: 160,
height: 120,
},
},
]}
onClickLinkPreview={url => console.log('onClickLinkPreview', url)}
/>
console.log('onClick'),
}}
text="Pretty sweet link: https://instagram.com/something"
previews={[
{
title:
'This is a really sweet post with a really long name. Gotta restrict that to just two lines, you know how that goes...',
domain: 'instagram.com',
image: {
url: util.pngObjectUrl,
contentType: 'image/png',
width: 160,
height: 120,
},
},
]}
onClickLinkPreview={url => console.log('onClickLinkPreview', url)}
/>
```
#### Link previews with pending image
```jsx
console.log('onClickLinkPreview', url)}
/>
console.log('onClickLinkPreview', url)}
/>
console.log('onClickLinkPreview', url)}
/>
console.log('onClickLinkPreview', url)}
/>
```
#### Link previews, no image
```jsx
console.log('onClickLinkPreview', url)}
/>
console.log('onClickLinkPreview', url)}
/>
console.log('onClick'),
}}
text="Pretty sweet link: https://instagram.com/something"
previews={[
{
title:
'This is a really sweet post with a really long name. Gotta restrict that to just two lines, you know how that goes...',
domain: 'instagram.com',
},
]}
onClickLinkPreview={url => console.log('onClickLinkPreview', url)}
/>
console.log('onClick'),
}}
text="Pretty sweet link: https://instagram.com/something"
previews={[
{
title:
'This is a really sweet post with a really long name. Gotta restrict that to just two lines, you know how that goes...',
domain: 'instagram.com',
},
]}
onClickLinkPreview={url => console.log('onClickLinkPreview', url)}
/>
```
### Tap to view
```jsx
console.log('displayTapToViewMessage', args)
}
authorAvatarPath={util.gifObjectUrl}
/>
console.log('displayTapToViewMessage', args)
}
/>
console.log('displayTapToViewMessage', args)
}
authorAvatarPath={util.gifObjectUrl}
/>
console.log('displayTapToViewMessage', args)
}
/>
console.log('displayTapToViewMessage', args)
}
/>
console.log('displayTapToViewMessage', args)
}
/>
console.log('displayTapToViewMessage', args)
}
authorAvatarPath={util.gifObjectUrl}
/>
console.log('displayTapToViewMessage', args)
}
authorAvatarPath={util.gifObjectUrl}
/>
console.log('displayTapToViewMessage', args)
}
authorAvatarPath={util.gifObjectUrl}
/>
console.log('displayTapToViewMessage', args)
}
authorAvatarPath={util.gifObjectUrl}
/>
console.log('displayTapToViewMessage', args)
}
authorAvatarPath={util.gifObjectUrl}
/>
console.log('displayTapToViewMessage', args)
}
/>
console.log('displayTapToViewMessage', args)
}
authorAvatarPath={util.gifObjectUrl}
/>
console.log('displayTapToViewMessage', args)
}
authorAvatarPath={util.gifObjectUrl}
/>
console.log('displayTapToViewMessage', args)
}
authorAvatarPath={util.gifObjectUrl}
/>
console.log('displayTapToViewMessage', args)
}
authorAvatarPath={util.gifObjectUrl}
/>
console.log('displayTapToViewMessage', args)
}
authorAvatarPath={util.gifObjectUrl}
/>
```
### In a group conversation
Note that the author avatar goes away if `collapseMetadata` is set.
```jsx
console.log('showVisualAttachment')}
authorAvatarPath={util.gifObjectUrl}
/>
console.log('showVisualAttachment')}
authorAvatarPath={util.gifObjectUrl}
/>
console.log('showVisualAttachment')}
authorAvatarPath={util.gifObjectUrl}
/>
console.log('showVisualAttachment')}
/>
console.log('onClickLinkPreview', url)}
/>
console.log('onClickLinkPreview', url)}
/>
```