Skip to main content
{
  "component": "CometChatConversations",
  "package": "cometchat_chat_uikit",
  "import": "import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';",
  "description": "Scrollable list of recent one-on-one and group conversations for the logged-in user.",
  "primaryOutput": {
    "prop": "onItemTap",
    "type": "Function(Conversation conversation)"
  },
  "props": {
    "data": {
      "conversationsRequestBuilder": {
        "type": "ConversationsRequestBuilder?",
        "default": "SDK default (30 per page)",
        "note": "Pass the builder, not the result of .build()"
      },
      "conversationsProtocol": {
        "type": "ConversationsBuilderProtocol?",
        "default": "null",
        "note": "Custom protocol for fetching conversations"
      },
      "scrollController": {
        "type": "ScrollController?",
        "default": "null",
        "note": "Custom scroll controller for the list"
      },
      "title": {
        "type": "String?",
        "default": "Chats",
        "note": "Title text for the app bar"
      },
      "controllerTag": {
        "type": "String?",
        "default": "null",
        "note": "Tag for controller management"
      },
      "mentionAllLabel": {
        "type": "String?",
        "default": "null",
        "note": "Custom label for @all mentions"
      },
      "mentionAllLabelId": {
        "type": "String?",
        "default": "null",
        "note": "Custom label ID for @all mentions"
      }
    },
    "callbacks": {
      "onItemTap": "Function(Conversation conversation)?",
      "onItemLongPress": "Function(Conversation conversation)?",
      "onSelection": "Function(List<Conversation>? list)?",
      "onBack": "VoidCallback?",
      "onError": "OnError?",
      "onLoad": "OnLoad<Conversation>?",
      "onEmpty": "OnEmpty?",
      "onSearchTap": "GestureTapCallback?",
      "datePattern": "String Function(Conversation conversation)?",
      "dateTimeFormatterCallback": "DateTimeFormatterCallback?"
    },
    "visibility": {
      "receiptsVisibility": { "type": "bool?", "default": true },
      "usersStatusVisibility": { "type": "bool?", "default": true },
      "groupTypeVisibility": { "type": "bool?", "default": true },
      "deleteConversationOptionVisibility": { "type": "bool?", "default": true },
      "hideAppbar": { "type": "bool?", "default": false },
      "hideError": { "type": "bool?", "default": false },
      "hideSearch": { "type": "bool?", "default": false },
      "showBackButton": { "type": "bool", "default": false },
      "dateBackgroundIsTransparent": { "type": "bool?", "default": null },
      "searchReadOnly": { "type": "bool", "default": false }
    },
    "sound": {
      "disableSoundForMessages": { "type": "bool?", "default": false },
      "customSoundForMessages": { "type": "String?", "default": "built-in" }
    },
    "selection": {
      "selectionMode": {
        "type": "SelectionMode?",
        "values": ["SelectionMode.single", "SelectionMode.multiple", "SelectionMode.none"],
        "default": "null"
      },
      "activateSelection": {
        "type": "ActivateSelection?",
        "values": ["ActivateSelection.onClick", "ActivateSelection.onLongClick"],
        "default": "null"
      }
    },
    "viewSlots": {
      "listItemView": "Widget Function(Conversation conversation)?",
      "leadingView": "Widget? Function(BuildContext context, Conversation conversation)?",
      "titleView": "Widget? Function(BuildContext context, Conversation conversation)?",
      "subtitleView": "Widget? Function(BuildContext context, Conversation conversation)?",
      "trailingView": "Widget? Function(Conversation conversation)?",
      "loadingStateView": "WidgetBuilder?",
      "emptyStateView": "WidgetBuilder?",
      "errorStateView": "WidgetBuilder?",
      "setOptions": "List<CometChatOption>? Function(Conversation, CometChatConversationsController, BuildContext)?",
      "addOptions": "List<CometChatOption>? Function(Conversation, CometChatConversationsController, BuildContext)?"
    },
    "formatting": {
      "textFormatters": {
        "type": "List<CometChatTextFormatter>?",
        "default": "default formatters from data source"
      },
      "typingIndicatorText": {
        "type": "String?",
        "default": "typing..."
      }
    },
    "icons": {
      "backButton": { "type": "Widget?", "default": "built-in back arrow" },
      "protectedGroupIcon": { "type": "Widget?", "default": "built-in lock icon" },
      "privateGroupIcon": { "type": "Widget?", "default": "built-in lock icon" },
      "readIcon": { "type": "Widget?", "default": "built-in read icon" },
      "deliveredIcon": { "type": "Widget?", "default": "built-in delivered icon" },
      "sentIcon": { "type": "Widget?", "default": "built-in sent icon" },
      "submitIcon": { "type": "Widget?", "default": "built-in check icon" },
      "searchBoxIcon": { "type": "Widget?", "default": "built-in search icon" }
    },
    "layout": {
      "datePadding": { "type": "EdgeInsets?", "default": "null" },
      "dateHeight": { "type": "double?", "default": "null" },
      "dateWidth": { "type": "double?", "default": "null" },
      "badgeWidth": { "type": "double?", "default": "null" },
      "badgeHeight": { "type": "double?", "default": "null" },
      "badgePadding": { "type": "EdgeInsetsGeometry?", "default": "null" },
      "avatarWidth": { "type": "double?", "default": "null" },
      "avatarHeight": { "type": "double?", "default": "null" },
      "avatarPadding": { "type": "EdgeInsetsGeometry?", "default": "null" },
      "avatarMargin": { "type": "EdgeInsetsGeometry?", "default": "null" },
      "statusIndicatorWidth": { "type": "double?", "default": "null" },
      "statusIndicatorHeight": { "type": "double?", "default": "null" },
      "statusIndicatorBorderRadius": { "type": "BorderRadiusGeometry?", "default": "null" },
      "searchPadding": { "type": "EdgeInsetsGeometry?", "default": "null" },
      "searchContentPadding": { "type": "EdgeInsetsGeometry?", "default": "null" }
    },
    "style": {
      "conversationsStyle": { "type": "CometChatConversationsStyle", "default": "CometChatConversationsStyle()" },
      "listItemStyle": { "type": "ListItemStyle?", "default": "null" },
      "appBarOptions": { "type": "List<Widget>?", "default": "null" }
    }
  },
  "events": [
    {
      "name": "CometChatConversationEvents.ccConversationDeleted",
      "payload": "Conversation",
      "description": "Conversation deleted from list"
    },
    {
      "name": "CometChatConversationEvents.ccUpdateConversation",
      "payload": "Conversation",
      "description": "Conversation updated"
    },
    {
      "name": "CometChatConversationEvents.ccMessageRead",
      "payload": "BaseMessage",
      "description": "Message marked as read"
    },
    {
      "name": "CometChatConversationEvents.ccMessageSent",
      "payload": "BaseMessage, MessageStatus",
      "description": "Message sent"
    }
  ],
  "sdkListeners": [
    "onTextMessageReceived",
    "onMediaMessageReceived",
    "onCustomMessageReceived",
    "onFormMessageReceived",
    "onCardMessageReceived",
    "onCustomInteractiveMessageReceived",
    "onSchedulerMessageReceived",
    "onTypingStarted",
    "onTypingEnded",
    "onMessagesDelivered",
    "onMessagesRead",
    "onMessagesDeliveredToAll",
    "onMessagesReadByAll",
    "onMessageEdited",
    "onMessageDeleted",
    "onUserOnline",
    "onUserOffline",
    "ccUserBlocked",
    "onGroupMemberJoined",
    "onGroupMemberLeft",
    "onGroupMemberKicked",
    "onGroupMemberBanned",
    "onGroupMemberUnbanned",
    "onGroupMemberScopeChanged",
    "onMemberAddedToGroup",
    "ccOwnershipChanged",
    "ccGroupLeft",
    "ccGroupDeleted",
    "ccGroupMemberAdded",
    "onIncomingCallReceived",
    "onOutgoingCallAccepted",
    "onOutgoingCallRejected",
    "onIncomingCallCancelled",
    "onCallEndedMessageReceived",
    "onConnected"
  ],
  "compositionExample": {
    "description": "Sidebar conversations wired to message view",
    "components": [
      "CometChatConversations",
      "CometChatMessages",
      "CometChatMessageHeader",
      "CometChatMessageList",
      "CometChatMessageComposer"
    ],
    "flow": "onItemTap emits Conversation -> extract User/Group via conversationWith -> pass to CometChatMessages or individual MessageHeader, MessageList, MessageComposer"
  },
  "types": {
    "CometChatOption": {
      "id": "String?",
      "title": "String?",
      "icon": "String?",
      "iconWidget": "Widget?",
      "onClick": "VoidCallback?"
    },
    "SelectionMode": {
      "single": "SelectionMode.single",
      "multiple": "SelectionMode.multiple",
      "none": "SelectionMode.none"
    },
    "ActivateSelection": {
      "onClick": "ActivateSelection.onClick",
      "onLongClick": "ActivateSelection.onLongClick"
    }
  }
}

