You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TextWithOverflow.tsx 2.3KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import React, { ReactNode, useRef } from 'react';
  2. import { keyframes } from 'tss-react';
  3. import { makeStyles } from 'tss-react/mui';
  4. import { TEXT_OVERFLOW_TYPES } from '../../constants.web';
  5. interface ITextWithOverflowProps {
  6. children: ReactNode;
  7. className?: string;
  8. overflowType?: TEXT_OVERFLOW_TYPES;
  9. }
  10. const useStyles = makeStyles<{ translateDiff: number; }>()((_, { translateDiff }) => {
  11. return {
  12. animation: {
  13. '&:hover': {
  14. animation: `${keyframes`
  15. 0%, 20% {
  16. transform: translateX(0%);
  17. left: 0%;
  18. }
  19. 80%, 100% {
  20. transform: translateX(-${translateDiff}px);
  21. left: 100%;
  22. }
  23. `} ${Math.max(translateDiff * 50, 2000)}ms infinite alternate linear;`
  24. }
  25. },
  26. textContainer: {
  27. overflow: 'hidden'
  28. },
  29. [TEXT_OVERFLOW_TYPES.ELLIPSIS]: {
  30. display: 'block',
  31. overflow: 'hidden',
  32. textOverflow: 'ellipsis',
  33. whiteSpace: 'nowrap'
  34. },
  35. [TEXT_OVERFLOW_TYPES.SCROLL_ON_HOVER]: {
  36. display: 'inline-block',
  37. overflow: 'visible',
  38. whiteSpace: 'nowrap'
  39. }
  40. };
  41. });
  42. const TextWithOverflow = ({
  43. className,
  44. overflowType = TEXT_OVERFLOW_TYPES.ELLIPSIS,
  45. children
  46. }: ITextWithOverflowProps) => {
  47. const containerRef = useRef<HTMLDivElement>(null);
  48. const contentRef = useRef<HTMLSpanElement>(null);
  49. const shouldAnimateOnHover = overflowType === TEXT_OVERFLOW_TYPES.SCROLL_ON_HOVER
  50. && containerRef.current
  51. && contentRef.current
  52. && containerRef.current.clientWidth < contentRef.current.clientWidth;
  53. const translateDiff = shouldAnimateOnHover ? contentRef.current.clientWidth - containerRef.current.clientWidth : 0;
  54. const { classes: styles, cx } = useStyles({ translateDiff });
  55. return (
  56. <div
  57. className = { cx(className, styles.textContainer) }
  58. ref = { containerRef }>
  59. <span
  60. className = { cx(styles[overflowType], shouldAnimateOnHover && styles.animation) }
  61. ref = { contentRef }>
  62. {children}
  63. </span>
  64. </div>
  65. );
  66. };
  67. export default TextWithOverflow;