> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-docs-llms-scoped-indexes.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Message Header

> Configure CometChat iOS UI Kit Message Header with user or group details, avatar, status, typing indicators, navigation, and call buttons.

The `CometChatMessageHeader` component displays user or group details in the toolbar including avatar, name, status, and typing indicators. It also provides navigation controls and call buttons.

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-llms-scoped-indexes/jz7GpUbUydkL66-q/images/cdbdc9b3-message-header-cd5bd3b233f9e340571a62cc0e32f3f5.png?fit=max&auto=format&n=jz7GpUbUydkL66-q&q=85&s=84d5731b1bfcf9066834d47fde86e720" alt="CometChatMessageHeader showing user avatar, name, online status, and call buttons in the navigation bar" width="1280" height="240" data-path="images/cdbdc9b3-message-header-cd5bd3b233f9e340571a62cc0e32f3f5.png" />
</Frame>

<Accordion title="AI Integration Quick Reference">
  ```json theme={null}
  {
    "component": "CometChatMessageHeader",
    "package": "CometChatUIKitSwift",
    "import": "import CometChatUIKitSwift\nimport CometChatSDK",
    "description": "Displays user or group details in the toolbar with avatar, name, status, typing indicators, and navigation controls.",
    "inherits": "UIView",
    "primaryOutput": {
      "callback": "onBack",
      "type": "() -> Void"
    },
    "props": {
      "data": {
        "user": {
          "type": "User?",
          "default": "nil",
          "note": "User to display in header"
        },
        "group": {
          "type": "Group?",
          "default": "nil",
          "note": "Group to display in header"
        }
      },
      "callbacks": {
        "onBack": "() -> Void",
        "onError": "(CometChatException) -> Void",
        "onAiChatHistoryClicked": "(User) -> Void  (assignable property)",
        "onAiNewChatClicked": "(User) -> Void  (assignable property)"
      },
      "visibility": {
        "hideBackButton": { "type": "Bool", "default": false },
        "hideUserStatus": { "type": "Bool", "default": false },
        "hideVideoCallButton": { "type": "Bool", "default": false },
        "hideVoiceCallButton": { "type": "Bool", "default": false },
        "hideNewChatButton": { "type": "Bool", "default": false },
        "hideChatHistoryButton": { "type": "Bool", "default": false },
        "hideThreadSubscriptionButton": { "type": "Bool", "default": false },
        "disableTyping": { "type": "Bool", "default": false }
      },
      "threads": {
        "parentMessage": { "type": "BaseMessage?", "default": "nil", "note": "Set to put the header in thread mode" },
        "enableThreadSubscription": { "type": "Bool", "default": false, "note": "Also requires parentMessage" }
      },
      "style": {
        "avatarStyle": { "type": "AvatarStyle", "default": "AvatarStyle()" },
        "statusIndicatorStyle": { "type": "StatusIndicatorStyle", "default": "StatusIndicatorStyle()" },
        "typingIndicatorStyle": { "type": "TypingIndicatorStyle", "default": "TypingIndicatorStyle()" }
      },
      "formatting": {
        "dateTimeFormatter": { "type": "CometChatDateTimeFormatter?", "default": "nil" }
      },
      "viewSlots": {
        "listItemView": "(User?, Group?) -> UIView",
        "leadingView": "(User?, Group?) -> UIView",
        "titleView": "(User?, Group?) -> UIView",
        "subtitleView": "(User?, Group?) -> UIView",
        "trailView": "(User?, Group?) -> UIView"
      }
    },
    "methods": {
      "connection": {
        "connect()": "Establishes WebSocket connection for real-time updates",
        "disconnect()": "Disconnects WebSocket connection"
      },
      "menuCustomization": {
        "set(options:)": "[CometChatPopupMenu.MenuItem]? - Sets custom menu options"
      }
    },
    "events": [],
    "sdkListeners": [
      "onUserOnline",
      "onUserOffline",
      "onTypingStarted",
      "onTypingEnded"
    ],
    "compositionExample": {
      "description": "MessageHeader is typically used at the top of your own chat screen",
      "components": ["CometChatMessageHeader", "CometChatMessageList", "CometChatMessageComposer"],
      "flow": "User views header → sees recipient info → taps back to return to conversations"
    },
    "types": {}
  }
  ```
</Accordion>

| Field | Value |
| - | - |
| Component | `CometChatMessageHeader` |
| Package | `CometChatUIKitSwift` |
| Inherits | `UIView` |

***

## Where It Fits

