Customize the Messaging Conversation Window Header Using LWC

You can customize the messaging conversation window header using a custom conversation header Lightning Web Component (LWC).

These steps show you how to create a messaging conversation window header using a custom LWC. The sample code creates a header, as shown in the screenshot. The code includes:

We left these features out of this example to keep the sample code short, but you can add them later to your LWC with your own custom code.

  • Header announcements
  • Accessibility
  • Right-to-left language handling
  • A minimize button in the mobile version’s header—In the browser, you can minimize the window with the default floating action button, but the mobile version doesn’t have that.

Custom messaging conversation window header

  1. Create an LWC bundle. See Salesforce Trailhead: Build Lightning Web Components.

    Let’s call our example bundle customHeader.

  2. In the customHeader.js-meta.xml configuration file of your LWC, specify the lightningSnapin__MessagingHeader target.

    You add this target to the configuration file so you can see the LWC in your Enhanced Web Chat experience. In other words, adding this target makes the LWC available for selection in Custom UI Components in Embedded Service Deployments in Setup. See Customize your UI with Lightning Web Components.

    customHeader.js-meta.xml
    1<?xml version="1.0" encoding="UTF-8"?>
    2<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    3 <apiVersion>60.0</apiVersion>
    4 <isExposed>true</isExposed>
    5 <targets>
    6     <target>lightningSnapin__MessagingHeader</target>
    7 </targets>
    8</LightningComponentBundle>
  3. In the customHeader.js file, use these methods to customize the header.

    1. To connect your custom component to Embedded Service, import the dispatchMessagingEvent, assignMessagingEventHandler, and MESSAGING_EVENT methods from the public event store lightningsnapin/eventStore.

      1import { dispatchMessagingEvent, assignMessagingEventHandler, MESSAGING_EVENT } from "lightningsnapin/eventStore";
    2. To dispatch a Messaging event, use dispatchMessagingEvent. See Messaging Conversation Window Header Events dfor all available Messaging header events.

      1/**
      2* Dispatch all public event handlers with data for a given event.
      3* @param {String} eventName - Name of event to dispatch. Can't be null.
      4* @param {Object} eventData - Data to pass to each event handler.
      5*                             Can't be null. Use empty object {} if you're passing no data.
      6*/
      7dispatchMessagingEvent(eventName, eventData);
    3. To listen to a Messaging event, use assignMessagingEventHandler.

      1/**
      2* Assign a public event handler for an event.
      3* @param {String} eventName - Name of the event to assign a handler.
      4* @param {Function} eventHandler - Function to assign to the event.
      5*/
      6assignMessagingEventHandler(eventName, eventHandler);
    customHeader.js
    1import { LightningElement, api } from "lwc";
    2import { dispatchMessagingEvent, assignMessagingEventHandler, MESSAGING_EVENT } from "lightningsnapin/eventStore";
    3
    4const SLDS_MENU_SELECTOR = "slds-dropdown-trigger slds-dropdown-trigger_click";
    5
    6export default class ChatHeader extends LightningElement {
    7  /**
    8  * Deployment configuration data.
    9  * @type {Object}
    10  */
    11  @api configuration = {};
    12
    13  /**
    14  * The status of the conversation. Valid values:
    15  * - NOT_STARTED
    16  * - OPEN
    17  * - CLOSED
    18  * @type {ConversationStatus}
    19  */
    20  @api conversationStatus;
    21
    22  /**
    23  * Class name for header menu.
    24  * @type {String}
    25  */
    26  menuClass = SLDS_MENU_SELECTOR;
    27
    28  /**
    29  * Array to store bot options menu.
    30  * @type {Array}
    31  */
    32  chatbotOptionsMenu = [];
    33
    34  /**
    35  * Whether the use is authenticated.
    36  * AuthMode can have the following values:
    37  * - Auth: user is in verified, which corresponds to the authenticated user mode.
    38  * - UnAuth: user is in unverified,  which corresponds to the guest user mode.
    39  */
    40  get isAuthenticatedContext() {
    41      return this.configuration.embeddedServiceMessagingChannel.authMode === "Auth";
    42  }
    43
    44  /**
    45  * Whether to show the back button.
    46  * @type {Boolean}
    47  */
    48  showBackButton = false;
    49
    50  /**
    51  * Whether to show the header menu button.
    52  * @returns {Boolean}
    53  */
    54  get showMenuButton() {
    55      return this.conversationStatus === "OPEN";
    56  }
    57
    58  /**
    59  * Whether to show the header menu.
    60  * @type {Boolean}
    61  */
    62  _showMenu = false;
    63  get showMenu() {
    64      return this._showMenu;
    65  }
    66  set showMenu(shouldShow) {
    67      this.menuClass = SLDS_MENU_SELECTOR + (shouldShow ? " slds-is-open" : "");
    68      this._showMenu = shouldShow;
    69  }
    70
    71  /**
    72  * Whether to show the close button.
    73  * @returns {Boolean}
    74  */
    75  get showCloseButton() {
    76      return this.conversationStatus !== "OPEN";
    77  }
    78
    79  /**
    80  * Handle back button click.
    81  */
    82  onBackButtonClick() {
    83      dispatchMessagingEvent(MESSAGING_EVENT.BACK_BUTTON_CLICK, {});
    84  }
    85
    86  /**
    87  * Handle menu button click.
    88  */
    89  onMenuButtonClick() {
    90      this.showMenu = !this.showMenu;
    91  }
    92
    93  /**
    94  * Handle minimize button click.
    95  */
    96  onMinimizeButtonClick() {
    97      dispatchMessagingEvent(MESSAGING_EVENT.MINIMIZE_BUTTON_CLICK, {});
    98  }
    99
    100  /**
    101  * Handle close button click.
    102  */
    103  onCloseButtonClick() {
    104      dispatchMessagingEvent(MESSAGING_EVENT.CLOSE_CONTAINER, {});
    105  }
    106
    107  /**
    108  * Handle end conversation button click.
    109  */
    110  onMenuOptionClick(event) {
    111      event.preventDefault();
    112
    113      dispatchMessagingEvent(MESSAGING_EVENT.MENU_ITEM_SELECTED, {
    114          selectedOption: this.chatbotOptionsMenu.find(option => option.optionIdentifier === event.target.getAttribute("value"))
    115      });
    116
    117      this.showMenu = false;
    118  }
    119
    120/**
    121* Handle end chat button click.
    122*
    123* Ending a messaging session is only supported for verified users.
    124* Ending a conversation is only supported for unverified users.
    125*/
    126onEndChatClick() {
    127    if (this.isAuthenticatedContext) {
    128        this.configuration.util.endSession();
    129    } else {
    130        dispatchMessagingEvent(MESSAGING_EVENT.CLOSE_CONVERSATION, {});
    131    }
    132
    133    this.showMenu = false;
    134}
    135
    136  connectedCallback() {
    137      assignMessagingEventHandler(MESSAGING_EVENT.PARTICIPANT_JOINED, (data) => {
    138          console.log(`Participant joined`);
    139
    140          if (data.options && Array.isArray(data.options)) {
    141              data.options.forEach((participantOption) => {
    142                  this.chatbotOptionsMenu.push(participantOption);
    143              });
    144          }
    145      });
    146
    147      assignMessagingEventHandler(MESSAGING_EVENT.PARTICIPANT_LEFT, (data) => {
    148          console.log(`Participant left`);
    149
    150          this.chatbotOptionsMenu = [];
    151      });
    152
    153      assignMessagingEventHandler(MESSAGING_EVENT.UPDATE_HEADER_TEXT, (data) => {
    154          console.log(`Update header text: ${data.text}`);
    155      });
    156
    157      assignMessagingEventHandler(MESSAGING_EVENT.TOGGLE_BACK_BUTTON, (data) => {
    158          console.log(`Toggle back button visibility.`);
    159
    160          this.showBackButton = data.showBackButton;
    161      });
    162  }
    163}
  4. In the customHeader.html file, add all the header components and buttons to render in the UI.

    customHeader.html
    1<template>
    2    <!-- Back button -->
    3    <template if:true={showBackButton}>
    4        <button class="headerButton backButton" onclick={onBackButtonClick}>
    5            <lightning-icon icon-name="utility:back" variant="inverse" size="x-small"></lightning-icon>
    6        </button>
    7    </template>
    8
    9    <!-- Header menu -->
    10    <section class={menuClass}>
    11        <template if:true={showMenuButton}>
    12            <!-- Menu button -->
    13            <button class="headerButton menuButton" onclick={onMenuButtonClick}>
    14                <lightning-icon icon-name="utility:threedots_vertical" variant="inverse" size="x-small"></lightning-icon>
    15            </button>
    16        </template>
    17
    18        <!-- Menu options-->
    19        <section class="optionsMenu slds-dropdown slds-dropdown_left slds-nubbin_top-left">
    20            <ul class="slds-dropdown__list">
    21                <!-- Bot menu options -->
    22                <template for:each={chatbotOptionsMenu} for:item="option">
    23                    <li class="slds-dropdown__item" key={option.optionIdentifier}>
    24                        <button class="chatbotMenuOption"
    25                                value={option.optionIdentifier}
    26                                onclick={onMenuOptionClick}>
    27                            <span value={option.optionIdentifier}>{option.title}</span>
    28                        </button>
    29                    </li>
    30                </template>
    31
    32            <!-- End chat option -->
    33            <li class="slds-dropdown__item">
    34                <button class="chatbotMenuOption"
    35                        onclick={onEndChatClick}>
    36                    <span class="slds-text-color_error">End Chat</span>
    37                </button>
    38            </li>
    39            </ul>
    40        </section>
    41    </section>
    42
    43    <!-- Header logo -->
    44    <!-- Replace this with your logo file. -->
    45    <img src="/path/to/logo.png" alt="My Logo"/>
    46
    47    <!-- Header text -->
    48    <h2>Custom Header</h2>
    49
    50    <!-- Minimize button -->
    51    <button class="headerButton minimizeButton" onclick={onMinimizeButtonClick}>
    52        <lightning-icon icon-name="utility:chevrondown" variant="inverse" size="x-small"></lightning-icon>
    53    </button>
    54
    55    <!-- Close button -->
    56    <template if:true={showCloseButton}>
    57        <button class="headerButton closeButton" onclick={onCloseButtonClick}>
    58            <lightning-icon icon-name="utility:close" variant="inverse" size="x-small"></lightning-icon>
    59        </button>
    60    </template>
    61</template>
  5. In the customHeader.css file, customize the UI style of the header components and buttons.

    customHeader.css
    1:host {
    2    width: 100%;
    3    max-width: 100%;
    4    min-height: 50px;
    5    display: flex;
    6    align-items: center;
    7    box-sizing: border-box;
    8    position: relative;
    9    padding: 0 14px;
    10    height: 50px;
    11    max-height: 50px;
    12    background-color: black;
    13}
    14
    15img {
    16    margin-right: 4px;
    17    max-height: 40px;
    18    max-width: 40px;
    19}
    20
    21h2 {
    22    margin: 0;
    23    text-align: initial;
    24    align-self: center;
    25    flex-grow: 1;
    26    overflow: hidden;
    27    text-overflow: ellipsis;
    28    white-space: nowrap;
    29    font-weight: lighter;
    30    font-size: inherit;
    31    color: white;
    32}
    33
    34.headerButton {
    35    background: none;
    36    border: none;
    37    display: inline-flex;
    38    height: 32px;
    39    min-height: 32px;
    40    width: 32px;
    41    min-width: 32px;
    42    align-items: center;
    43    justify-content: center;
    44}
    45
    46.headerButton:hover:before {
    47    content: " ";
    48    position: absolute;
    49    top: 9px;
    50    width: 32px;
    51    height: 32px;
    52    background-color: #fff;
    53    opacity: .2;
    54    border-radius: 4px;
    55    box-sizing: border-box;
    56    pointer-events: none;
    57}
    58
    59.headerButton.menuButton:hover:before {
    60    top: 0;
    61}
    62
    63.headerButton.closeButton:hover:before {
    64    right: 14px;
    65}
    66
    67lightning-icon {
    68    fill: white;
    69}
    70
    71.optionsMenu {
    72    width: 100vw;
    73    left: -0.9rem;
    74}
    75
    76.optionsMenu > .slds-dropdown__list {
    77    max-height: 20rem;
    78    overflow-y: auto;
    79}
    80
    81.slds-nubbin_top-left:before,
    82.slds-nubbin_top-left:after {
    83    left: 2rem;
    84    top: -0.5rem;
    85}
    86
    87.slds-dropdown {
    88    max-width: 30rem;
    89}
    90
    91.slds-dropdown__item > button {
    92    position: relative;
    93    z-index: 100;
    94    padding: 0.75rem 1rem;
    95    background-color: #ffffff;
    96    border: 0;
    97    display: flex;
    98    width: 100%;
    99}
    100
    101.slds-dropdown__item > button:focus,
    102.slds-dropdown__item > button:hover {
    103    outline: 0;
    104    text-decoration: none;
    105    background-color: #e5e5e5;
    106}
    107
    108.slds-dropdown__list > .slds-dropdown__item:not(:first-child) {
    109    border-top: #e2e2e2 1px solid;
    110}
    111
    112.slds-dropdown__item .slds-truncate:not(.closeConversation) {
    113    color: #005290;
    114}
  6. Deploy the LWC to your org. See Salesforce Developer Guide: Introducing Lightning Web Components.

  7. Add the LWC to your Embedded Service Deployment. See Salesforce Help: Customize Your UI with Lightning Web Components. To get custom LWC configuration details, see Salesforce Developer Guide: Get Custom Lightning Web Components Configuration Details