Creating a Button

Let’s say you found a really neat button up on CodePen and you want to embed it in your interactive video (note about licensing).

As an example we’ll use these fancy buttons by David Conner:

Create the component

We’ll start by creating our button component file:

FancyButton.jsx (ver 1)

import EkoUIComponents from 'EkoUIComponents';

export default class MyButton extends EkoUIComponents.EkoButton {
}

We need our component to have its own markup structure, just like in the Codepen, and for that we can override EkoButton‘s getContent method.

Notice that we’ve made some minor changes to the original markup - we’ve changed the <a> tag to a <button> tag and stripped the HREF attribute. This is to maintain markup semantics, since this component is going to be used as a button and not as a link. We’ve also changed the class attribute to className, because that’s how things roll in the world of React.

FancyButton.jsx - (ver 2)

import EkoUIComponents from 'EkoUIComponents';

export default class FancyButton extends EkoUIComponents.EkoButton {
    getContent() {
        return (
            <button className="btn btn-4">
                <span>Fancy Button</span>
            </button>
            );
    }
}

Pour in the design

The design of this button is entirely CSS based, or to be more precise, SASS based. In any case - no JS needed! Let’s grab the proper CSS code for the hover animation and put it in it’s own file.

We added background: none; to style definition to override some defaults that might affect visibility caused by changing the <a> tag to the <button> tag.

FancyButton.scss (ver 1)

.btn {
    color: #fff;
    cursor: pointer;
    font-size:16px;
    font-weight: 400;
    line-height: 45px;
    margin: 0 0 2em;
    max-width: 160px;
    position: relative;
    text-decoration: none;
    text-transform: uppercase;
    width: 100%;
    background: none;

    &:hover { text-decoration: none; }
}

.btn-4 {
    border: 1px solid;
    overflow: hidden;
    position: relative;

    span {
        z-index: 20;
    }

    &:after {
        background: #fff;
        content: "";
        height: 155px;
        left: -75px;
        opacity: .2;
        position: absolute;
        top: -50px;
        transform: rotate(35deg);
        transition: all 550ms cubic-bezier(0.19, 1, 0.22, 1);
        width: 50px;
        z-index: -10;
    }
}

.btn-4:hover {
    &:after {
        left: 120%;
        transition: all 550ms cubic-bezier(0.19, 1, 0.22, 1);
    }
}

Now we need to import this file into our FancyButton.jsx component:

FancyButton.jsx - (ver 3)

 import EkoUIComponents from 'EkoUIComponents';
 import './FancyButton.scss';

 export default class FancyButton extends EkoUIComponents.EkoButton {
     getContent() {
         return (
            <button className="btn btn-4">
                <span>Fancy Button</span>
            </button>
            );
     }
 }

Add more state visualisation

So far our button only has an idle state and a hover state. If your button is used to reflect a decision, it’s important to reflect the decision state visually. For example, we want the button to show when the decision associated with it was selected, or perhaps when a different option was selected.

A good way to go about it is to alter which className is present in the DOM based on the decision state. For example, we will use the class selected when the node associated with the button is selected, and notSelected when any other node was selected for this decision. Let’s add this logic to our button class:

FancyButton.jsx - (ver 4)

 import EkoUIComponents from 'EkoUIComponents';
 import './FancyButton.scss';

 export default class FancyButton extends EkoUIComponents.EkoButton {
     getContent() {
         let uiController = this.props.globalState.ui.controllers[this.props.config.stateSourceId];
         let selectedNodeId = uiController.selected.nodeId;
         let buttonClasses = 'btn btn-4 ';

         if (selectedNodeId) {
            if (selectedNodeId === this.getDecisionNodeId()) {
                buttonClasses += 'selected';
            }
            else {
                buttonClasses += 'notSelected';
            }
         }
         return (
            <button className={buttonClasses}>
                <span>Fancy Button</span>
            </button>
            );
     }
 }

The code above starts by first creating a reference to the uiController associated with this button’s decision. The uiController is what holds all the the up-to-date information on the state of the decision.

It then pulls out the nodeId of the selected decision. The if tree that follows takes care of the three possible decision states: Either no decision has been made yet, a decision had been made which corresponds to this button’s node, or a decision has been made which doesn’t correspond with this button’s node.
In the two latter cases, the proper CSS class (selected/notSelected) will automagically be added to the DOM by React.

We only need to add some styling in our SASS file to reflect this:

FancyButton.scss (ver 2)

.btn {
    color: #fff;
    cursor: pointer;
    font-size:16px;
    font-weight: 400;
    line-height: 45px;
    margin: 0 0 2em;
    max-width: 160px;
    position: relative;
    text-decoration: none;
    text-transform: uppercase;
    width: 100%;
    background: none;

    &:hover { text-decoration: none; }
}

.btn-4 {
    border: 1px solid;
    overflow: hidden;
    position: relative;

    span {
        z-index: 20;
    }

    &:after {
        background: #fff;
        content: "";
        height: 155px;
        left: -75px;
        opacity: .2;
        position: absolute;
        top: -50px;
        transform: rotate(35deg);
        transition: all 550ms cubic-bezier(0.19, 1, 0.22, 1);
        width: 50px;
        z-index: -10;
    }
}

.btn-4:hover {
    &:after {
        left: 120%;
        transition: all 550ms cubic-bezier(0.19, 1, 0.22, 1);
    }
}

.btn-4.selected{
    background: rgba(200, 0, 28, 0.5);
}

.btn-4.notSelected{
    opacity: 0.5;
}

Use the button

Now we have a working custom button. Let’s replace one of the existing buttons generated by Eko Studio with our custom button.

First we locate our button in Eko Studio, right click and select “get element id”.

Then in our app.js, we use the ui plugin’s ui.override method to replace the original button with our new button class:

App.js

import FancyButton from './FancyButton';

export default function onInit(player, ctx) {
    player.ui.override('button_start_dc8404', FancyButton);
}

Voila! Your project now includes a custom button. You can of course continue extending and customizing your own buttons/UI components however you see fit with web technologies.

Regarding licenses

Take proper care with licenses. Make sure you have permission to use shared code from the Internet, and provide attribution when required. More about Codepen licensing here

Rate this page: X
Tell us more!