JSFiddle - React, Tailwind, and code Playground

HTML

<a href="javascript:alert('clicked');" class="button">RIPPLE BUTTON</a>

CSS

a.button {
	display: inline-block;
	padding: 6px 12px;
	margin: 2px;
	line-height: 30px;
	border-radius: 6px;
	-webkit-border-radius: 6px;
	-o-border-radius: 6px;
	-moz-border-radius: 6px;
	border-width: 1px;
	border-style: solid;
	text-decoration: none;
	font-family: Roboto,sans-serif;
	font-size: 12px;
	color: #000;
	text-shadow: 0 1px 0 rgba(255,255,255,0.09);
	text-decoration: none !important;
	cursor: pointer;
	outline: none;
	background-color: #D2D2D2;
	border-color: #D2D2D2;
	background-image: -webkit-gradient(
		linear,
		left top,
		left bottom,
		color-stop(0, #D2D2D2),
		color-stop(0.5, #E4E4E4),
		color-stop(0.5, #EDEDED),
		color-stop(1, #FFFFFF)
	);
	background-image: -webkit-linear-gradient(
		center top,
		#D2D2D2 0%,
		#E4E4E4 50%,
		#EDEDED 50%,
		#FFFFFF 100%
	);
	background-image: -moz-linear-gradient(
		center top,
		#D2D2D2 0%,
		#E4E4E4 50%,
		#EDEDED 50%,
		#FFFFFF 100%
	);
	background-image: -o-linear-gradient(
		center top,
		#D2D2D2 0%,
		#E4E4E4 50%,
		#EDEDED 50%,
		#FFFFFF 100%
	);
	background-image: -ms-linear-gradient(
		center top,
		#D2D2D2 0%,
		#E4E4E4 50%,
		#EDEDED 50%,
		#FFFFFF 100%
	);
	background-image: linear-gradient(
		to top,
		#D2D2D2 0%,
		#E4E4E4 50%,
		#EDEDED 50%,
		#FFFFFF 100%
	);	
}
a.button:hover {
	background-color: #4488ee;
	border-color: #4488ee;
	background-image: -webkit-gradient(
		linear,
		left top,
		left bottom,
		color-stop(0, #4488ee),
		color-stop(0.5, #5590ee),
		color-stop(0.5, #77a2ff),
		color-stop(1, #88aaff)
		);
	background-image: -webkit-linear-gradient(
		center top,
		#4488ee 0%,
		#5590ee 50%,
		#77a2ff 50%,
		#88aaff 100%
		);
	background-image: -moz-linear-gradient(
		center top,
		#4488ee 0%,
		#5590ee 50%,
		#77a2ff 50%,
		#88aaff 100%
		);
	background-image: -o-linear-gradient(
		center top,
		#4488ee 0%,
		#5590ee 50%,
		#77a2ff 50%,
		#88aaff 100%
		);
	background-image: -ms-linear-gradient(
		center top,
		#4488ee 0%,
		#5590ee 50%,
		#77a2ff 50%,
		#88aaff...

JavaScript

/*!
 * jQuery Color Animations v@VERSION
 * https://github.com/jquery/jquery-color
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * Date: @DATE
 */
(function( jQuery, undefined ) {

	var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",

	// plusequals test for += 100 -= 100
	rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
	// a set of RE's that can match strings and generate color tuples.
	stringParsers = [{
			re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
			parse: function( execResult ) {
				return [
					execResult[ 1 ],
					execResult[ 2 ],
					execResult[ 3 ],
					execResult[ 4 ]
				];
			}
		}, {
			re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
			parse: function( execResult ) {
				return [
					execResult[ 1 ] * 2.55,
					execResult[ 2 ] * 2.55,
					execResult[ 3 ] * 2.55,
					execResult[ 4 ]
				];
			}
		}, {
			// this regex ignores A-F because it's compared against an already lowercased string
			re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
			parse: function( execResult ) {
				return [
					parseInt( execResult[ 1 ], 16 ),
					parseInt( execResult[ 2 ], 16 ),
					parseInt( execResult[ 3 ], 16 )
				];
			}
		}, {
			// this regex ignores A-F because it's compared against an already lowercased string
			re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
			parse: function( execResult ) {
				return [
					parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
					parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
					parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
				];
			}
		}, {
			re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
			space: "hsla",
			parse: function( execResult...