Skip to main content
Version: v5

Custom Attachments

The AttachmentFactory class allows you to build your own attachments to display in the Message List and in the MessageComposer before sending the attachment. It exposes the following properties and behavior:

public open class AttachmentFactory constructor(
public val canHandle: (attachments: List<Attachment>) -> Boolean,
public val previewContent: (
@Composable (
modifier: Modifier,
attachments: List<Attachment>,
onAttachmentRemoved: (Attachment) -> Unit,
) -> Unit
)? = null,
public val content: @Composable (
modifier: Modifier,
attachmentState: AttachmentState,
) -> Unit,
public val textFormatter: (attachments: Attachment) -> String = Attachment::previewText,
  • canHandle: Lambda function that accepts a List of attachments in a message and returns true if a given factory can consume the attachments and show some UI.
  • previewContent: Lambda function that accepts a Modifier, List of Attachments and an onAttachmentRemoved handler. It's used to render selected attachments in the MessageComposer or the MessageInput before sending the message.
  • content: Defines the composable function that accepts a Modifier and an AttachmentState and shows a given attachment component in the message list.
  • textFormatter: Lambda function that accepts an attachment and returns a string representation for it.

There are a few examples of default attachment factory implementations, in the StreamAttachmentFactories.kt file:

public fun defaultFactories(
): List<AttachmentFactory> = listOf(

These factories perform specific checks that you can explore by opening each specific factory.

Each of these factories supplies a predicate, as well as two content composable lambda functions that provide the appropriate content in the message input or the message list.

To customize the factories your code uses, you can always override the attachmentFactories parameter of the ChatTheme wrapper:

override fun onCreate(savedInstanceState: Bundle?) {
val defaultFactories = StreamAttachmentFactories.defaultFactories()

setContent {
// override the default factories by adding your own
ChatTheme(attachmentFactories = myAttachmentFactories + defaultFactories) {
// Chat components

That way, you can build any type of factory you want, to show things like the user location within a Google Maps component, audio files, videos and more.


Because we pick the first factory that can handle the attachments, the order of the factories matters when rendering the UI.

Make sure to always put the higher priority Attachment factories first.

Quoted Attachments

You can also customize the way attachments are displayed inside quoted messages. The approach used is nearly identical to the one shown in the previous example, with only the last step of the process being different.

After creating new attachment factories which display custom attachments inside quoted messages, you override ChatTheme.quotedAttachmentFactories like so:

override fun onCreate(savedInstanceState: Bundle?) {
val myQuotedAttachmentFactories = listOf<AttachmentFactory>()
val defaultFactories = StreamAttachmentFactories.defaultQuotedFactories()

setContent {
// override the default factories by adding your own
ChatTheme(quotedAttachmentFactories = myQuotedAttachmentFactories + defaultFactories) {
// Chat components

In-Depth Guide

If you want to see a real world example of creating custom attachments, check out our detailed guide on creating custom attachments.

Did you find this page helpful?