`CometChatMessageHeader` displays the recipient's information at the top of the chat screen. It's typically used in your own chat screen alongside `CometChatMessageList` and `CometChatMessageComposer`.

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class ChatViewController: UIViewController {
    
    private var messageHeader: CometChatMessageHeader!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupMessageHeader()
    }
    
    private func setupMessageHeader(for user: User) {
        messageHeader = CometChatMessageHeader()
        messageHeader.set(user: user)
        
        // Handle back button
        messageHeader.set(onBack: { [weak self] in
            self?.navigationController?.popViewController(animated: true)
        })
        
        view.addSubview(messageHeader)
    }
}
```

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-llms-scoped-indexes/jz7GpUbUydkL66-q/images/cdbdc9b3-message-header-cd5bd3b233f9e340571a62cc0e32f3f5.png?fit=max&auto=format&n=jz7GpUbUydkL66-q&q=85&s=84d5731b1bfcf9066834d47fde86e720" alt="CometChatMessageHeader showing user avatar, name, online status, and call buttons in the navigation bar" width="1280" height="240" data-path="images/cdbdc9b3-message-header-cd5bd3b233f9e340571a62cc0e32f3f5.png" />
</Frame>

***

## Minimal Render

```swift lines theme={null}
import CometChatUIKitSwift
import CometChatSDK

let messageHeader = CometChatMessageHeader()
messageHeader.set(user: user)
```

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-llms-scoped-indexes/jz7GpUbUydkL66-q/images/cdbdc9b3-message-header-cd5bd3b233f9e340571a62cc0e32f3f5.png?fit=max&auto=format&n=jz7GpUbUydkL66-q&q=85&s=84d5731b1bfcf9066834d47fde86e720" alt="CometChatMessageHeader showing minimal render with user details and default styling" width="1280" height="240" data-path="images/cdbdc9b3-message-header-cd5bd3b233f9e340571a62cc0e32f3f5.png" />
</Frame>

***

## Actions and Events

### Callback Props

#### onBack

Fires when the back button is pressed. Use this for custom navigation handling.

```swift lines theme={null}
import CometChatUIKitSwift

let messageHeader = CometChatMessageHeader()

messageHeader.set(onBack: { [weak self] in
    self?.navigationController?.popViewController(animated: true)
})
```

#### onError

Fires when an error occurs.

```swift lines theme={null}
import CometChatUIKitSwift

let messageHeader = CometChatMessageHeader()

messageHeader.set(onError: { error in
    print("Error: \(error.errorDescription)")
})
```

### Actions Reference

| Method | Description | Example |
| - | - | - |
| `set(onBack:)` | Triggered when back button is pressed | Custom navigation |
| `set(onError:)` | Triggered when an error occurs | Show error alert |
| `set(user:)` | Sets the user to display | Configure header for user |
| `set(group:)` | Sets the group to display | Configure header for group |

### SDK Events (Real-Time, Automatic)

| SDK Listener | Internal behavior |
| - | - |
| `onUserOnline` | Updates status indicator to online |
| `onUserOffline` | Updates status indicator to offline |
| `onTypingStarted` | Shows typing indicator in subtitle |
| `onTypingEnded` | Hides typing indicator |

***

## Custom View Slots

| Slot | Signature | Replaces |
| - | - | - |
| `listItemView` | `(User?, Group?) -> UIView` | Entire header content |
| `leadingView` | `(User?, Group?) -> UIView` | Avatar / left section |
| `titleView` | `(User?, Group?) -> UIView` | Name / title text |
| `subtitleView` | `(User?, Group?) -> UIView` | Status / subtitle text |
| `trailView` | `(User?, Group?) -> UIView` | Right side (call buttons) |

### listItemView

Replace the entire header content with a custom view.

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift
import CometChatSDK

let messageHeader = CometChatMessageHeader()

messageHeader.set(listItemView: { user, group in
    let customView = CustomHeaderView()
    customView.configure(user: user, group: group)
    return customView
})
```

You can create a `CustomHeaderView` as a custom `UIView`:

