JSFiddle - React, Tailwind, and code Playground

HTML

<!doctype html>
<html><head>
	<meta http-equiv="content-type" content="text/html; charset=UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
	<title>Qlik Sense Mashup</title>
	
	<meta name="HandheldFriendly" content="True">
	<meta name="MobileOptimized" content="320">
	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
	<meta name="apple-mobile-web-app-capable" content="yes">
	<meta name="apple-mobile-web-app-status-bar-style" content="black">
	<meta http-equiv="cleartype" content="on">
	<script src="../../resources/assets/external/requirejs/require.js"></script>
	<!-- Bootstrap core CSS -->
	<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
	<link href="http://demo.heldendaten.net:8080/extensions/Vertriebsdemo_Sense_Mashup/dist/css/AdminLTE.min.css" rel="stylesheet">
	<link href="http://demo.heldendaten.net:8080/extensions/Vertriebsdemo_Sense_Mashup/dist/css/skins/skin-orange.css" rel="stylesheet">
	<link href="http://fontawesome.io/assets/font-awesome/css/font-awesome.min.css" rel="stylesheet">
	<link href="../../resources/autogenerated/qlik-styles.css" rel="stylesheet">
	<style>
		/**
		* set padding to make room for bootstrap menu
		*
		*/
		body {
			padding-bottom: 30px;
		}

		/*
		* need to set the height for objects
		* set top padding to make room for selection toolbar
		*/
		div.qvobject, div.qvplaceholder {
			padding: 30px 10px 10px 10px;
			height: 400px;
		}

		.qcmd {
			cursor: pointer;
		}

		#popup {
			background-color: #7f8c8d;
			color: #FFFFFF;
			position: fixed;
			padding: 10px;
			margin: 10px;
			bottom: 0;
			right: 0;
			display: none;
			border-radius: 5px;
		}

		/*
		 * Overrides Bootstrap navbar z-index to avoid conflict with selections bar
		 */
		.navbar-fixed-top {
			position: relative;
			z-index: 100;
		}
		
		.container{
			width: 100%...

CSS

/* CSS */
* {
	position: relative;
	-moz-box-sizing: border-box;
	box-sizing: border-box;
	margin: 0;
	padding: 0;
	list-style: none;
}

html,
body {
	height: 100%;
}

body {
	background: #52be7f;
	color: #fff;
}

.component {
	position: relative;
	margin-bottom: 3em;
	height: 15em;
	background: rgba(0,0,0,0.05);
	font-family: 'Lato', Arial, sans-serif;
}

.component > h2 {
	position: absolute;
	overflow: hidden;
	width: 100%;
	text-align: center;
	text-transform: uppercase;
	white-space: nowrap;
	font-weight: 300;
	font-style: italic;
	font-size: 12em;
	opacity: 0.1;
	cursor: default;
}

.cn-button {
	position: absolute;
	top: 100%;
	left: 50%;
	z-index: 11;
	margin-top: -2.25em;
	margin-left: -2.25em;
	padding-top: 0em;
	width: 4.5em;
	height: 4.5em;
	border: none;
	border-radius: 50%;
	background: none;
	background-color: #fff;
	color: #52be7f;
	text-align: center;
	font-weight: 700;
	font-size: 1.5em;
	text-transform: uppercase;
	cursor: pointer;
	-webkit-backface-visibility: hidden;
}

.csstransforms .cn-wrapper {
	position: absolute;
	top: 100%;
	left: 50%;
	z-index: 10;
	margin-top: -13em;
	margin-left: -13.5em;
	width: 27em;
	height: 27em;
	border-radius: 50%;
	background: transparent;
	opacity: 0;
	-webkit-transition: all .3s ease 0.3s;
	-moz-transition: all .3s ease 0.3s;
	transition: all .3s ease 0.3s;
	-webkit-transform: scale(0.1);
	-ms-transform: scale(0.1);
	-moz-transform: scale(0.1);
	transform: scale(0.1);
	pointer-events: none;
	overflow: hidden;
}

/*cover to prevent extra space of anchors from being clickable*/
.csstransforms .cn-wrapper:after{
  content:".";
  display:block;
  font-size:2em;
  width:6.2em;
  height:6.2em;
  position: absolute;
  left: 50%;
  margin-left: -3.1em;
  top:50%;
  margin-top: -3.1em;
  border-radius: 50%;
  z-index:10;
  color: transparent;
}

.csstransforms .opened-nav {
	border-radius: 50%;
	opacity: 1;
	-webkit-transition: all .3s ease;
	-moz-transition: all .3s ease;
	transition: all .3s...

JavaScript

/*
 * Bootstrap-based responsive mashup
 * @owner Enter you name here (xxx)
 */
/*
 *    Fill in host and port for Qlik engine
 */
var prefix = window.location.pathname.substr( 0, window.location.pathname.toLowerCase().lastIndexOf( "/extensions" ) + 1 );

var config = {
	host: window.location.hostname,
	prefix: prefix,
	port: window.location.port,
	isSecure: window.location.protocol === "https:"
};
//to avoid errors in workbench: you can remove this when you have added an app
var app;
require.config( {
	baseUrl: (config.isSecure ? "https://" : "http://" ) + config.host + (config.port ? ":" + config.port : "" ) + config.prefix + "resources"
} );

require( ["js/qlik"], function ( qlik ) {

	var selectionslist = [];
	var control = false;
	qlik.setOnError( function ( error ) {
		$( '#popupText' ).append( error.message + "<br>" );
		if ( !control ) {
			control = true;
			$( '#popup' ).delay( 1000 ).fadeIn( 1000 ).delay( 11000 ).fadeOut( 1000 );
		}
	} );

	$( "#closePopup" ).click( function () {
		$( '#popup' ).hide();
	} );
	if ( $( 'ul#qbmlist li' ).length === 0 ) {
		$( '#qbmlist' ).append( "<li><a>No bookmarks available</a></li>" );
	}
	$( "body" ).css( "overflow: hidden;" );
	function AppUi ( app ) {
		var me = this;
		this.app = app;
		app.global.isPersonalMode( function ( reply ) {
			me.isPersonalMode = reply.qReturn;
		} );
		app.getAppLayout( function ( layout ) {
			$( "#title" ).html( layout.qTitle );
			$( "#title" ).attr( "title", "Last reload:" + layout.qLastReloadTime.replace( /T/, ' ' ).replace( /Z/, ' ' ) );
			//TODO: bootstrap tooltip ??
		} );
		app.getList( 'SelectionObject', function ( reply ) {
			$( "[data-qcmd='back']" ).parent().toggleClass( 'disabled', reply.qSelectionObject.qBackCount < 1 );
			$( "[data-qcmd='forward']" ).parent().toggleClass( 'disabled', reply.qSelectionObject.qForwardCount < 1 );
		} );
		app.getList( "BookmarkList", function ( reply ) {
			var str = "";
			reply.qBookmarkList.qItems.forEach( function ( value )...