Where It Fits

CometChatConversations is a sidebar list widget. It renders recent conversations and emits the selected Conversation via onItemTap. Wire it to CometChatMessageHeader, CometChatMessageList, and CometChatMessageComposer to build a standard two-panel chat layout.
import 'package:flutter/material.dart';
import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';

class ChatApp extends StatefulWidget {
  const ChatApp({super.key});

  @override
  State<ChatApp> createState() => _ChatAppState();
}

class _ChatAppState extends State<ChatApp> {
  User? selectedUser;
  Group? selectedGroup;

  void handleItemTap(Conversation conversation) {
    final entity = conversation.conversationWith;
    setState(() {
      if (entity is User) {
        selectedUser = entity;
        selectedGroup = null;
      } else if (entity is Group) {
        selectedGroup = entity;
        selectedUser = null;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: [
          SizedBox(
            width: 400,
            child: CometChatConversations(
              onItemTap: handleItemTap,
            ),
          ),
          Expanded(
            child: selectedUser != null || selectedGroup != null
                ? CometChatMessages(
                    user: selectedUser,
                    group: selectedGroup,
                  )
                : const Center(
                    child: Text('Select a conversation'),
                  ),
          ),
        ],
      ),
    );
  }
}

Minimal Render

import 'package:flutter/material.dart';
import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';

class ConversationsDemo extends StatelessWidget {
  const ConversationsDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: SafeArea(
        child: CometChatConversations(),
      ),
    );
  }
}
You can also launch it using Navigator.push:
Navigator.push(
  context, 
  MaterialPageRoute(builder: (context) => const CometChatConversations())
);