```swift lines theme={null}
import UIKit
import CometChatSDK

class CustomHeaderView: UIView {
    
    private let backButton: UIButton = {
        let button = UIButton(type: .system)
        button.setImage(UIImage(systemName: "chevron.left"), for: .normal)
        button.tintColor = .black
        return button
    }()
    
    private let profileImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFill
        imageView.layer.cornerRadius = 18
        imageView.clipsToBounds = true
        imageView.backgroundColor = .lightGray
        return imageView
    }()
    
    private let nameLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: 16, weight: .semibold)
        label.textColor = .black
        return label
    }()
    
    private let statusLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: 12)
        label.textColor = .gray
        return label
    }()
    
    private let videoCallButton: UIButton = {
        let button = UIButton(type: .system)
        button.setImage(UIImage(systemName: "video.fill"), for: .normal)
        button.tintColor = .black
        return button
    }()
    
    private let callButton: UIButton = {
        let button = UIButton(type: .system)
        button.setImage(UIImage(systemName: "phone.fill"), for: .normal)
        button.tintColor = .black
        return button
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func setupView() {
        backgroundColor = .white

        let userInfoStack = UIStackView(arrangedSubviews: [nameLabel, statusLabel])
        userInfoStack.axis = .vertical
        userInfoStack.spacing = 2
        userInfoStack.alignment = .leading

        let rightButtonsStack = UIStackView(arrangedSubviews: [videoCallButton, callButton])
        rightButtonsStack.axis = .horizontal
        rightButtonsStack.spacing = 16

        addSubview(backButton)
        addSubview(profileImageView)
        addSubview(userInfoStack)
        addSubview(rightButtonsStack)

        backButton.translatesAutoresizingMaskIntoConstraints = false
        profileImageView.translatesAutoresizingMaskIntoConstraints = false
        userInfoStack.translatesAutoresizingMaskIntoConstraints = false
        rightButtonsStack.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            backButton.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
            backButton.centerYAnchor.constraint(equalTo: centerYAnchor),
            backButton.widthAnchor.constraint(equalToConstant: 30),
            backButton.heightAnchor.constraint(equalToConstant: 30),

            profileImageView.leadingAnchor.constraint(equalTo: backButton.trailingAnchor, constant: 10),
            profileImageView.centerYAnchor.constraint(equalTo: centerYAnchor),
            profileImageView.widthAnchor.constraint(equalToConstant: 36),
            profileImageView.heightAnchor.constraint(equalToConstant: 36),

            userInfoStack.leadingAnchor.constraint(equalTo: profileImageView.trailingAnchor, constant: 10),
            userInfoStack.centerYAnchor.constraint(equalTo: centerYAnchor),

            rightButtonsStack.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
            rightButtonsStack.centerYAnchor.constraint(equalTo: centerYAnchor)
        ])
    }
    
    func configure(user: User?, group: Group?) {
        nameLabel.text = user?.name ?? group?.name ?? "Chat"
        if let user = user {
            statusLabel.text = user.status == .online ? "Online" : "Offline"
        } else if let group = group {
            statusLabel.text = "\(group.membersCount) members"
        }
    }
}
```

### leadingView

Customize the leading view (avatar area) of the header.

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift
import CometChatSDK

let messageHeader = CometChatMessageHeader()

messageHeader.set(leadingView: { user, group in
    let view = CustomLeadingView()
    return view
})
```

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-llms-scoped-indexes/KBUX2d7UNeNDowv9/images/e6fad16f-headerLeadng-6f55e63eb8a291dfe2a06771801f2337.png?fit=max&auto=format&n=KBUX2d7UNeNDowv9&q=85&s=bb43b95dd21d3b243811fee312b543b8" alt="CometChatMessageHeader with custom leadingView showing avatar with Admin badge overlay" width="1280" height="240" data-path="images/e6fad16f-headerLeadng-6f55e63eb8a291dfe2a06771801f2337.png" />
</Frame>

You can create a `CustomLeadingView` as a custom `UIView`:

```swift lines theme={null}
import UIKit

class CustomLeadingView: UIView {

    private let profileImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFill
        imageView.layer.cornerRadius = 20
        imageView.clipsToBounds = true
        imageView.backgroundColor = .lightGray
        imageView.image = UIImage(systemName: "person.fill")
        return imageView
    }()

    private let badgeLabel: UILabel = {
        let label = UILabel()
        label.text = "Admin"
        label.font = UIFont.systemFont(ofSize: 10, weight: .bold)
        label.textColor = .white
        label.backgroundColor = .orange
        label.textAlignment = .center
        label.layer.cornerRadius = 6
        label.clipsToBounds = true
        return label
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func setupView() {
        addSubview(profileImageView)
        addSubview(badgeLabel)

        profileImageView.translatesAutoresizingMaskIntoConstraints = false
        badgeLabel.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            profileImageView.leadingAnchor.constraint(equalTo: leadingAnchor),
            profileImageView.trailingAnchor.constraint(equalTo: trailingAnchor),
            profileImageView.topAnchor.constraint(equalTo: topAnchor),
            profileImageView.bottomAnchor.constraint(equalTo: bottomAnchor),
            profileImageView.heightAnchor.constraint(equalToConstant: 40),
            profileImageView.widthAnchor.constraint(equalToConstant: 40),

            badgeLabel.trailingAnchor.constraint(equalTo: profileImageView.trailingAnchor),
            badgeLabel.bottomAnchor.constraint(equalTo: profileImageView.bottomAnchor),
            badgeLabel.widthAnchor.constraint(equalToConstant: 40),
            badgeLabel.heightAnchor.constraint(equalToConstant: 12)
        ])
    }
}
```

### titleView

Customize the title view of the header.

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift
import CometChatSDK

let messageHeader = CometChatMessageHeader()

messageHeader.set(titleView: { user, group in
    let view = CustomTitleView()
    return view
})
```

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-llms-scoped-indexes/yGOD4hG5x8gw_zqp/images/77d20b8c-headerTitle-20200a0eddfa0c9f2337abb9511a9671.png?fit=max&auto=format&n=yGOD4hG5x8gw_zqp&q=85&s=d373607434eb03ac34b8fc6c8308d324" alt="CometChatMessageHeader with custom titleView showing group name with Public badge" width="1280" height="240" data-path="images/77d20b8c-headerTitle-20200a0eddfa0c9f2337abb9511a9671.png" />
</Frame>

