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