@stackchat/proactive-messaging
v1.0.9
Published
Message popups for the stackchat web-messenger
Downloads
132
Readme
@stackchat/proactive-messaging
A utility library for @stackchat/web-messenger
to display proactive messages to a user above the Stackchat Web Messenger button or tab.
Table of Contents
Introduction
This library allows you to handle the creation, display and manipulation of messages that are proactively displayed to the user. A user can also interact with these messages eliminating the need of guesswork from the user.
Proactive messages can be triggered automatically during an ongoing conversation in the Stackchat Web Messenger or can be manually triggered as the need arises.
Each proactive message looks like this(when default styles are used)
or like this with actions:
Note: Proactive messages are only displayed if and only if the messenger widget is not open. If it is open, then all the proactive messages are silently ignored.
Usage
Note: This library works in conjuction with and requires @stackchat/web-messenger
so as to be able to display proactive messages.
Script
If your project does not use a bundler or package manager, you can use our cdn hosted assets:
<!--
Copy and paste the following script right below
the 'script' tag for Stackchat Web Messenger
-->
<script async type="text/javascript" src="https://assets.au.stackchat.com/sdk/proactive-messaging/1.0.4/index.js"></script>
Optionally, if you would to include our default styles, also add the following:
<link type="text/css" src="https://assets.au.stackchat.com/sdk/proactive-messaging/1.0.4/main.css">
Now you have access to Stackchat Web Messenger(exposed as window.stackchat
) and ProactiveMessaging(exposed as window.ProactiveMessaging
)
<script>
let messageStack;
// add an event listener to initialise Proactive
// Messaging once Stackchat Web Messenger has
// finished initialising
window.stackchat.on('ready', initialiseProactiveMessaging)
window.stackchat.init({
appId: "YOUR_APP_ID_HERE"
})
function initialiseProactiveMessaging() {
// This step is required before calling
// messageStack.start()
messageStack = new window.ProactiveMessaging({
messenger: window.stackchat,
ttl: 4000 // default
author: "Test Bot"
})
// start
messageStack.start();
}
</script>
Package Manager
Install the dependencies via npm
or yarn
:
# NPM
npm install --save @stackchat/web-messenger@latest @stackchat/proactive-messaging@latest
# Yarn
yarn add @stackchat/web-messenger@latest @stackchat/proactive-messaging@latest
To include our default styles, also include the following:
import "@stackchat/proactive-messaging/dist/main.css"
Now in your JavaScript code:
import Stackchat from "@stackchat/web-messenger";
import { ProactiveMessaging } from "@stackchat/proactive-messaging";
let messageStack
// Add an event listener to know when Web Messenger
// is ready to go
Stackchat.on('ready', initialiseProactiveMessaging)
//
const initialiseProactiveMessaging() => {
// This step is required before calling
// messageStack.start()
messageStack = new ProactiveMessaging({
messenger: Stackchat,
ttl: 4000 // default
author: "Test Bot"
})
// start
messageStack.start();
}
// Initialise Web Messenger
Stackchat.init({
appId: "YOUR_APP_ID_HERE"
})
API
This library exposes a single class - ProactiveMessaging
- which is used to handle proactives messages and to manipulate them.
const messageStack = new ProactiveMessaging(options) //see below
Initialisation Options
options
| Property | Optional | Default Value | Description | |-----------|----------|--- |-------------| |
messenger
|No |- |An initialised instance of the StackChat Web Messenger. This is required to be able to display the proactive messages above the message bubble/tab | |ttl
|Yes |2000 |The amount of time each message should live on the screen in milliseconds. By default, its 2s i.e. 2000ms| |author
|No |- |The name displayed at the top of each message. This is what will be used as author name for each proactive message| |maxMessages
|No |- |The maximum number of messages that are displayed on the screen at any given time. By default, it is 3| |singularCloseButton
|No |- |Determines whether to show one close button for all messages or one for each message|
Methods
start()
Triggers the
ProactiveMessaging
instance to start listening for incoming messages in a conversation. As long as the messenger widget is not open,ProactiveMessaging
will ensure that any message which contains the following in itsmetadata
property will be displayed proactively.{ proactive: true } // Therefore the message object should look like this message = { metadata: { proactive: true, ...otherMetaProps }, ...otherMessageProps }
addMessage(text, actions?)
Allows the developer to simulate or display a proactive message to the user without it becoming a part of the ongoing conversation.
For e.g.
// Without actions messageStack.addMessage("Hello, world!") // With actions messageStack.addMessage( "Hello, world!", [ { text: "Hello there!", openMessengerOnReply: false }, { text: "Hi! What are you up to?", openMessengerOnReply: true } ] )
stop()
Triggers the
ProactiveMessaging
instance to stop listening to incoming messages and removes all associated DOM elements from the page.
Event Binding
ProactiveMessaging
offers two special methods to allow developers to react to events as they occur.
Note: You can add and remove event binding at any time.
on(event, handler)
Allows you to specify a callback for a event which is called when that aforesaid event occurs.
off(event?, handler?)
Allows you to remove a callback tied to an event. If no handler is specfied, it removes all the callbacks associated with the event. If no event has been specified, all callbacks for all events are cleared.
Events
This is the list of events that you can use with on
and off
methods as described above.
ready
This event is fired when your
ProactiveMessaging
instance is ready. From this point on, it can start displaying proactive messages.messageStack.on("ready", () => { console.log("Proactive Messaging is ready!"); });
proactive-message:clicked
This event is fired when a user clicks on a proactive message. This event is not fired when a user dismisses a message or clicks on a quick reply.
messageStack.on("proactive-message:clicked", (event) => { console.log("Proactive Message clicked > message", event.message); });
proactive-message:dismissed
This event is fired when a user dismisses a proactive message. It is not fired if the message auto dismisses after the
ttl
.messageStack.on("proactive-message:dismissed", (event) => { console.log("Proactive Message dismissed > message", event.message); });
quick-reply:clicked
This event is fired when a user clicks on one of the quick replies in a proactive message.
messageStack.on("quick-reply:clicked", (event) => { console.log("Quick reply clicked"); console.log("Message", event.message); console.log("Quick reply", event.quickReply); });
messenger:opened
This event is fired whenever the Stackchat Web Messenger is opened by your
ProactiveMessaging
instance. Stackchat Web Messenger is opened when a user clicks on a message or clicks on one of the quick replies. Refer to the first part of the API section above.messageStack.on("messenger:opened", () => { console.log("Stackchat Web Messenger opened"); });
clear
This event is fired when all the proactive messages have been cleared - by user interaction or otherwise. Consider this as a blank slate similar to right after the
ready
event has occured.messageStack.on("clear", () => { console.log("All proactive messages cleared!"); });
Styling
Default Styles
This library includes some base styles that display proactive messages in the nice UI as shown above here and here.
Consuming default styles depends on the way you integrate this library:
Script
You can use our CDN hosted stylesheet via a
script
tag<link type="text/css" src="https://assets.au.stackchat.com/sdk/proactive-messaging/1.0.4/main.css">
Package Manager
When using a package manager like
npm
oryarn
, the default styles are automatically imported when you importProactiveMessaging
.In this case, you need only provide additional styles to suit your organisation's branding requirements. Please look at the custom styles section below.
Custom Styles
The module mostly uses class
es to apply styles to the individual components and they are named logically so to enable easy overrides.
Important
Some base styles are required to display proactive messages properly. These styles are added to the elements inline and therefore, can not be overridden.
Animations
If you plan on overriding the default animation behaviour, please ensure you provide styles for two selectors i.e.
@keyframes
and@webkit-keyframes
to account for compatibility with different browsers.
The default stylesheet is provided below for your reference. Use it as a reference point for classes you would like to add custom styles to.
/** The base container for all proactive messages **/
.proactive-container {
overflow-y: hidden;
display: flex;
align-items: flex-end;
justify-content: flex-end;
flex-direction: column;
z-index: 9998;
}
.proactive-container * {
outline: none;
}
/** Singular close button to dismiss all messages **/
.proactive-container .external-close-button {
width: 32px;
height: 32px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
border: none;
background-color: #d8d8d8;
cursor: pointer;
}
/** The container for individual proactive message **/
.proactive-container .proactive-message {
margin-bottom: 8px;
padding: 4px;
}
/** The message inside each proactive message **/
.proactive-container .proactive-message .message {
background-color: white;
border-radius: 8px;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: flex-start;
box-shadow: 0 0 4px 1px rgba(0, 0, 0, 0.2);
width: 232px;
}
.proactive-container .proactive-message .message .header {
position: relative;
width: 100%;
height: 40px;
display: flex;
align-items: center;
justify-content: flex-start;
}
/** The author of the proactive message **/
.proactive-container .proactive-message .message .header .name {
margin: 0;
margin-left: 16px;
margin-right: 8px;
font-weight: 600;
font-size: 14px;
color: #8c1aff;
}
/** The close button inside each proactive message **/
.proactive-container .proactive-message .message .header .close-button {
position: absolute;
right: 0;
top: 0;
width: 40px;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: transparent;
border: none;
cursor: pointer;
}
/** The content of the proactive message **/
.proactive-container .proactive-message .message .content {
padding: 8px 16px 16px 16px;
}
.proactive-container .proactive-message .message .content .text {
margin: 0;
font-size: 14px;
}
/** The container for quick actions(if any) for each individual message **/
.proactive-container .proactive-message .actions {
margin-top: 4px;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: flex-end;
}
/** Each indidivual action of a proactive message **/
.proactive-container .proactive-message .actions .action {
background: linear-gradient(
0,
rgba(140, 26, 255, 0.45) 60%,
rgba(140, 26, 255, 0.45) 60%
), linear-gradient(0, #fff 100%, #fff 0);
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
border: 1px solid #8c1aff;
border-radius: 4px;
margin-left: 4px;
font-size: 14px;
padding: 11px;
min-width: 64px;
font-weight: 600;
cursor: pointer;
line-height: 16px;
color: #000;
}
/**
* Classes to handle animating in and out
* of individual proactive messages
*/
.show-message,
.hide-message {
-webkit-animation-name: animGenie;
animation-name: animGenie;
-webkit-animation-duration: 0.4s;
animation-duration: 0.4s;
}
.hide-message {
animation-direction: reverse;
-webkit-animation-name: animGenieReverse;
animation-name: animGenieReverse;
}
/**
* The animation for messaging coming in
* and being displayed on screen
*/
@-webkit-keyframes animGenie {
0% {
opacity: 0;
-webkit-transform: translate3d(45%, calc(144%), 0) scale3d(0, 1, 1);
transform: translate3d(45%, calc(144%), 0) scale3d(0, 1, 1);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
40% {
opacity: 0.5;
-webkit-transform: translate3d(27%, 0, 0) scale3d(0.02, 1.1, 1);
transform: translate3d(27%, 0, 0) scale3d(0.02, 1.1, 1);
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out;
}
70% {
opacity: 0.6;
-webkit-transform: translate3d(9%, -40px, 0) scale3d(0.8, 1.1, 1);
transform: translate3d(9%, -40px, 0) scale3d(0.8, 1.1, 1);
}
100% {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
}
}
@keyframes animGenie {
0% {
opacity: 0;
-webkit-transform: translate3d(45%, calc(144%), 0) scale3d(0, 1, 1);
transform: translate3d(45%, calc(144%), 0) scale3d(0, 1, 1);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
40% {
opacity: 0.5;
-webkit-transform: translate3d(27%, 0, 0) scale3d(0.02, 1.1, 1);
transform: translate3d(27%, 0, 0) scale3d(0.02, 1.1, 1);
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out;
}
70% {
opacity: 0.6;
-webkit-transform: translate3d(9%, -40px, 0) scale3d(0.8, 1.1, 1);
transform: translate3d(9%, -40px, 0) scale3d(0.8, 1.1, 1);
}
100% {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
}
}
/**
* The animation for messaging going out
* and being removed off screen
*/
@-webkit-keyframes animGenieReverse {
0% {
opacity: 0;
-webkit-transform: translate3d(45%, calc(144%), 0) scale3d(0, 1, 1);
transform: translate3d(45%, calc(144%), 0) scale3d(0, 1, 1);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
40% {
opacity: 0.5;
-webkit-transform: translate3d(27%, 0, 0) scale3d(0.02, 1.1, 1);
transform: translate3d(27%, 0, 0) scale3d(0.02, 1.1, 1);
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out;
}
70% {
opacity: 0.6;
-webkit-transform: translate3d(9%, -40px, 0) scale3d(0.8, 1.1, 1);
transform: translate3d(9%, -40px, 0) scale3d(0.8, 1.1, 1);
}
100% {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
}
}
@keyframes animGenieReverse {
0% {
opacity: 0;
-webkit-transform: translate3d(45%, calc(144%), 0) scale3d(0, 1, 1);
transform: translate3d(45%, calc(144%), 0) scale3d(0, 1, 1);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
40% {
opacity: 0.5;
-webkit-transform: translate3d(27%, 0, 0) scale3d(0.02, 1.1, 1);
transform: translate3d(27%, 0, 0) scale3d(0.02, 1.1, 1);
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out;
}
70% {
opacity: 0.6;
-webkit-transform: translate3d(9%, -40px, 0) scale3d(0.8, 1.1, 1);
transform: translate3d(9%, -40px, 0) scale3d(0.8, 1.1, 1);
}
100% {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
}
}