You can create a `CustomTitleView` as a custom `UIView`:

```swift lines theme={null}
import UIKit

class CustomTitleView: UIView {

    private let titleLabel: UILabel = {
        let label = UILabel()
        label.text = "Artistic Design"
        label.font = UIFont.systemFont(ofSize: 16, weight: .medium)
        label.textColor = .black
        return label
    }()

    private let publicBadge: UIView = {
        let view = UIView()
        view.backgroundColor = .blue
        view.layer.cornerRadius = 10

        let icon = UIImageView(image: UIImage(systemName: "person.3.fill"))
        icon.tintColor = .white
        icon.contentMode = .scaleAspectFit

        let label = UILabel()
        label.text = "Public"
        label.font = UIFont.systemFont(ofSize: 12, weight: .bold)
        label.textColor = .white

        let stackView = UIStackView(arrangedSubviews: [icon, label])
        stackView.spacing = 4
        stackView.alignment = .center
        stackView.translatesAutoresizingMaskIntoConstraints = false

        view.addSubview(stackView)

        NSLayoutConstraint.activate([
            stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            view.widthAnchor.constraint(equalToConstant: 60),
            view.heightAnchor.constraint(equalToConstant: 20)
        ])
        
        return view
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func setupView() {
        addSubview(titleLabel)
        addSubview(publicBadge)

        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        publicBadge.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor),
            titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor),

            publicBadge.leadingAnchor.constraint(equalTo: titleLabel.trailingAnchor, constant: 6),
            publicBadge.centerYAnchor.constraint(equalTo: centerYAnchor)
        ])
    }
}
```

### subtitleView

Customize the subtitle area (status, typing indicator).

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift
import CometChatSDK

let messageHeader = CometChatMessageHeader()

messageHeader.set(subtitleView: { user, group in
    let label = UILabel()
    label.font = UIFont.systemFont(ofSize: 13)
    label.textColor = UIColor.secondaryLabel
    
    if let user = user {
        label.text = user.status == .online ? "🟢 Online" : "⚫ Offline"
    } else if let group = group {
        label.text = "\(group.membersCount) members"
    }
    
    return label
})
```

### trailView

Customize the right side of the header (call buttons, etc.).

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift
import CometChatSDK

let messageHeader = CometChatMessageHeader()

messageHeader.set(trailView: { user, group in
    let view = CustomTrailView()
    return view
})
```

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-llms-scoped-indexes/yGOD4hG5x8gw_zqp/images/7ae625d7-headerTrail-b0c07329c262e97434036abff2c0132d.png?fit=max&auto=format&n=yGOD4hG5x8gw_zqp&q=85&s=d8b3b0542bf563cbe3c349fe3a94161a" alt="CometChatMessageHeader with custom trailView showing video call, voice call, and bookmark buttons" width="1280" height="240" data-path="images/7ae625d7-headerTrail-b0c07329c262e97434036abff2c0132d.png" />
</Frame>

You can create a `CustomTrailView` as a custom `UIView`:

