textarea.tsx 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. import {forwardRef} from 'react';
  2. import TextareaAutosize from 'react-autosize-textarea';
  3. import isPropValid from '@emotion/is-prop-valid';
  4. import styled from '@emotion/styled';
  5. import {inputStyles, InputStylesProps} from 'sentry/components/input';
  6. export interface TextAreaProps
  7. extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'css'>,
  8. InputStylesProps {
  9. /**
  10. * Enable autosizing of the textarea.
  11. */
  12. autosize?: boolean;
  13. /**
  14. * Max number of rows to default to.
  15. */
  16. maxRows?: number;
  17. /**
  18. * Number of rows to default to.
  19. */
  20. rows?: number;
  21. }
  22. const TextAreaControl = forwardRef(function TextAreaControl(
  23. {autosize, rows, maxRows, size: _size, ...p}: TextAreaProps,
  24. ref: React.Ref<HTMLTextAreaElement>
  25. ) {
  26. return autosize ? (
  27. <TextareaAutosize {...p} async ref={ref} rows={rows ? rows : 2} maxRows={maxRows} />
  28. ) : (
  29. <textarea ref={ref} {...p} />
  30. );
  31. });
  32. TextAreaControl.displayName = 'TextAreaControl';
  33. const TextArea = styled(TextAreaControl, {
  34. shouldForwardProp: (p: string) =>
  35. ['autosize', 'rows', 'maxRows'].includes(p) || isPropValid(p),
  36. })`
  37. ${inputStyles};
  38. line-height: ${p => p.theme.text.lineHeightBody};
  39. /** Allow react-autosize-textarea to freely control height based on props. */
  40. ${p =>
  41. p.autosize &&
  42. `
  43. height: unset;
  44. min-height: unset;
  45. `}
  46. `;
  47. export default TextArea;