JSFiddle - React, Tailwind, and code Playground

HTML

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-tokenfield/0.12.0/css/bootstrap-tokenfield.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/typeahead.js/0.11.1/typeahead.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Caret.js/0.3.1/jquery.caret.min.js"></script>
<body>

	<div class="outerbox">
		<input id="textbox" class="typeahead" type="text" placeholder="Enter a color"/>
	</div>

	<div class="outerbox">
		<textarea id="textarea" class="typeahead" placeholder="Type @ to trigger color lookup"></textarea>
	</div>

</body>

CSS

body
{
    min-width: 400px;
	padding: 2em;
}

.typeahead,
.tt-query,
.tt-hint {
  width: 396px;
  height: 30px;
  padding: 8px 12px;
  font-size: 24px;
  line-height: 30px;
  border: 2px solid #ccc;
  -webkit-border-radius: 8px;
     -moz-border-radius: 8px;
          border-radius: 8px;
  outline: none;
  height: 2em;
}

.typeahead {
  background-color: #fff;
}

.typeahead:focus {
  border: 2px solid #0097cf;
}

.tt-query {
  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
}

.tt-hint {
  color: #999
}

.tt-menu {
  /*width: 422px;*/
  width: auto;
  margin: 12px 0;
  padding: 8px 0;
  background-color: #fff;
  border: 1px solid #ccc;
  border: 1px solid rgba(0, 0, 0, 0.2);
  -webkit-border-radius: 8px;
     -moz-border-radius: 8px;
          border-radius: 8px;
  -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
     -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
          box-shadow: 0 5px 10px rgba(0,0,0,.2);
}

.tt-suggestion {
  padding: 3px 20px;
  font-size: 18px;
  line-height: 24px;
}

.tt-suggestion:hover {
  cursor: pointer;
  color: #fff;
  background-color: #0097cf;
}

.tt-suggestion.tt-cursor {
  color: #fff;
  background-color: #0097cf;

}

.tt-suggestion p {
  margin: 0;
}

.gist {
  font-size: 14px;
}

.twitter-typeahead, .tt-hint, .tt-input 
{ 
	width: 100%; 
} 

.tt-menu 
{
	width: auto;
}

.outerbox
{
	border: 2px dashed #ccc;
	padding: 1em;
	margin: 1em;
}

#textarea
{
	height: 300px;
}

JavaScript

function MultiTypeahead(id, data, trigger, vertAdjustMenu)
	{
		trigger = (undefined !== trigger) ? trigger : '';
		var validChars = /^[a-zA-Z]+$/;

		
		function extractor(query)
		{
			var result = (new RegExp('([^,; \r\n]+)$')).exec(query);
			if(result && result[1])
				return result[1].trim();
			return '';
		}

		var lastUpper = false;
		function strMatcher(id, strs) 
		{
		  	return function findMatches(q, sync, async) 
			{
				var pos = $(id).caret('pos');
				q = (0 < pos) ? extractor(q.substring(0, pos)) : '';

				if (q.length <= trigger.length)
					return;

				if (trigger.length)
				{
					if(trigger != q.substr(0, trigger.length))
						return;
					
					q = q.substr(trigger.length);
				}

				if (!q.match(validChars))
					return;

				var firstChar = q.substr(0, 1);
				lastUpper = (firstChar === firstChar.toUpperCase() && firstChar !== firstChar.toLowerCase());
	
				var cpos = $(id).caret('position');
				$(id).parent().find('.tt-menu').css('left', cpos.left + 'px');
				if (vertAdjustMenu)
					$(id).parent().find('.tt-menu').css('top', (cpos.top + cpos.height) + 'px');

				var matches = [];
				var matches = [], substrRegex = new RegExp(q, 'i');
				$.each(strs, function(i, str) 
				{
					if (str.length > q.length && substrRegex.test(str))
						matches.push(str);
				});
			
				if (!matches.length)
					return;
			
				sync(matches);
		  	};
		};

		var lastVal = '';
		var lastPos = 0;
		function beforeReplace(event, data)
		{
			lastVal = $(id).val();
			lastPos = $(id).caret('pos');
			return true;
		}

		function onReplace(event, data)
		{            
			if (!data || !data.length)
				return;

			if (!lastVal.length)
				return;

			var root = lastVal.substr(0, lastPos);
			var post = lastVal.substr(lastPos);

			var typed = extractor(root);
			if (!lastUpper && typed.length >= root.length && 0 >= post.length)
				return;

			var str = root.substr(0, root.length - typed.length);
	
			str += lastUpper ? (data.substr(0,...