```swift lines theme={null}
import UIKit

class CustomTrailView: UIView {

    private let videoCallButton: UIButton = {
        let button = UIButton(type: .system)
        let image = UIImage(systemName: "video.fill")?.withRenderingMode(.alwaysTemplate)
        button.setImage(image, for: .normal)
        button.tintColor = .black
        return button
    }()

    private let callButton: UIButton = {
        let button = UIButton(type: .system)
        let image = UIImage(systemName: "phone.fill")?.withRenderingMode(.alwaysTemplate)
        button.setImage(image, for: .normal)
        button.tintColor = .black
        return button
    }()
    
    private let bookMarkButton: UIButton = {
        let button = UIButton(type: .system)
        let image = UIImage(systemName: "bookmark.fill")?.withRenderingMode(.alwaysTemplate)
        button.setImage(image, for: .normal)
        button.tintColor = .black
        return button
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func setupView() {
        let buttonsStack = UIStackView(arrangedSubviews: [videoCallButton, callButton, bookMarkButton])
        buttonsStack.axis = .horizontal
        buttonsStack.spacing = 16
        buttonsStack.distribution = .fillEqually

        addSubview(buttonsStack)
        buttonsStack.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            buttonsStack.leadingAnchor.constraint(equalTo: leadingAnchor),
            buttonsStack.trailingAnchor.constraint(equalTo: trailingAnchor),
            buttonsStack.topAnchor.constraint(equalTo: topAnchor),
            buttonsStack.bottomAnchor.constraint(equalTo: bottomAnchor)
        ])
    }
}
```

***

## Styling

### Style Hierarchy

1. Global styles (`CometChatMessageHeader.style`) apply to all instances
2. Instance styles override global for specific instances

### Global Level Styling

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift

// Apply global styles that affect all CometChatMessageHeader instances
CometChatMessageHeader.style.backgroundColor = UIColor.systemBackground
CometChatMessageHeader.style.titleTextColor = UIColor.label
CometChatMessageHeader.style.titleTextFont = UIFont.systemFont(ofSize: 17, weight: .semibold)
CometChatMessageHeader.style.subtitleTextColor = UIColor.secondaryLabel
CometChatMessageHeader.style.subtitleTextFont = UIFont.systemFont(ofSize: 13)
CometChatMessageHeader.style.backButtonImageTintColor = UIColor.systemBlue

// Custom avatar style
let avatarStyle = AvatarStyle()
avatarStyle.cornerRadius = CometChatCornerStyle(cornerRadius: 20)
CometChatMessageHeader.style.avatarStyle = avatarStyle
```

### Instance Level Styling

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift

// Create a custom style for a specific instance
var customStyle = MessageHeaderStyle()
customStyle.backgroundColor = UIColor(red: 0.95, green: 0.95, blue: 0.97, alpha: 1.0)
customStyle.titleTextColor = UIColor.darkGray
customStyle.titleTextFont = UIFont.systemFont(ofSize: 18, weight: .bold)
customStyle.subtitleTextColor = UIColor.gray

let messageHeader = CometChatMessageHeader()
messageHeader.style = customStyle
```

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-llms-scoped-indexes/4bjA68wl0wrynpsh/images/54a6e640-message-header-style-d4203b4eece8507a4e5750d88e7fa913.png?fit=max&auto=format&n=4bjA68wl0wrynpsh&q=85&s=df8639a60bfbe22b349249249ac11ad9" alt="CometChatMessageHeader with custom instance styling showing modified background color and text appearance" width="1280" height="240" data-path="images/54a6e640-message-header-style-d4203b4eece8507a4e5750d88e7fa913.png" />
</Frame>

### Key Style Properties

| Property | Type | Default | Description |
| - | - | - | - |
| `backgroundColor` | `UIColor` | `CometChatTheme.backgroundColor01` | Background color |
| `borderWidth` | `CGFloat` | `0` | Border width |
| `borderColor` | `UIColor` | `.clear` | Border color |
| `cornerRadius` | `CometChatCornerStyle?` | `nil` | Corner radius |
| `titleTextColor` | `UIColor` | `CometChatTheme.textColorPrimary` | Title text color |
| `titleTextFont` | `UIFont` | `CometChatTypography.Heading4.medium` | Title font |
| `subtitleTextColor` | `UIColor` | `CometChatTheme.textColorSecondary` | Subtitle text color |
| `subtitleTextFont` | `UIFont` | `CometChatTypography.Body.regular` | Subtitle font |
| `backButtonImageTintColor` | `UIColor` | `CometChatTheme.iconColorPrimary` | Back button tint |
| `backButtonIcon` | `UIImage?` | System chevron | Back button icon |
| `privateGroupBadgeImageTintColor` | `UIColor` | `CometChatTheme.iconColorSecondary` | Private group badge tint |
| `passwordProtectedGroupBadgeImageTintColor` | `UIColor` | `CometChatTheme.iconColorSecondary` | Password group badge tint |
| `avatarStyle` | `AvatarStyle` | `AvatarStyle()` | Avatar customization |
| `statusIndicatorStyle` | `StatusIndicatorStyle` | `StatusIndicatorStyle()` | Online/offline status indicator customization |
| `typingIndicatorStyle` | `TypingIndicatorStyle` | `TypingIndicatorStyle()` | Typing indicator customization |

