JSFiddle - React, Tailwind, and code Playground

by Mike McCaughan

HTML

<input type="time" />
<div class="shadow-dom">
    <input type="text" value="--:-- --"/>
    <div class="spinner">
        <button class="spin-up">&#9652;</button>
        <button class="spin-down">&#9662;</button>
    </div>
</div>
<input type="time" class="do-not-touch"/>

CSS

.shadow-dom, .time-picker { display: inline-block; position: relative; }
.shadow-dom input, .time-picker input { width: 60px; }
.shadow-dom .spinner, .time-picker .spinner { position: absolute; height: 19px; width: 22px; top: 0; right: 0; }
.shadow-dom .spinner button, .time-picker .spinner button { position: absolute; width: 22px; height: 11px; margin: 0; padding: 0; line-height: 0; }
.shadow-dom .spinner .spin-up, .time-picker .spinner .spin-up { top: 0; right: 0; }
.shadow-dom .spinner .spin-down, .time-picker .spinner .spin-down { bottom: -2px; right: 0; }

JavaScript

/*!
 * jQuery lightweight plugin boilerplate
 * Original author: @ajpiano
 * Further changes, comments: @addyosmani
 * Licensed under the MIT license
 */

// the semi-colon before the function invocation is a safety
// net against concatenated scripts and/or other plugins
// that are not closed properly.
;(function ( $, window, document, undefined ) {

    // undefined is used here as the undefined global
    // variable in ECMAScript 3 and is mutable (i.e. it can
    // be changed by someone else). undefined isn't really
    // being passed in so we can ensure that its value is
    // truly undefined. In ES5, undefined can no longer be
    // modified.

    // window and document are passed through as local
    // variables rather than as globals, because this (slightly)
    // quickens the resolution process and can be more
    // efficiently minified (especially when both are
    // regularly referenced in your plugin).

    // Create the defaults once
    var pluginName = "timePicker",
        defaults = {
            mode: "12",
            valueMode: "24",
            minTime: 8,
            maxTime: 20
        };

    // The actual plugin constructor
    function Plugin( element, options ) {
        this.element = element;

        // jQuery has an extend method that merges the
        // contents of two or more objects, storing the
        // result in the first object. The first object
        // is generally empty because we don't want to alter
        // the default options for future instances of the plugin
        this.options = $.extend( {}, defaults, options) ;

        this._defaults = defaults;
        this._name = pluginName;

        this.init();
    }

    Plugin.prototype = {

        init: function() {
            // Place initialization logic here
            // You already have access to the DOM element and
            // the options via the instance, e.g. this.element
            // and this.options
            // you can add more...