Filtering Conversations

Pass a ConversationsRequestBuilder to conversationsRequestBuilder. Pass the builder instance — not the result of .build().
CometChatConversations(
  conversationsRequestBuilder: ConversationsRequestBuilder()
    ..conversationType = "user"
    ..limit = 10,
)

Filter Recipes

RecipeCode
Only user conversationsConversationsRequestBuilder()..conversationType = "user"
Only group conversationsConversationsRequestBuilder()..conversationType = "group"
Limit to 10 per pageConversationsRequestBuilder()..limit = 10
With specific tagsConversationsRequestBuilder()..tags = ["vip"]
With user and group tagsConversationsRequestBuilder()..withUserAndGroupTags = true
Include blocked usersConversationsRequestBuilder()..includeBlockedUsers = true
Search conversationsConversationsRequestBuilder()..searchKeyword = "hello"
Unread onlyConversationsRequestBuilder()..unread = true
Default page size is 30. The component uses infinite scroll — the next page loads as the user scrolls to the bottom.

ConversationsRequestBuilder Properties

PropertyDescriptionCode
limitNumber of conversations to fetch per request. Maximum 50...limit = 30
conversationTypeFilter by conversation type: "user" or "group". If not set, returns both...conversationType = "user"
withTagsInclude tags associated with conversations. Default false...withTags = true
tagsFilter conversations by specific tags...tags = ["archived", "vip"]
withUserAndGroupTagsInclude user/group tags in the Conversation object. Default false...withUserAndGroupTags = true
includeBlockedUsersInclude conversations with blocked users. Default false...includeBlockedUsers = true
withBlockedInfoInclude blocked info in the ConversationWith object. Default false...withBlockedInfo = true
searchKeywordSearch conversations by user or group name. Requires Advanced plan...searchKeyword = "John"
unreadFetch only unread conversations. Requires Advanced plan...unread = true
build()Builds and returns a ConversationsRequest object..build()
Refer to ConversationsRequestBuilder for the full builder API.

Actions and Events

Callback Props

onItemTap

Fires when a conversation row is tapped. Primary navigation hook — set the active conversation and render the message view.
CometChatConversations(
  onItemTap: (conversation) {
    print("Selected: ${conversation.conversationId}");
  },
)

onItemLongPress

Fires when a conversation row is long-pressed. Useful for showing context menus or custom actions.
CometChatConversations(
  onItemLongPress: (conversation) {
    // Show custom context menu
  },
)

onSelection

Fires when conversations are selected in multi-select mode. Requires selectionMode to be set.
CometChatConversations(
  selectionMode: SelectionMode.multiple,
  onSelection: (selectedList) {
    print("Selected ${selectedList?.length ?? 0} conversations");
  },
)

onError

Fires on internal errors (network failure, auth issue, SDK exception).
CometChatConversations(
  onError: (error) {
    print("CometChatConversations error: $error");
  },
)

onBack

Fires when the back button is pressed.
CometChatConversations(
  showBackButton: true,
  onBack: () {
    Navigator.pop(context);
  },
)

onLoad

Fires when the conversation list is successfully loaded.
CometChatConversations(
  onLoad: (list) {
    print("Loaded ${list.length} conversations");
  },
)

onEmpty

Fires when the conversation list is empty.
CometChatConversations(
  onEmpty: () {
    print("No conversations found");
  },
)

Global UI Events

CometChatConversationEvents emits events subscribable from anywhere in the application. Add a listener in initState and remove it in dispose.
EventFires whenPayload
ccConversationDeletedA conversation is deleted from the listConversation
When to use: sync external UI with conversation state changes. For example, update an unread count badge in a tab bar when a conversation is deleted.
import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';

class _YourScreenState extends State<YourScreen> with CometChatConversationEventListener {

  @override
  void initState() {
    super.initState();
    CometChatConversationEvents.addConversationListListener("listenerId", this);
  }

  @override
  void dispose() {
    CometChatConversationEvents.removeConversationListListener("listenerId");
    super.dispose();
  }

  @override
  void ccConversationDeleted(Conversation conversation) {
    print("Deleted: ${conversation.conversationId}");
  }
}

SDK Events (Real-Time, Automatic)

The component listens to these SDK events internally. No manual attachment needed unless additional side effects are required.
SDK ListenerInternal behavior
onTextMessageReceived / onMediaMessageReceived / onCustomMessageReceivedMoves conversation to top, updates last message preview and unread count
onTypingStarted / onTypingEndedShows/hides typing indicator in the subtitle
onMessagesDelivered / onMessagesReadUpdates receipt ticks (unless receiptsVisibility: false)
onUserOnline / onUserOfflineUpdates online/offline status dot (unless usersStatusVisibility: false)
onGroupMemberJoined / onGroupMemberLeft / onGroupMemberKicked / onGroupMemberBanned / onMemberAddedToGroupUpdates group conversation metadata
Automatic: new messages, typing indicators, receipts, user presence, group membership changes.

Custom View Slots

