JSFiddle - React, Tailwind, and code Playground

by FZambia

HTML

<script src="https://rawgit.com/Caligatio/jsSHA/master/src/sha256.js"></script>
<script src="https://cdn.jsdelivr.net/sockjs/1.0/sockjs.min.js"></script>
<script src="https://rawgit.com/centrifugal/centrifuge-js/master/centrifuge.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.15.1/TweenMax.min.js"></script>
<p style="margin: 0 auto; max-width: 400px; margin-bottom: 10px;">
    Demo chat using <a target="_blank"  href="https://github.com/centrifugal/centrifugo">Centrifugo server</a> and javascript client for it. <span class="help">Open several browser tabs to see it in action. Layout inspired by <a href="http://tympanus.net/Development/CreativeGooeyEffects/" target="_blank">Lucas Bebber's work</a></span>
</p>
<div class="content">
    <div class="chat-window">
        <div class="chat-messages" style="height: 406px;">
            <ol class="chat-messages-list">
            </ol>
        </div>
        <div class="chat-input-bar">
            <div class="chat-info-container">
                
            </div>
            <div class="chat-effect-container" style="-webkit-filter: none; filter: none;">
                <div class="chat-effect-bar"></div>
            </div>
            <div class="chat-input-wrapper">
                <button class="chat-input-tool">
                    <i class="icon icon-camera"></i>
                </button>
                <div class="chat-input" contenteditable=""></div>
                <button class="chat-send">
                    <i class="fa fa-paper-plane"></i>
                </button>
            </div>
        </div>
    </div>
</div>

CSS

*,
*:after,
*:before {
	-webkit-box-sizing: border-box;
	box-sizing: border-box;
}

.cf:before,
.cf:after {
	content: '';
	display: table;
}

.cf:after {
	clear: both;
}

body {
	background: #46484a;
	color: #a8a8a8;
	font-weight: 400;
	font-size: 1em;
	font-family: 'Raleway', 'Avenir Next', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

a {
	color: #fff;
	text-decoration: none;
	outline: none;
}

a:hover,
a:focus,
.codrops-demos a.current-demo {
	color: #eab1c6;
	outline: none;
}

button:focus {
	outline: none;
}

.container {
	margin: 0 auto;
	text-align: center;
	overflow: hidden;
}
.chat-window button:focus {
	-webkit-tap-highlight-color: rgba(255,255,255,0);
	-webkit-tap-highlight-color: transparent;
	outline: none;
}

.chat-window {
	width: 310px;
	margin: 0 auto;
	overflow: hidden;
	border: 0px solid #36383a;
	border-width: 50px 15px;
	color: #474c57;
	border-radius: 20px;
	font-family: 'Avenir Next', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

@media screen and (max-width:380px) {
	.chat-window {
		border: none;
		border-radius: 0px;
	}
}

.chat-window a {
	color: #eab1c6;
}

.chat-window a:hover,
.chat-window a:focus {
	color: #C7668A;
}

.chat-messages {
	height: 460px;
	overflow-x: hidden;
	overflow-y: auto;
	width: 100%;
	position: relative;
	border-radius: 2px 2px 0 0;
	background: url(https://i.imgur.com/5YrKtuf.jpg) no-repeat center center;
  -webkit-background-size: cover;
  -moz-background-size: cover;
  -o-background-size: cover;
  background-size: cover;
}

.chat-messages-list {
	list-style-type: none;
	padding: 0;
	margin: 0;
	width: 100%;
	padding: 15px 25px 60px;
}

.chat-message {
	position: relative;
	font-size: 0;
	margin-bottom: 10px;
}

.chat-message-effect {
	position: absolute;
}

.chat-message-bubble {
	display: inline-block;
	font-size: 14px;
	max-width: 350px;
	background: #fff;
	padding: 8px 14px;
	border-radius: 18px;
	min-width: 0;
}

.chat-message-self.chat-message-merge-start .chat-message-bubble...

JavaScript

// Centrifugo address
var url = "https://centrifugo.herokuapp.com/connection";

// project key - must be registered in Centrifugo configuration
var project = "development";

// project secret, note that you MUST NEVER reveal project secret key in production
// this is just a demo where we generate connection token on client side
var secret = "secret";

// generate random user ID
var user = "" + parseInt((Math.random() * (10 - 20000) + 20000).toFixed(2));

// current timestamp
var timestamp = parseInt(new Date().getTime()/1000).toString();

// generate connection token (must be done on backend in real usage scenario)
var hmacBody = project + user + timestamp;
var shaObj = new jsSHA("SHA-256", "TEXT");
shaObj.setHMACKey(secret, "TEXT");
shaObj.update(hmacBody);
var token = shaObj.getHMAC("HEX");

var KEY_ENTER=13;

var $input=$(".chat-input"),
    $sendButton=$(".chat-send"),
    $messagesContainer=$(".chat-messages"),
    $messagesList=$(".chat-messages-list"),
    $effectContainer=$(".chat-effect-container"),
    $infoContainer=$(".chat-info-container"),
    messages=0,
    bleeding=100,
    isFriendTyping=false,
    incomingMessages=0,
    lastMessage="";

function addMessage(message,messageType){
    messageType = messageType || 'system';
    var $messageContainer=$("<li/>")
    .addClass('chat-message '+ 'chat-message-'+messageType)
    .appendTo($messagesList)
    ;
    var $messageBubble=$("<div/>")
    .addClass('chat-message-bubble')
    .appendTo($messageContainer)
    ;
    $messageBubble.text(message);
    
    var oldScroll=$messagesContainer.scrollTop();
    $messagesContainer.scrollTop(9999999);
    var newScroll=$messagesContainer.scrollTop();
    var scrollDiff=newScroll-oldScroll;
    TweenMax.fromTo(
        $messagesList,0.4,{
            y:scrollDiff
        },{
            y:0,
            ease:Quint.easeOut
        }
    );
    
    return {
        $container:$messageContainer,
        $bubble:$messageBubble
    };
}

function...