JSFiddle - React, Tailwind, and code Playground

by mackry

HTML

<ul>
    <li class="challenge">Eat More Broccoli 1</li>
    <li class="challenge">Eat More Broccoli 2</li>
    <li class="challenge">Eat More Broccoli 3</li>
    <li class="challenge">Eat More Broccoli 4</li>
</ul>

<div id="modal">
    <div class="dialog">
        <div>
            <span>1 of 1</span>
            <a href="#previous" title="Previous Challenge">⇽</a>
            <a href="#next" title="Next Challenge">⇾</a>
            <a href="#close" title="Close">&times;</a>
        </div>
        <h3>Eat More Broccoli 1</h3>
    </div>
        <div class="dialog">
        <div>
            <span>1 of 1</span>
            <a href="#previous" title="Previous Challenge">⇽</a>
            <a href="#next" title="Next Challenge">⇾</a>
            <a href="#close" title="Close">&times;</a>
        </div>
        <h3>Eat More Broccoli 2</h3>
    </div>
        <div class="dialog">
        <div>
            <span>1 of 1</span>
            <a href="#previous" title="Previous Challenge">⇽</a>
            <a href="#next" title="Next Challenge">⇾</a>
            <a href="#close" title="Close">&times;</a>
        </div>
        <h3>Eat More Broccoli 3</h3>
    </div>
        <div class="dialog">
        <div>
            <span>1 of 1</span>
            <a href="#previous" title="Previous Challenge">⇽</a>
            <a href="#next" title="Next Challenge">⇾</a>
            <a href="#close" title="Close">&times;</a>
        </div>
        <h3>Eat More Broccoli 4</h3>
    </div>
</div>

CSS

body {
    background: #f7f7f7;
    font-family: 'Helvetica Neue', Arial, sans-serif;
}

ul {
    margin: 50px;
}

.challenge {
    background: #fff;
    border: 1px solid #ccc;
    color: #555;
    display: inline-block;
    margin-right: 14px;
    padding: 15px;
    height: 100px;
    width: 150px; 
    
    box-shadow: 0 1px 2px rgba(0, 0, 0, .07);
}

.challenge:hover {
    border: 1px solid #999;
    cursor: pointer;
}

#modal {
    background: transparent;
    display: block;
    height: 0;
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    overflow-x: auto;
    overflow-y: scroll;
    z-index: 0;
    
    -webkit-perspective: 1000;
}

#modal.show {
    height: auto;
    z-index: 9999;
    
    -moz-transform: translateZ(0);
    -webkit-transform: translateZ(0);
    transform: translateZ(0);
    
    -moz-transition: background 500ms ease-out 200ms;
    -webkit-transition: background 500ms ease-out 200ms;
    transition: background 500ms ease-out 200ms;
}

#modal .dialog {
    background: white;
    border: solid 1px #999;
    opacity: 1;
    padding: 15px;
    position: absolute;
    top: 0;
    left: 0;
    visibility: hidden;
    height: 100px;
    width: 150px;
    
    -moz-box-shadow: 0px 20px 60px rgba(0,0,0,.2);
    -webkit-box-shadow: 0px 20px 60px rgba(0,0,0,.2);
    box-shadow: 0px 20px 60px rgba(0,0,0,.2);
}

#modal.show .active {
    visibility: visible;
    height: 300px;
    width: 350px;
    
    -moz-transform: translateZ(0);
    -webkit-transform: translateZ(0);
    transform: translateZ(0);
    
    -moz-transition: all 200ms ease-out;
    -webkit-transition: all 200ms ease-out;
    transition: all 200ms ease-out;
}

#modal .dialog div {
    color: #999;
    font-size: 13px;
    line-height: 0;
    position: absolute;
    right: 13px;
    top: 16px;
}

#modal h3 {
    background: #fff;
}

.dialog div a {
    color: #0084ff;
    font-size: 18px;
    text-decoration: none;
}

.dialog div span {
    margin: 0 5px; ...

JavaScript

$(document).ready(function() {
    var modal = $('#modal'),
        dialogs = $('#modal .dialog'),
        close = dialogs.find('a[href="#close"]'),
        challenges = $('.challenge'),
        selectedChallenge = null,
        activeDialog = null;

    challenges.each(function() {
        var $this = $(this);
        $this.click(function() {
            selectedChallenge = $this;
            activeDialog = dialogs.eq($this.index());
            positionModal();
        
            setTimeout(function() {
                modal.addClass('show');
                activeDialog.addClass('active');
            }, 1);   
        });
    });
    
    close.click(closeModal);

    function closeModal() {
        modal.removeClass('show');
        activeDialog.removeClass('active');
    }
    
    function positionModal() {
        var xPos = selectedChallenge.offset().left,
            yPos = selectedChallenge.offset().top;
        
        activeDialog.css({
            left: xPos,
            top: yPos
        });
    }
    
    // keyboard left right arrow keys
    $(document).keydown(function(e) {
        if (e.keyCode == 37) {
            togglePrevChallenge();
            return false;
        } else if (e.keyCode == 39) {
            toggleNextChallenge();
            return false;
        }
    });
    
    $('a[href="#previous"]').click(togglePrevChallenge);
    $('a[href="#next"]').click(toggleNextChallenge);
    
    function togglePrevChallenge() {
        var prevChallenge = selectedChallenge.prev();
        if (prevChallenge.is('li')) {
            selectedChallenge = prevChallenge;
        } else {
            selectedChallenge = challenges.last();
        }
        
        activeDialog.removeClass('active');
        activeDialog = dialogs.eq(selectedChallenge.index());
        positionModal();
        
        setTimeout(function() {
            activeDialog.addClass('active');
        }, 1);   
    }
    
    function toggleNextChallenge() {
          ...