### Customization Matrix

| What to change | Where | Property/API | Example |
| - | - | - | - |
| Background color | Style | `backgroundColor` | `UIColor.systemBackground` |
| Title appearance | Style | `titleTextColor`, `titleTextFont` | Custom colors and fonts |
| Subtitle appearance | Style | `subtitleTextColor`, `subtitleTextFont` | Custom colors and fonts |
| Back button | Style | `backButtonIcon`, `backButtonImageTintColor` | Custom icon and color |
| Avatar look | Style | `avatarStyle` | `AvatarStyle()` with custom radius |
| Status indicator | Style | `statusIndicatorStyle` | `StatusIndicatorStyle()` with custom colors |
| Typing indicator | Style | `typingIndicatorStyle` | `TypingIndicatorStyle()` with custom font |
| Hide back button | Property | `hideBackButton` | `header.hideBackButton = true` |
| Hide status | Property | `hideUserStatus` | `header.hideUserStatus = true` |
| Disable typing | Property | `disableTyping` | `header.disableTyping = true` |
| Hide AI buttons | Property | `hideNewChatButton`, `hideChatHistoryButton` | `header.hideNewChatButton = true` |
| Custom subtitle | View Slot | `set(subtitleView:)` | See Custom View Slots |
| Custom menu options | Method | `set(options:)` | See Menu Customization |

***

## Connection Management

Manually control the WebSocket connection for the message header.

### connect()

Establishes the WebSocket connection for real-time updates. Use this when you need to manually reconnect after disconnecting.

```swift lines theme={null}
@discardableResult
public func connect() -> Self
```

```swift lines theme={null}
import CometChatUIKitSwift

let messageHeader = CometChatMessageHeader()

// Manually connect to receive real-time updates
messageHeader.connect()
```

### disconnect()

Disconnects the WebSocket connection. Use this when you want to temporarily stop receiving real-time updates, such as when the view is not visible.

```swift lines theme={null}
@discardableResult
public func disconnect() -> Self
```

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift

class ChatViewController: UIViewController {
    
    private var messageHeader: CometChatMessageHeader!
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        messageHeader.disconnect()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        messageHeader.connect()
    }
}
```

***

## Menu Customization

### set(options:)

Sets custom menu options for the message header. These options appear in the header's menu (typically accessed via a more button or long press).

```swift lines theme={null}
@discardableResult
public func set(options: [CometChatPopupMenu.MenuItem]?) -> CometChatMessageHeader
```

| Parameter | Type | Description |
| - | - | - |
| `options` | `[CometChatPopupMenu.MenuItem]?` | The menu items shown in the header overflow menu |

```swift lines theme={null}
import CometChatUIKitSwift
import CometChatSDK

let messageHeader = CometChatMessageHeader()

// On CometChatMessageHeader, `set(options:)` takes the ARRAY directly — it is not a closure.
// (Conversations, Users, Groups and Group Members each take a closure returning their own
// option type; the header does not. Passing a closure here will not compile.)
let viewProfileOption = CometChatPopupMenu.MenuItem(
    title: "View Profile",
    icon: UIImage(systemName: "person.circle") ?? UIImage(),
    action: { [weak self] in self?.showProfile() }
)

let muteOption = CometChatPopupMenu.MenuItem(
    title: "Mute Notifications",
    icon: UIImage(systemName: "bell.slash") ?? UIImage(),
    action: { [weak self] in self?.toggleMute() }
)

messageHeader.set(options: [viewProfileOption, muteOption])
```

***

## Props

All props are optional. Sorted alphabetically.

### avatarStyle

Customizes the appearance of the avatar in the message header.

| | |
| - | - |
| Type | `AvatarStyle` |
| Default | `AvatarStyle()` |

```swift lines theme={null}
import CometChatUIKitSwift

let messageHeader = CometChatMessageHeader()

let avatarStyle = AvatarStyle()
avatarStyle.backgroundColor = UIColor.systemBlue
avatarStyle.cornerRadius = CometChatCornerStyle(cornerRadius: 20)
avatarStyle.borderWidth = 2
avatarStyle.borderColor = UIColor.white

messageHeader.avatarStyle = avatarStyle
```

### dateTimeFormatter

Custom formatter for date/time display in the message header (e.g., "Last seen at...").

| | |
| - | - |
| Type | `CometChatDateTimeFormatter?` |
| Default | `nil` |

```swift lines theme={null}
import CometChatUIKitSwift

let messageHeader = CometChatMessageHeader()