Each slot replaces a section of the default UI. Slots that accept a conversation parameter receive the Conversation object for that row.
SlotSignatureReplaces
listItemViewWidget Function(Conversation)Entire list item row
leadingViewWidget? Function(BuildContext, Conversation)Avatar / left section
titleViewWidget? Function(BuildContext, Conversation)Name / title text
subtitleViewWidget? Function(BuildContext, Conversation)Last message preview
trailingViewWidget? Function(Conversation)Timestamp / badge / right section
loadingStateViewWidgetBuilderLoading spinner
emptyStateViewWidgetBuilderEmpty state
errorStateViewWidgetBuilderError state
setOptionsList<CometChatOption>? Function(Conversation, Controller, BuildContext)Context menu actions (replaces default)
addOptionsList<CometChatOption>? Function(Conversation, Controller, BuildContext)Context menu actions (adds to default)

listItemView

Replace the entire list item row.
CometChatConversations(
  listItemView: (conversation) {
    final entity = conversation.conversationWith;
    final name = entity is User ? entity.name : (entity as Group).name;
    
    return CometChatListItem(
      avatarName: name,
      avatarURL: entity is User ? entity.avatar : (entity as Group).icon,
      title: name,
      avatarStyle: CometChatAvatarStyle(
        borderRadius: BorderRadius.circular(8),
      ),
    );
  },
)
For a more complete custom list item with status indicator and date:
Widget getCustomListItem(Conversation conversation, BuildContext context) {
  User? conversationWithUser;
  Group? conversationWithGroup;
  
  if (conversation.conversationWith is User) {
    conversationWithUser = conversation.conversationWith as User;
  } else {
    conversationWithGroup = conversation.conversationWith as Group;
  }

  // Get status indicator
  StatusIndicatorUtils statusIndicatorUtils = StatusIndicatorUtils.getStatusIndicatorFromParams(
    context: context,
    user: conversationWithUser,
    group: conversationWithGroup,
    onlineStatusIndicatorColor: Color(0xFF09C26F),
  );

  // Build tail view with date
  final lastMessageTime = conversation.lastMessage?.sentAt ?? DateTime.now();
  Widget tail = CometChatDate(
    date: lastMessageTime,
    padding: EdgeInsets.zero,
    style: CometChatDateStyle(
      backgroundColor: Colors.transparent,
      textStyle: TextStyle(color: Color(0xFF727272), fontSize: 12),
      border: Border.all(width: 0, color: Colors.transparent),
    ),
    pattern: DateTimePattern.dayDateTimeFormat,
  );

  return CometChatListItem(
    avatarHeight: 48,
    avatarWidth: 48,
    id: conversation.conversationId,
    avatarName: conversationWithUser?.name ?? conversationWithGroup?.name,
    avatarURL: conversationWithUser?.avatar ?? conversationWithGroup?.icon,
    avatarStyle: CometChatAvatarStyle(
      borderRadius: BorderRadius.circular(8),
      backgroundColor: Color(0xFFAA9EE8),
    ),
    title: conversationWithUser?.name ?? conversationWithGroup?.name,
    tailView: tail,
    statusIndicatorColor: statusIndicatorUtils.statusIndicatorColor,
    statusIndicatorIcon: statusIndicatorUtils.icon,
    statusIndicatorStyle: CometChatStatusIndicatorStyle(
      border: Border.all(width: 2, color: Colors.white),
    ),
    hideSeparator: true,
    style: ListItemStyle(
      background: Colors.transparent,
      titleStyle: TextStyle(
        overflow: TextOverflow.ellipsis,
        fontSize: 16,
        fontWeight: FontWeight.w500,
        color: Color(0xFF141414),
      ),
      padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
    ),
  );
}

// Usage:
CometChatConversations(
  listItemView: (conversation) => getCustomListItem(conversation, context),
)

leadingView

Replace the avatar / left section. Typing-aware avatar example.
// In your StatefulWidget, use the MessageListener mixin:
class _ConversationsScreenState extends State<ConversationsScreen> with MessageListener {
  Map<String, TypingIndicator> typingMap = {};

  @override
  void initState() {
    super.initState();
    CometChat.addMessageListener("typing_listener", this);
  }

  @override
  void dispose() {
    CometChat.removeMessageListener("typing_listener");
    super.dispose();
  }

  @override
  void onTypingStarted(TypingIndicator typingIndicator) {
    setTypingIndicator(typingIndicator, true);
  }

  @override
  void onTypingEnded(TypingIndicator typingIndicator) {
    setTypingIndicator(typingIndicator, false);
  }

