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