Skip to content

Commit 1469aae

Browse files
committed
Use some sort of multiple select component for Tag input
To improve UX and let user intuitively add multiple tags, this commit contains functionality that allows to add multiple tags by simply clicking Enter button Closes: #46
1 parent 375ac43 commit 1469aae

File tree

8 files changed

+83
-19
lines changed

8 files changed

+83
-19
lines changed

package-lock.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"react-dom": "^16.0.0",
3838
"react-redux": "^5.0.6",
3939
"react-router-dom": "^4.2.2",
40+
"react-tagging-input": "^2.1.2",
4041
"redux": "^3.7.2",
4142
"redux-immutable": "^4.0.0",
4243
"redux-thunk": "^2.2.0"

src/components/NewSnippet.jsx

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import React from 'react';
22
import { connect } from 'react-redux';
33
import { Controlled as CodeMirror } from 'react-codemirror2';
4+
import Tags from 'react-tagging-input';
45

56
import 'codemirror/lib/codemirror.css';
67

78
import Title from './common/Title';
8-
import Input from './common/Input';
99
import ListBoxWithSearch from './ListBoxWithSearch';
1010
import * as actions from '../actions';
1111

@@ -20,28 +20,35 @@ class NewSnippet extends React.Component {
2020
tags: [],
2121
syntax: '', // eslint-disable-line react/no-unused-state
2222
};
23+
this.onKeyPress = (e) => {
24+
if (e.which === 13) { e.preventDefault(); }
25+
};
2326
this.postSnippet = this.postSnippet.bind(this);
2427
this.onSyntaxClick = this.onSyntaxClick.bind(this);
2528
this.onInputChange = this.onInputChange.bind(this);
29+
this.onTagAdded = this.onTagAdded.bind(this);
30+
this.onTagRemoved = this.onTagRemoved.bind(this);
2631
}
2732

2833
componentDidMount() {
2934
const { dispatch } = this.props;
30-
3135
dispatch(actions.fetchSyntaxes);
3236
}
3337

38+
onTagAdded(tag) {
39+
this.setState({ tags: [...this.state.tags, tag] });
40+
}
41+
42+
onTagRemoved(tag) {
43+
this.setState({ tags: this.state.tags.filter(item => item !== tag) });
44+
}
45+
3446
onSyntaxClick(syntax) {
3547
this.setState({ syntax }); // eslint-disable-line react/no-unused-state
3648
}
3749

3850
onInputChange(e) {
39-
const { name } = e.target;
40-
let { value } = e.target;
41-
42-
if (name === 'tags') {
43-
value = value.split(',').map(item => item.trim());
44-
}
51+
const { name, value } = e.target;
4552

4653
this.setState({ [name]: value });
4754
}
@@ -56,20 +63,28 @@ class NewSnippet extends React.Component {
5663
return (
5764
[
5865
<Title title="New snippet" key="New Snippet Title" />,
59-
<form className="new-snippet" key="New Snippet" onSubmit={this.postSnippet}>
66+
<form
67+
className="new-snippet"
68+
key="New Snippet"
69+
onKeyPress={this.onKeyPress}
70+
onSubmit={this.postSnippet}
71+
role="presentation"
72+
>
6073
<div className="new-snippet-code-wrapper">
6174
<div className="new-snippet-code-header">
62-
<Input
75+
<input
76+
className="input"
6377
placeholder="Title"
6478
name="title"
65-
onChangeHandler={this.onInputChange}
79+
type="text"
6680
value={this.state.title}
81+
onChange={this.onInputChange}
6782
/>
68-
<Input
69-
placeholder="Tags (separate tags by comma)"
70-
name="tags"
71-
onChangeHandler={this.onInputChange}
72-
value={this.state.tags.toString()}
83+
<Tags
84+
tags={this.state.tags}
85+
placeholder="Tags"
86+
onAdded={this.onTagAdded}
87+
onRemoved={this.onTagRemoved}
7388
/>
7489
</div>
7590
<div className="new-snippet-code">

src/components/Snippet.jsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import codemirror from 'codemirror';
66
import 'codemirror/lib/codemirror.css';
77

88
import Title from './common/Title';
9-
import Input from './common/Input';
109
import Spinner from './common/Spinner';
1110
import * as actions from '../actions';
1211
import { downloadSnippet } from '../helpers';
@@ -70,7 +69,11 @@ class Snippet extends React.Component {
7069
In order to embed this content into your website or blog,
7170
simply copy and paste code provided below:
7271
</p>
73-
<Input value={`<script src='http://xsnippet.org/${snippet.get('id')}/embed/'></script>`} />
72+
<input
73+
className="input"
74+
type="text"
75+
defaultValue={`<script src='http://xsnippet.org/${snippet.get('id')}/embed/'></script>`}
76+
/>
7477
</div>
7578
<div className="snippet-code">
7679
<CodeMirror

src/styles/NewSnippet.styl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
@import './common/variables.styl'
22
@import './common/overwrite.styl'
3+
@import './common/mixins.styl'
34

45
lang-bar-width = 230px
56

@@ -17,6 +18,7 @@ lang-bar-width = 230px
1718
flex-flow: row nowrap
1819
height: offset
1920
min-height: offset
21+
align-items: flex-end
2022

2123
&-code
2224
flex: 1
@@ -29,6 +31,7 @@ lang-bar-width = 230px
2931
&-header
3032
background-color: snippet-header-light
3133
.input
34+
basic-input()
3235
width: 47%
3336
& > input
3437
margin-right: 5%
@@ -65,7 +68,7 @@ lang-bar-width = 230px
6568
&-header
6669
background-color: snippet-header-normal
6770
.input
68-
width: 100%
71+
basic-input()
6972
&-list
7073
height: 100%
7174
&-wrapper

src/styles/Snippet.styl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
@import './common/variables.styl'
2+
@import './common/mixins.styl'
23

34
.snippet
45
display: flex
@@ -52,6 +53,7 @@
5253
font-size: 14px
5354
padding-bottom: 10px
5455
& input
56+
basic-input()
5557
color: text-dark
5658
background-color: snippet-content-light
5759
padding: 4px 9px

src/styles/common/mixins.styl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
@import './common/variables.styl'
2+
3+
basic-input()
4+
width: 100%
5+
background-color: transparent
6+
border: none
7+
border-bottom: 1px solid rgba(text-light, .4)
8+
outline: none
9+
color: text-light
10+
font-size: 15px
11+
font-family: font-quicksand
12+
letter-spacing: -.3px
13+
&::placeholder
14+
color: rgba(text-light, .6)
15+
&:focus
16+
border-bottom: 1px solid text-light

src/styles/common/overwrite.styl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
@import './common/variables.styl'
2+
@import './common/mixins.styl'
23

34
.react-codemirror2,
45
.CodeMirror
@@ -26,3 +27,21 @@
2627
.snippet .CodeMirror-cursor {
2728
display: none !important
2829
}
30+
31+
.react-tags
32+
display: flex
33+
width: 47%
34+
input
35+
basic-input()
36+
.react-tags__container
37+
display: flex
38+
color: text-light
39+
li
40+
border: 1px solid rgba(text-light, .4)
41+
margin-right: 4px
42+
padding: 7px
43+
&:hover
44+
border-color: text-light
45+
a
46+
margin-left: 3px
47+
cursor: pointer

0 commit comments

Comments
 (0)