  void setTypingIndicator(TypingIndicator typingIndicator, bool isTypingStarted) {
    final id = typingIndicator.receiverType == ReceiverTypeConstants.user
        ? typingIndicator.sender.uid
        : typingIndicator.receiverId;
    
    setState(() {
      if (isTypingStarted) {
        typingMap[id] = typingIndicator;
      } else {
        typingMap.remove(id);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return CometChatConversations(
      leadingView: (context, conversation) {
        final entity = conversation.conversationWith;
        final id = entity is User ? entity.uid : (entity as Group).guid;
        
        if (typingMap.containsKey(id)) {
          return Container(
            decoration: BoxDecoration(
              border: Border.all(color: Color(0xFFF76808), width: 2),
              borderRadius: BorderRadius.circular(8),
            ),
            child: Image.asset("assets/typing_icon.png", height: 40, width: 40),
          );
        }
        return null; // Use default avatar
      },
    );
  }
}

titleView

Replace the name / title text. Inline user status example.
CometChatConversations(
  titleView: (context, conversation) {
    final entity = conversation.conversationWith;
    final name = entity is User ? entity.name : (entity as Group).name;
    final statusMessage = entity is User ? entity.statusMessage : null;
    
    return Row(
      children: [
        Text(name ?? "", style: TextStyle(fontWeight: FontWeight.w500)),
        if (statusMessage != null)
          Text(" · $statusMessage", style: TextStyle(color: Color(0xFF6852D6))),
      ],
    );
  },
)

subtitleView

Replace the last message preview text.
CometChatConversations(
  subtitleView: (context, conversation) {
    final entity = conversation.conversationWith;
    String subtitle;
    
    if (entity is User) {
      final dateTime = entity.lastActiveAt ?? DateTime.now();
      subtitle = "Last Active: ${DateFormat('dd/MM/yyyy, HH:mm').format(dateTime)}";
    } else {
      final dateTime = (entity as Group).createdAt ?? DateTime.now();
      subtitle = "Created: ${DateFormat('dd/MM/yyyy, HH:mm').format(dateTime)}";
    }
    
    return Text(subtitle, style: TextStyle(color: Color(0xFF727272), fontSize: 14));
  },
)

trailingView

Replace the timestamp / badge / right section. Relative time badge example.
CometChatConversations(
  trailingView: (conversation) {
    final timestamp = conversation.updatedAt?.millisecondsSinceEpoch ?? 0;
    final now = DateTime.now();
    final lastSeen = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
    final diffInMinutes = now.difference(lastSeen).inMinutes;
    final diffInHours = now.difference(lastSeen).inHours;

    String timeText;
    String label;
    Color cardColor;

    if (diffInMinutes < 60) {
      timeText = "$diffInMinutes";
      label = "Min ago";
      cardColor = Color(0x666852D6);
    } else if (diffInHours < 10) {
      timeText = "$diffInHours";
      label = "Hr ago";
      cardColor = Color(0x66FFAB00);
    } else {
      timeText = "$diffInHours";
      label = "Hr ago";
      cardColor = Color(0x66F44649);
    }

    return Card(
      color: cardColor,
      child: Padding(
        padding: EdgeInsets.all(4),
        child: Column(
          children: [
            Text(timeText, style: TextStyle(fontWeight: FontWeight.bold)),
            Text(label, style: TextStyle(fontSize: 12)),
          ],
        ),
      ),
    );
  },
)

setOptions

Replace the context menu / long-press actions on each conversation item.
CometChatConversations(
  setOptions: (conversation, controller, context) {
    return [
      CometChatOption(
        id: "delete",
        title: "Delete",
        icon: AssetConstants.delete,
        onClick: () {
          // Delete conversation
        },
      ),
    ];
  },
)

addOptions

Add to the existing context menu actions without removing defaults.
CometChatConversations(
  addOptions: (conversation, controller, context) {
    return [
      CometChatOption(
        id: "archive",
        title: "Archive",
        iconWidget: Icon(Icons.archive_outlined),
        onClick: () {
          // Archive conversation
        },
      ),
      CometChatOption(
        id: "pin",
        title: "Pin",
        iconWidget: Icon(Icons.push_pin_outlined),
        onClick: () {
          // Pin conversation
        },
      ),
      CometChatOption(
        id: "mark_unread",
        title: "Mark as unread",
        iconWidget: Icon(Icons.mark_chat_unread_outlined),
        onClick: () {
          // Mark conversation as unread
        },
      ),
    ];
  },
)

appBarOptions

Add custom widgets to the app bar.
CometChatConversations(
  showBackButton: false,
  appBarOptions: [
    PopupMenuButton(
      icon: CometChatAvatar(
        image: CometChatUIKit.loggedInUser?.avatar,
        name: CometChatUIKit.loggedInUser?.name,
      ),
      itemBuilder: (context) => [
        PopupMenuItem(value: 'create', child: Text("Create Conversation")),
        PopupMenuItem(value: 'logout', child: Text("Logout")),
      ],
      onSelected: (value) {
        // Handle menu selection
      },
    ),
  ],
)
For a more complete popup menu with styling:
CometChatConversations(
  showBackButton: false,
  appBarOptions: [
    PopupMenuButton(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(8),
        side: BorderSide(color: Color(0xFFF5F5F5), width: 1),
      ),
      color: Colors.white,
      elevation: 4,
      menuPadding: EdgeInsets.zero,
      padding: EdgeInsets.zero,
      icon: Padding(
        padding: EdgeInsets.only(left: 12, right: 16),
        child: CometChatAvatar(
          width: 40,
          height: 40,
          image: CometChatUIKit.loggedInUser?.avatar,
          name: CometChatUIKit.loggedInUser?.name,
        ),
      ),
      onSelected: (value) {
        switch (value) {
          case '/create':
            // Navigate to create conversation
            break;
          case '/logout':
            CometChatUIKit.logout();
            break;
        }
      },
      position: PopupMenuPosition.under,
      itemBuilder: (BuildContext context) {
        return [
          PopupMenuItem(
            height: 44,
            padding: EdgeInsets.all(16),
            value: '/create',
            child: Row(
              children: [
                Padding(
                  padding: EdgeInsets.only(right: 8),
                  child: Icon(Icons.add_comment_outlined, color: Color(0xFFA1A1A1), size: 24),
                ),
                Text("Create Conversation", style: TextStyle(fontSize: 14, color: Color(0xFF141414))),
              ],
            ),
          ),
          PopupMenuItem(
            height: 44,
            padding: EdgeInsets.all(16),
            value: '/name',
            child: Row(
              children: [
                Padding(
                  padding: EdgeInsets.only(right: 8),
                  child: Icon(Icons.account_circle_outlined, color: Color(0xFFA1A1A1), size: 24),
                ),
                Text(CometChatUIKit.loggedInUser?.name ?? "", style: TextStyle(fontSize: 14, color: Color(0xFF141414))),
              ],
            ),
          ),
          PopupMenuItem(
            height: 44,
            padding: EdgeInsets.all(16),
            value: '/logout',
            child: Row(
              children: [
                Padding(
                  padding: EdgeInsets.only(right: 8),
                  child: Icon(Icons.logout, color: Colors.red, size: 24),
                ),
                Text("Logout", style: TextStyle(fontSize: 14, color: Colors.red)),
              ],
            ),
          ),
        ];
      },
    ),
  ],
  onItemTap: (conversation) {
    User? user;
    Group? group;
    if (conversation.conversationWith is User) {
      user = conversation.conversationWith as User;
    } else {
      group = conversation.conversationWith as Group;
    }
    // Navigate to messages
  },
)

Styling

Set CometChatConversationsStyle to customize the appearance.
CometChatConversations(
  conversationsStyle: CometChatConversationsStyle(
    backgroundColor: Colors.white,
    titleTextColor: Color(0xFF141414),
    avatarStyle: CometChatAvatarStyle(
      borderRadius: BorderRadius.circular(8),
      backgroundColor: Color(0xFFFBAA75),
    ),
    badgeStyle: CometChatBadgeStyle(
      backgroundColor: Color(0xFFF76808),
    ),
  ),
)

Style Properties

PropertyTypeDescription
backgroundColorColorBackground color of the component
borderBorderBorder for the widget
borderRadiusBorderRadiusGeometryBorder radius for the widget
titleTextColorColorColor of the header title
titleTextStyleTextStyleStyle for the header title
backIconColorColorBack button icon color
searchBackgroundColorColorBackground color of search box
searchBorderBorderSideBorder for search box
searchBorderRadiusBorderRadiusBorder radius for search box
searchPlaceHolderTextColorColorPlaceholder text color in search
searchPlaceHolderTextStyleTextStylePlaceholder text style in search
searchIconColorColorSearch icon color
separatorColorColorColor of list item separators
separatorHeightdoubleHeight of list item separators
emptyStateTextColorColorText color for empty state title
emptyStateTextStyleTextStyleText style for empty state title
emptyStateSubTitleTextColorColorText color for empty state subtitle
emptyStateSubTitleTextStyleTextStyleText style for empty state subtitle
errorStateTextColorColorText color for error state title
errorStateTextStyleTextStyleText style for error state title
errorStateSubTitleTextColorColorText color for error state subtitle
errorStateSubTitleTextStyleTextStyleText style for error state subtitle
itemTitleTextColorColorText color for conversation item title
itemTitleTextStyleTextStyleText style for conversation item title
itemSubtitleTextColorColorText color for conversation item subtitle
itemSubtitleTextStyleTextStyleText style for conversation item subtitle
messageTypeIconColorColorIcon color for message type indicators
avatarStyleCometChatAvatarStyleStyle for avatars
badgeStyleCometChatBadgeStyleStyle for unread badges
receiptStyleCometChatMessageReceiptStyleStyle for message receipts
statusIndicatorStyleCometChatStatusIndicatorStyleStyle for online status indicator
dateStyleCometChatDateStyleStyle for date/time display
typingIndicatorStyleCometChatTypingIndicatorStyleStyle for typing indicator
mentionsStyleCometChatMentionsStyleStyle for @mentions
deleteConversationDialogStyleCometChatConfirmDialogStyleStyle for delete confirmation dialog
privateGroupIconBackgroundColorBackground color for private group icon
protectedGroupIconBackgroundColorBackground color for protected group icon
submitIconColorColorColor for submit icon in selection mode
checkBoxBackgroundColorColorBackground color for selection checkbox
checkBoxCheckedBackgroundColorColorBackground color when checkbox is checked
checkBoxBorderBorderSideBorder for selection checkbox
checkBoxBorderRadiusBorderRadiusGeometryBorder radius for selection checkbox
checkboxSelectedIconColorColorIcon color when checkbox is selected
listItemSelectedBackgroundColorColorBackground color for selected list items

Common Patterns

Custom empty state with CTA

CometChatConversations(
  emptyStateView: (context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text("No conversations yet"),
          SizedBox(height: 16),
          ElevatedButton(
            onPressed: () {
              // Navigate to contacts
            },
            child: Text("Start a conversation"),
          ),
        ],
      ),
    );
  },
)

