CommentInput.tsx

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