<div id = "root">
body{
    background-color: #E2E2E2;
}

.tags-input{
    background-color: #FFF;
    border: 1px solid #ccc;
    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
    display: inline-block;
    padding: 4px 6px;
    color: #555;
    border-radius: 4px;
    line-height: 22px;
    cursor: text;
    width: 100%;
    max-width: 100%;
}

.tag{
    margin-right: 5px;
}

.text-input{
    border: none;
    box-shadow: none;
    outline: none;
    background-color: transparent;
    padding: 0 6px;
    margin: 0;
    max-width: inherit;
    display: inline-block;
}

.tag-remove::after{
    content: "x";
    opacity: 0.8;
    padding: 0px 2px;
    cursor: pointer;
    margin-left: 3.5px;
    transition: opacity linear 0.1s;
}

.tag-remove:hover:after{
    opacity: 1;
}

class TagInput extends React.Component{
    constructor(props){
        super(props);

        this.state = {
            tags: [],
            newTag: ''
        }

    } 

    componentDidMount(){
        this.setState({tags: this.props.tags});
    }

    removeTag = (index) => {
        let tags = this.state.tags;
        tags.splice(index,1);
        this.setState({ tags });
        this.props.onChange(this.state.tags);
    }
    
    onOutsideClickAdd = () => {
        if (this.state.newTag.trim().length){
            const tags = this.state.tags;
            tags.push(this.state.newTag);
            this.setState({tags, newTag: ''});
            this.props.onChange(this.state.tags);
        }
    }

    handleTag = (e) => {
        const target = e.target;
        e.keyCode === 13 && e.preventDefault();
        if (e.keyCode === 13 && target.value && target.value.trim().length){
            const tags = this.state.tags;
            tags.push(target.value);
            this.setState({tags, newTag: ''});
            this.props.onChange(this.state.tags);
        }

        if(target.value.length > 6){ 
            target.size++;
        }
    }

    render(){
        return(
                <div className="tags-input">
                {this.state.tags.map((tag,index) => {
                    return (
                        <span key={index} className="tag mr-1 mb-1 badge bg-primary">
                            {tag} <span className="tag-remove" onClick={() => this.removeTag(index)}></span>
                        </span>
                    )})
                }
                <input value={this.state.newTag} onChange={(e) => this.setState({newTag: e.target.value})} type="text" size="7" placeholder="New Tag" className="text-input" onKeyDown={e => this.handleTag(e)} />
            </div>
            
        );
    }
}

TagInput.defaultProps = {onChange: ((tags)=> console.log(tags)),
    tags: []}

class App extends React.Component{
    render(){
        return(
            <div style={{width: "70%", margin: "40px auto"}}>
                <TagInput />
            </div>
        );
    }
    
}

ReactDOM.render(<App />, document.getElementById('root')); 
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js