Hide all chrome — minimal list

CometChatConversations(
  receiptsVisibility: false,
  usersStatusVisibility: false,
  groupTypeVisibility: false,
  deleteConversationOptionVisibility: false,
  hideAppbar: true,
)
CometChatConversations(
  hideSearch: false,
  onSearchTap: () {
    // Handle search tap - navigate to search screen
  },
)

Custom date pattern

CometChatConversations(
  datePattern: (conversation) {
    final date = conversation.lastMessage?.sentAt ?? DateTime.now();
    return DateFormat('d MMM, hh:mm a').format(date);
  },
)

Text formatters

Configure text formatters for the conversation subtitle. See CometChatMentionsFormatter for mention formatting.
CometChatConversations(
  textFormatters: [
    CometChatMentionsFormatter(
      style: CometChatMentionsStyle(
        mentionSelfTextBackgroundColor: Color(0xFFF76808),
        mentionTextBackgroundColor: Colors.white,
        mentionTextColor: Colors.black,
        mentionSelfTextColor: Colors.white,
      ),
    ),
  ],
)

Accessibility

The component renders a scrollable list of interactive items. Each conversation row is tappable and responds to both tap and long-press gestures. The context menu (options) is accessible via long-press. The unread badge count is exposed as text content. Avatar images include the conversation name for accessibility. For screen readers, the conversation list is rendered as a semantic list using Flutter’s built-in accessibility features. Status indicators (online/offline, group type icons) use visual icons — consider providing custom Semantics widgets via leadingView if screen reader descriptions are needed for these visual indicators. When using selection mode, checkboxes are rendered with proper accessibility labels. The component respects system accessibility settings including text scaling and high contrast modes.

