ソースを参照

Create TagInput component

Tatiana Inama 7 年 前
コミット
217c9d7fda

+ 2 - 0
recipes/package.json

@@ -5,9 +5,11 @@
   "dependencies": {
     "@material/react-button": "^0.11.0",
     "@material/react-card": "^0.11.0",
+    "@material/react-chips": "^0.12.0",
     "@material/react-drawer": "^0.11.0",
     "@material/react-layout-grid": "^0.11.0",
     "@material/react-list": "^0.11.0",
+    "@material/react-material-icon": "^0.12.0",
     "@material/react-text-field": "^0.11.0",
     "@types/jest": "^24.0.11",
     "@types/node": "^11.13.0",

+ 1 - 0
recipes/public/index.html

@@ -26,6 +26,7 @@
     <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500">
     <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lekton">
     <link rel="stylesheet" href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css">
+    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
   </head>
   <body>
     <noscript>You need to enable JavaScript to run this app.</noscript>

BIN
recipes/recipes-design.xd


+ 3 - 2
recipes/src/components/Input/index.tsx

@@ -10,19 +10,20 @@ type InputProps = {
 	value: string|number,
 	onChange: (e: any) => void,
 	textarea?: boolean,
+	onKeyDown? : (e: any) => void,
 };
 
 const Input = (props: InputProps) => (
 	<TextField
 		label={props.label}
-		helperText={<HelperText>{props.helperText || ''}</HelperText>}
-		style={{ width: '100%' }}
+		helperText={props.helperText ? (<HelperText>{props.helperText || ''}</HelperText>) : undefined}
 		textarea={props.textarea}
 	>
 		<Field
 			value={props.value}
 			//@ts-ignore
 			onChange={props.onChange}
+			onKeyDown={props.onKeyDown}
 		/>
 	</TextField>
 );

+ 3 - 0
recipes/src/components/Input/styles.scss

@@ -0,0 +1,3 @@
+.mdc-text-field {
+  width: 100%;
+}

+ 82 - 0
recipes/src/components/TagInput/index.tsx

@@ -0,0 +1,82 @@
+
+import React, { Component } from 'react';
+import { ChipSet, Chip } from '@material/react-chips';
+import MaterialIcon from '@material/react-material-icon';
+import Input from 'components/Input';
+
+import './styles.scss';
+
+interface Tag {
+  label?: string,
+  id?: string
+};
+
+type TagInputProps = {
+  onNewTag: (tags: string[]) => void,
+  initialValues?: string[],
+  label?: string,
+}
+
+type TagInputState = {
+  tags: Tag[],
+  newTag: string,
+}
+
+class TagInput extends Component<TagInputProps, TagInputState> {
+  
+  constructor(props: TagInputProps) {
+    super(props);
+    this.state = {
+      tags: [],
+      newTag: '',
+    }
+  }
+  
+  mkTag = (tagLike: string): Tag => ({
+    label: tagLike,
+    id: tagLike.replace(/\s/g,''),
+  })
+
+  updateTags = (newTags: Tag[]) => {
+    this.setState({
+      tags: newTags,
+      newTag: '',
+    });
+    this.props.onNewTag(newTags.map(t => t.label||''))
+  }
+
+  handleKeyDown = (e: any) => {
+    const label = e.target.value;
+    if (!!label && e.key === 'Enter') {
+      this.updateTags(this.state.tags.concat([this.mkTag(label)]))
+    }
+  }
+
+  render() {
+    return (
+      <div className="cbk-tag-input">
+        <Input
+          value={this.state.newTag}
+          label={this.props.label || 'Tags'}
+          onChange={(e) => this.setState({newTag: e.currentTarget.value})}
+          onKeyDown={this.handleKeyDown}
+        />
+        <ChipSet
+          input
+          updateChips={this.updateTags}
+        >
+          {this.state.tags.map((tag: any) =>
+            <Chip
+              id={tag.id}
+              key={tag.id}
+              label={tag.label}
+              trailingIcon={<MaterialIcon icon='cancel' />}
+            />
+          )}
+        </ChipSet>
+      </div>
+    );
+  }
+}
+
+export default TagInput;

+ 9 - 0
recipes/src/components/TagInput/styles.scss

@@ -0,0 +1,9 @@
+.cbk-tag-input {
+  display: flex;
+  flex-direction: row;
+  
+  .mdc-text-field {
+    grid-column-end: span 3;
+    width: auto!important;
+  }
+}

+ 8 - 4
recipes/src/containers/Recipes/Create.tsx

@@ -3,6 +3,8 @@ import  Navbar from 'components/Navbar';
 import { Grid, Row, Cell } from '@material/react-layout-grid';
 
 import Input from 'components/Input';
+import TagInput from 'components/TagInput';
+
 import './styles.scss';
 
 import sample_img from "../../sample.png";
@@ -120,13 +122,15 @@ class CreateRecipe extends React.Component<CreateRecipeProps, CreateRecipeState>
                 />
               </Cell>
               <Cell columns={3}>
-                <Input
-                  label='Tags'
-                  value={this.state.form.preparationTime}
-                  onChange={this.updateField('preparationTime')}
+              </Cell>
+              <Cell columns={12}>
+                <TagInput
+                  onNewTag={(tag) => { console.log(tag) }}
                 />
               </Cell>
             </Row>
+            <Row>
+            </Row>
           </Grid>
         </div>