CommentInput.tsx

  1import React, { useState, useEffect } from 'react';
  2
  3import Tab from '@material-ui/core/Tab';
  4import Tabs from '@material-ui/core/Tabs';
  5import TextField from '@material-ui/core/TextField';
  6import { makeStyles } from '@material-ui/core/styles';
  7
  8import Content from '../Content';
  9
 10/**
 11 * Styles
 12 */
 13const useStyles = makeStyles((theme) => ({
 14  container: {
 15    margin: theme.spacing(2, 0),
 16    padding: theme.spacing(0, 2, 2, 2),
 17  },
 18  textarea: {},
 19  tabContent: {
 20    margin: theme.spacing(2, 0),
 21  },
 22  preview: {
 23    overflow: 'auto',
 24    borderBottom: `solid 3px ${theme.palette.grey['200']}`,
 25    minHeight: '5rem',
 26  },
 27}));
 28
 29type TabPanelProps = {
 30  children: React.ReactNode;
 31  value: number;
 32  index: number;
 33} & React.HTMLProps<HTMLDivElement>;
 34function TabPanel({ children, value, index, ...props }: TabPanelProps) {
 35  return (
 36    <div
 37      role="tabpanel"
 38      hidden={value !== index}
 39      id={`editor-tabpanel-${index}`}
 40      aria-labelledby={`editor-tab-${index}`}
 41      {...props}
 42    >
 43      {value === index && children}
 44    </div>
 45  );
 46}
 47
 48const a11yProps = (index: number) => ({
 49  id: `editor-tab-${index}`,
 50  'aria-controls': `editor-tabpanel-${index}`,
 51});
 52
 53type Props = {
 54  inputProps?: any;
 55  inputText?: string;
 56  loading: boolean;
 57  onChange: (comment: string) => void;
 58};
 59
 60/**
 61 * Component for issue comment input
 62 *
 63 * @param inputProps Reset input value
 64 * @param loading Disable input when component not ready yet
 65 * @param onChange Callback to return input value changes
 66 */
 67function CommentInput({ inputProps, inputText, loading, onChange }: Props) {
 68  const [input, setInput] = useState<string>(inputText ? inputText : '');
 69  const [tab, setTab] = useState(0);
 70  const classes = useStyles();
 71
 72  useEffect(() => {
 73    if (inputProps) setInput(inputProps.value);
 74  }, [inputProps]);
 75
 76  useEffect(() => {
 77    onChange(input);
 78  }, [input, onChange]);
 79
 80  return (
 81    <div>
 82      <Tabs value={tab} onChange={(_, t) => setTab(t)}>
 83        <Tab label="Write" {...a11yProps(0)} />
 84        <Tab label="Preview" {...a11yProps(1)} />
 85      </Tabs>
 86      <div className={classes.tabContent}>
 87        <TabPanel value={tab} index={0}>
 88          <TextField
 89            fullWidth
 90            label="Comment"
 91            placeholder="Leave a comment"
 92            className={classes.textarea}
 93            multiline
 94            value={input}
 95            variant="filled"
 96            rows="4" // TODO: rowsMin support
 97            onChange={(e: any) => setInput(e.target.value)}
 98            disabled={loading}
 99          />
100        </TabPanel>
101        <TabPanel value={tab} index={1} className={classes.preview}>
102          <Content markdown={input} />
103        </TabPanel>
104      </div>
105    </div>
106  );
107}
108
109export default CommentInput;