let dateTimeFormatter = CometChatDateTimeFormatter()
dateTimeFormatter.todayFormat = "h:mm a"
dateTimeFormatter.yesterdayFormat = "'Yesterday at' h:mm a"
dateTimeFormatter.otherFormat = "MMM d, yyyy"

messageHeader.dateTimeFormatter = dateTimeFormatter
```

### disableTyping

Disables typing indicators in the message header.

| | |
| - | - |
| Type | `Bool` |
| Default | `false` |

```swift lines theme={null}
import CometChatUIKitSwift

let messageHeader = CometChatMessageHeader()
messageHeader.disableTyping = true
```

### enableThreadSubscription

*Available since v5.1.22*

Enables the subscribe/unsubscribe bell in the header's trailing area, letting users opt in to notifications for a thread's replies. The bell **also** requires `parentMessage` — setting this flag alone on a conversation header renders nothing, so turning the feature on globally cannot put a thread control on a non-thread screen. It renders in one-on-one threads as well as groups.

The bell manages itself: it reads the current state from the SDK, flips optimistically on tap, reverts on failure, toasts in both directions, and stays in step with a toggle made from the message action sheet.

| | |
| - | - |
| Type | `Bool` |
| Default | `false` |

```swift lines theme={null}
import CometChatUIKitSwift

let messageHeader = CometChatMessageHeader()
messageHeader.set(parentMessage: parentMessage)
messageHeader.set(enableThreadSubscription: true)
```

See the [Thread Subscription guide](/ui-kit/ios/guide-thread-subscription) for the full feature.

### hideBackButton

Hides the back button in the header.

| | |
| - | - |
| Type | `Bool` |
| Default | `false` |

### hideChatHistoryButton

Hides the AI chat history button in the header.

| | |
| - | - |
| Type | `Bool` |
| Default | `false` |

```swift lines theme={null}
import CometChatUIKitSwift

let messageHeader = CometChatMessageHeader()
messageHeader.hideChatHistoryButton = true
```

### hideNewChatButton

Hides the AI new chat button in the header.

| | |
| - | - |
| Type | `Bool` |
| Default | `false` |

```swift lines theme={null}
import CometChatUIKitSwift

let messageHeader = CometChatMessageHeader()
messageHeader.hideNewChatButton = true
```

### hideUserStatus

Hides the user status (online/offline/last active).

| | |
| - | - |
| Type | `Bool` |
| Default | `false` |

### hideThreadSubscriptionButton

*Available since v5.1.22*

Hides the subscribe/unsubscribe bell while leaving the feature on — for a screen that already draws its own control and would otherwise show two.

| | |
| - | - |
| Type | `Bool` |
| Default | `false` |

### hideVideoCallButton

Hides the video call button.

| | |
| - | - |
| Type | `Bool` |
| Default | `false` |

### hideVoiceCallButton

Hides the voice call button.

| | |
| - | - |
| Type | `Bool` |
| Default | `false` |

### onAiChatHistoryClicked

Callback triggered when the AI chat history button is clicked.

| | |
| - | - |
| Type | `(() -> Void)?` |
| Default | `nil` |

```swift lines theme={null}
import CometChatUIKitSwift

let messageHeader = CometChatMessageHeader()

messageHeader.onAiChatHistoryClicked = { [weak self] user in
    // Handle AI chat history button click
    self?.presentAiChatHistory()
})
```

### onAiNewChatClicked

Callback triggered when the AI new chat button is clicked.

| | |
| - | - |
| Type | `(() -> Void)?` |
| Default | `nil` |

```swift lines theme={null}
import CometChatUIKitSwift

let messageHeader = CometChatMessageHeader()

messageHeader.onAiNewChatClicked = { [weak self] user in
    // Handle AI new chat button click
    self?.startNewAiChat()
})
```

### parentMessage

*Available since v5.1.22*

The thread's root message the subscription bell acts on. Setting it puts the header in **thread mode**; leaving it `nil` keeps the header in its normal conversation mode with no bell.

| | |
| - | - |
| Type | `BaseMessage?` |
| Default | `nil` |

```swift lines theme={null}
import CometChatUIKitSwift

let messageHeader = CometChatMessageHeader()
messageHeader.set(parentMessage: parentMessage)
```

### statusIndicatorStyle

Customizes the appearance of the online/offline status indicator.

| | |
| - | - |
| Type | `StatusIndicatorStyle` |
| Default | `StatusIndicatorStyle()` |

```swift lines theme={null}
import CometChatUIKitSwift

let messageHeader = CometChatMessageHeader()