Props

All props are optional. Sorted alphabetically.

activateSelection

Controls when selection mode activates.
TypeActivateSelection
Defaultnull
Values: ActivateSelection.onClick, ActivateSelection.onLongClick

addOptions

Adds to the current list of actions available on long press.
TypeList<CometChatOption>? Function(Conversation, CometChatConversationsController, BuildContext)
Defaultnull

appBarOptions

List of widgets to display in the app bar.
TypeList<Widget>
Defaultnull

backButton

Custom back button widget.
TypeWidget
DefaultBuilt-in back arrow

conversationsRequestBuilder

Controls which conversations load and in what order.
TypeConversationsRequestBuilder
DefaultSDK default (30 per page)
Pass the builder instance, not the result of .build().

conversationsProtocol

Custom protocol for fetching conversations.
TypeConversationsBuilderProtocol
Defaultnull
Use this for advanced customization of how conversations are fetched.

conversationsStyle

Style configuration for the component.
TypeCometChatConversationsStyle
DefaultCometChatConversationsStyle()

customSoundForMessages

Path to a custom audio file for incoming message notifications.
TypeString
DefaultBuilt-in sound

datePattern

Custom date format function for conversation timestamps.
TypeString Function(Conversation)
DefaultBuilt-in date formatting

deleteConversationOptionVisibility

Controls visibility of delete option in context menu.
Typebool
Defaulttrue

deliveredIcon

Custom icon for delivered message receipts.
TypeWidget
DefaultBuilt-in delivered icon

disableSoundForMessages

Disables notification sound for incoming messages.
Typebool
Defaultfalse

emptyStateView

Custom widget displayed when there are no conversations.
TypeWidgetBuilder
DefaultBuilt-in empty state

errorStateView

Custom widget displayed when an error occurs.
TypeWidgetBuilder
DefaultBuilt-in error state
Hidden when hideError: true.

groupTypeVisibility

Controls visibility of group type icon (public/private/password).
Typebool
Defaulttrue

hideAppbar

Hides the entire app bar.
Typebool
Defaultfalse

hideError

Hides the default and custom error views.
Typebool
Defaultfalse

hideSearch

Hides the search bar in the app bar.
Typebool
Defaultfalse

leadingView

Custom renderer for the avatar / left section.
TypeWidget? Function(BuildContext, Conversation)
DefaultBuilt-in avatar
Return null to use the default avatar.

listItemView

Custom renderer for the entire list item row.
TypeWidget Function(Conversation)
DefaultBuilt-in list item

loadingStateView

Custom widget displayed during loading state.
TypeWidgetBuilder
DefaultBuilt-in shimmer

mentionAllLabel

Custom label for group mentions (@channel, @everyone).
TypeString
Defaultnull

mentionAllLabelId

Custom label ID for group mentions.
TypeString
Defaultnull

onBack

Callback fired when the back button is pressed.
TypeVoidCallback
Defaultnull

onEmpty

Callback fired when the conversation list is empty.
TypeOnEmpty
Defaultnull

onError

Callback fired when the component encounters an error.
TypeOnError
Defaultnull

onItemLongPress

Callback fired when a conversation row is long-pressed.
TypeFunction(Conversation)
Defaultnull

onItemTap

Callback fired when a conversation row is tapped.
TypeFunction(Conversation)
Defaultnull

onLoad

Callback fired when the conversation list is loaded.
TypeOnLoad<Conversation>
Defaultnull

onSearchTap

Callback fired when the search box is tapped.
TypeGestureTapCallback
Defaultnull
Requires searchReadOnly: true to work properly.

onSelection

