Messenger UI
A messenger UI with a simple chatbot to demonstrate its functionality.
by Perry Kaufman
HTML
<section id="messager" class="messager">
<div id="messager-screen" class="messager-screen">
</div>
<form id="messager-form" class="messager-form">
<input class="messager-input" type="text" />
<button class="messager-button" type="submit">
send
</button>
</form>
</section>
CSS
@import url('https://fonts.googleapis.com/css?family=Open+Sans|Source+Sans+Pro');
html,
body {
box-sizing: border-box;
font-family: 'Open Sans', sans-serif;
font-size: 20px;
height: 100%;
padding: 0;
margin: 0;
width: 100%;
}
* {
box-sizing: inherit;
}
.messager {
display: flex;
height: 100%;
flex-flow: column nowrap;
width: 100%;
}
.messager-screen {
background-color: white;
display: flex;
flex: 1;
flex-flow: column nowrap;
padding: 10px;
overflow-y: scroll;
width: 100%;
}
.message {
display: flex;
flex-flow: column nowrap;
flex-shrink: 0;
margin-bottom: 5px;
max-width: 70%;
}
.message.send {
align-items: flex-end;
align-self: flex-end;
}
.message.receive {
align-items: flex-start;
align-self: flex-start;
}
.message-content {
border: none;
border-radius: 10px;
display: inline-block;
font-size: 1em;
max-width: 100%;
padding: 5px 8px;
overflow-wrap: break-word;
white-space: normal;
}
.receive>.message-content {
background-color: lightgray;
border-bottom-left-radius: 0;
}
.send>.message-content {
background-color: blue;
border-bottom-right-radius: 0;
color: white;
}
.message-time {
color: rgb(0, 0, 0, 0.75);
display: inline-block;
font-size: .6em;
margin-top: 3px;
}
.messager-form {
background-color: lightgray;
display: flex;
flex: 0 0 auto;
padding: 10px;
width: 100%;
}
.messager-input {
border: 2px solid gray;
border-radius: 10px;
flex: 1;
font-size: inherit;
margin-right: 2px;
min-width: 0;
padding: 2px 10px;
transition: all .2s ease-in-out;
}
.messager-input:focus {
border-color: blue;
outline: 0;
}
.messager-button {
background-color: blue;
border: none;
border-radius: 10px;
box-shadow: 2px 2px 3px rgb(0, 0, 0, 0.66);
color: white;
flex: none;
font-size: inherit;
padding: 2px 10px;
transition: all .25s ease-in-out, transform .1s ease-in-out;
}
.messager-button:focus,
.messager-button:hover {
...
JavaScript
const formatDate = function(date) {
let minutes = date.getMinutes();
let hours = date.getHours();
let day = date.getDate();
let month = date.getMonth() + 1;
let year = date.getFullYear();
let output = '';
if (hours === 0) output += '12';
else if (hours <= 12) output += String(hours);
else if (hours <= 23) output += String(hours - 12);
output += ':';
if (minutes < 10) output += '0';
output += String(minutes);
if (hours < 12) output += ' AM, '
else output += ' PM, '
output += String(month) + '/' + String(day) + '/' + String(year);
return output;
}
class Message {
constructor(content, date, type) {
this.content = content.trim();
if (this.content === '') throw new Error('Message cannot be empty.');
this.date = date;
this.type = type;
}
}
class ChatBot {
constructor(client) {
this.client = client;
this.client.setListener((message) => {
this._respondToMessage(message);
});
this._postGreeting();
}
_postGreeting() {
let greeting = 'Hello! I am a chatbot! I will repeat anything you say!';
this.client.postMessage(new Message(greeting, new Date(), 'receive'));
}
_respondToMessage(message) {
let length = message.content.length;
setTimeout(() => {
this.client.postMessage(new Message(message.content, new Date(), 'receive'));
}, 250 + 25 * length);
}
}
class MessagerUI {
constructor() {
this._listener = null;
let messager = document.querySelector('#messager');
if (!messager) {
throw new Error('Messager incorrectly formatted.');
}
this._screen = messager.querySelector('#messager-screen')
if (!this._screen) {
throw new Error('Messager incorrectly formatted.');
}
this._form = messager.querySelector('#messager-form')
if (!this._form) {
throw new Error('Messager incorrectly formatted.');
}
this._input = this._form.querySelector('input');
if (!this._input) {
throw new Error('Messager...