let statusIndicatorStyle = StatusIndicatorStyle()
statusIndicatorStyle.backgroundColor = UIColor.systemGreen
statusIndicatorStyle.borderWidth = 2
statusIndicatorStyle.borderColor = UIColor.white
statusIndicatorStyle.cornerRadius = CometChatCornerStyle(cornerRadius: 6)

messageHeader.statusIndicatorStyle = statusIndicatorStyle
```

### typingIndicatorStyle

Customizes the appearance of the typing indicator in the message header subtitle.

| | |
| - | - |
| Type | `TypingIndicatorStyle` |
| Default | `TypingIndicatorStyle()` |

```swift lines theme={null}
import CometChatUIKitSwift

let messageHeader = CometChatMessageHeader()

let typingIndicatorStyle = TypingIndicatorStyle()
typingIndicatorStyle.textColor = UIColor.systemGray
typingIndicatorStyle.textFont = UIFont.italicSystemFont(ofSize: 13)

messageHeader.typingIndicatorStyle = typingIndicatorStyle
```

***

## Events

The MessageHeader component does not emit any global UI events.

***

## Date Time Formatter

Customize how timestamps appear in the message header (e.g., "Last seen at...") using the `CometChatDateTimeFormatter`.

### Global Level Formatting

```swift lines theme={null}
import CometChatUIKitSwift

// Customize time format for last seen
CometChatMessageHeader.dateTimeFormatter.time = { timestamp in
    let date = Date(timeIntervalSince1970: TimeInterval(timestamp))
    let formatter = DateFormatter()
    formatter.dateFormat = "h:mm a"
    return "Last seen at " + formatter.string(from: date)
}

// Customize today format
CometChatMessageHeader.dateTimeFormatter.today = { timestamp in
    let date = Date(timeIntervalSince1970: TimeInterval(timestamp))
    let formatter = DateFormatter()
    formatter.dateFormat = "h:mm a"
    return "Last seen today at " + formatter.string(from: date)
}

// Customize yesterday format
CometChatMessageHeader.dateTimeFormatter.yesterday = { timestamp in
    let date = Date(timeIntervalSince1970: TimeInterval(timestamp))
    let formatter = DateFormatter()
    formatter.dateFormat = "h:mm a"
    return "Last seen yesterday at " + formatter.string(from: date)
}
```

### Instance Level Formatting

```swift lines theme={null}
import CometChatUIKitSwift

let messageHeader = CometChatMessageHeader()

messageHeader.dateTimeFormatter.otherDay = { timestamp in
    let date = Date(timeIntervalSince1970: TimeInterval(timestamp))
    let formatter = DateFormatter()
    formatter.dateFormat = "MMM d, yyyy"
    return "Last seen on " + formatter.string(from: date)
}
```

### Available Formatters

| Formatter | Purpose | Default Format |
| - | - | - |
| `time` | Standard time display | `h:mm a` |
| `today` | Last seen today | `Today at h:mm a` |
| `yesterday` | Last seen yesterday | `Yesterday at h:mm a` |
| `lastweek` | Last seen within last week | Day name |
| `otherDay` | Last seen older dates | `MMM d, yyyy` |

***

## Common Patterns

### Hide call buttons

```swift lines theme={null}
let messageHeader = CometChatMessageHeader()
messageHeader.set(user: user)
messageHeader.hideVideoCallButton = true
messageHeader.hideVoiceCallButton = true
```

### Custom back button action

```swift lines theme={null}
let messageHeader = CometChatMessageHeader()
messageHeader.set(user: user)

messageHeader.set(onBack: { [weak self] in
    // Custom navigation logic
    self?.dismiss(animated: true)
})
```

### Custom subtitle with typing indicator

```swift lines theme={null}
let messageHeader = CometChatMessageHeader()
messageHeader.set(user: user)

messageHeader.set(subtitleView: { user, group in
    let label = UILabel()
    label.font = UIFont.systemFont(ofSize: 12)
    
    if let user = user {
        label.text = user.status == .online ? "Online" : "Offline"
        label.textColor = user.status == .online ? .systemGreen : .secondaryLabel
    }
    
    return label
})
```

### Minimal header

```swift lines theme={null}
let messageHeader = CometChatMessageHeader()
messageHeader.set(user: user)
messageHeader.hideBackButton = true
messageHeader.hideUserStatus = true
messageHeader.hideVideoCallButton = true
messageHeader.hideVoiceCallButton = true
```

***

## Related Components

* [Messages](/ui-kit/ios/message-list) - Parent component containing MessageHeader
* [Message List](/ui-kit/ios/message-list) - Display messages in a conversation
* [Message Composer](/ui-kit/ios/message-composer) - Send messages in a conversation
* [Conversations](/ui-kit/ios/conversations) - Navigate back to conversation list


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.