Callback fired when conversations are selected/deselected.
TypeFunction(List<Conversation>?)
Defaultnull
Requires selectionMode to be set.

privateGroupIcon

Custom icon for private group indicator.
TypeWidget
DefaultBuilt-in lock icon

protectedGroupIcon

Custom icon for password-protected group indicator.
TypeWidget
DefaultBuilt-in lock icon

readIcon

Custom icon for read message receipts.
TypeWidget
DefaultBuilt-in read icon

receiptsVisibility

Controls visibility of message read/delivery receipts.
Typebool
Defaulttrue

scrollController

Custom scroll controller for the list.
TypeScrollController
Defaultnull

searchBoxIcon

Custom prefix icon for the search box.
TypeWidget
DefaultBuilt-in search icon

searchContentPadding

Padding for search box content.
TypeEdgeInsetsGeometry
Defaultnull

searchPadding

Padding for the search box.
TypeEdgeInsetsGeometry
Defaultnull

searchReadOnly

Makes the search box read-only (tap only).
Typebool
Defaultfalse

selectionMode

Enables single or multi-select mode.
TypeSelectionMode
Defaultnull
Values: SelectionMode.single, SelectionMode.multiple, SelectionMode.none Must pair with onSelection to capture selections.

sentIcon

Custom icon for sent message receipts.
TypeWidget
DefaultBuilt-in sent icon

setOptions

Replaces the list of actions available on long press.
TypeList<CometChatOption>? Function(Conversation, CometChatConversationsController, BuildContext)
Defaultnull

showBackButton

Shows the back button in the app bar.
Typebool
Defaultfalse

subtitleView

Custom renderer for the last message preview.
TypeWidget? Function(BuildContext, Conversation)
DefaultBuilt-in subtitle

textFormatters

Custom text formatters for the conversation subtitle.
TypeList<CometChatTextFormatter>
DefaultDefault formatters from data source
See CometChatMentionsFormatter for mention formatting.

title

Custom title text for the app bar.
TypeString
Default”Chats”

titleView

Custom renderer for the name / title text.
TypeWidget? Function(BuildContext, Conversation)
DefaultBuilt-in title

trailingView

Custom renderer for the timestamp / badge / right section.
TypeWidget? Function(Conversation)
DefaultBuilt-in trailing view

typingIndicatorText

Custom text shown when a user is typing.
TypeString
Default”typing…“

usersStatusVisibility

Controls visibility of online/offline status indicator.
Typebool
Defaulttrue

avatarHeight

Height for user/group avatars.
Typedouble
Defaultnull

avatarWidth

Width for user/group avatars.
Typedouble
Defaultnull

avatarPadding

Padding for user/group avatars.
TypeEdgeInsetsGeometry
Defaultnull

avatarMargin

Margin for user/group avatars.
TypeEdgeInsetsGeometry
Defaultnull

badgeWidth

Width for unread message badge.
Typedouble
Defaultnull

badgeHeight

Height for unread message badge.
Typedouble
Defaultnull

badgePadding

Padding for unread message badge.
TypeEdgeInsetsGeometry
Defaultnull

controllerTag

Tag for controller management. When passed, parent is responsible for closing.
TypeString
Defaultnull

dateBackgroundIsTransparent

Controls whether the date background is transparent.
Typebool
Defaultnull

dateHeight

Height for the conversation date display.
Typedouble
Defaultnull

datePadding

Padding for the conversation date display.
TypeEdgeInsets
Defaultnull

dateTimeFormatterCallback

Callback for custom date and time formatting.
TypeDateTimeFormatterCallback
Defaultnull

dateWidth

Width for the conversation date display.
Typedouble
Defaultnull

listItemStyle

Style configuration for list items.
TypeListItemStyle
Defaultnull

searchContentPadding

Padding for search box content.
TypeEdgeInsetsGeometry
Defaultnull

searchPadding

Padding for the search box.
TypeEdgeInsetsGeometry
Defaultnull

statusIndicatorBorderRadius

Border radius for the status indicator.
TypeBorderRadiusGeometry
Defaultnull

statusIndicatorHeight

Height for the status indicator.
Typedouble
Defaultnull

statusIndicatorWidth

Width for the status indicator.
Typedouble
Defaultnull

submitIcon

Custom submit icon for selection mode.
TypeWidget
DefaultBuilt-in check icon

Events

EventPayloadFires when
CometChatConversationEvents.ccConversationDeletedConversationConversation deleted from list
CometChatConversationEvents.ccUpdateConversationConversationConversation updated (last message change, metadata update)
Subscribe using CometChatConversationEvents.addConversationListListener() and unsubscribe with removeConversationListListener().

Customization Matrix

What to changeWhereProperty/APIExample
Override behavior on user interactionWidget propson<Event> callbacksonItemTap: (c) => setActive(c)
Filter which conversations appearWidget propsconversationsRequestBuilderconversationsRequestBuilder: ConversationsRequestBuilder()..limit = 10
Toggle visibility of UI elementsWidget props<feature>Visibility boolean propsreceiptsVisibility: false
Replace a section of the list itemWidget props<slot>View render propslistItemView: (conversation) => CustomWidget()
Change colors, fonts, spacingWidget propsconversationsStyleconversationsStyle: CometChatConversationsStyle(backgroundColor: Colors.white)