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.

CopyButton.js 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // @flow
  2. import React, { useState } from 'react';
  3. import { Icon, IconCheck, IconCopy } from '../../base/icons';
  4. import { translate } from '../i18n';
  5. import { copyText } from '../util';
  6. type Props = {
  7. /**
  8. * Css class to apply on container
  9. */
  10. className: string,
  11. /**
  12. * The displayed text
  13. */
  14. displayedText: string,
  15. /**
  16. * The text that needs to be copied (might differ from the displayedText)
  17. */
  18. textToCopy: string,
  19. /**
  20. * The text displayed on mouse hover
  21. */
  22. textOnHover: string,
  23. /**
  24. * The text displayed on copy success
  25. */
  26. textOnCopySuccess: string
  27. };
  28. /**
  29. * Component meant to enable users to copy the conference URL.
  30. *
  31. * @returns {React$Element<any>}
  32. */
  33. function CopyButton({ className, displayedText, textToCopy, textOnHover, textOnCopySuccess }: Props) {
  34. const [ isClicked, setIsClicked ] = useState(false);
  35. const [ isHovered, setIsHovered ] = useState(false);
  36. /**
  37. * Click handler for the element.
  38. *
  39. * @returns {void}
  40. */
  41. async function onClick() {
  42. setIsHovered(false);
  43. const isCopied = await copyText(textToCopy);
  44. if (isCopied) {
  45. setIsClicked(true);
  46. setTimeout(() => {
  47. setIsClicked(false);
  48. }, 2500);
  49. }
  50. }
  51. /**
  52. * Hover handler for the element.
  53. *
  54. * @returns {void}
  55. */
  56. function onHoverIn() {
  57. if (!isClicked) {
  58. setIsHovered(true);
  59. }
  60. }
  61. /**
  62. * Hover handler for the element.
  63. *
  64. * @returns {void}
  65. */
  66. function onHoverOut() {
  67. setIsHovered(false);
  68. }
  69. /**
  70. * Renders the content of the link based on the state.
  71. *
  72. * @returns {React$Element<any>}
  73. */
  74. function renderContent() {
  75. if (isClicked) {
  76. return (
  77. <>
  78. <div className = 'copy-button-content selected'>
  79. {textOnCopySuccess}
  80. </div>
  81. <Icon src = { IconCheck } />
  82. </>
  83. );
  84. }
  85. return (
  86. <>
  87. <div className = 'copy-button-content'>
  88. {isHovered ? textOnHover : displayedText}
  89. </div>
  90. <Icon src = { IconCopy } />
  91. </>
  92. );
  93. }
  94. return (
  95. <div
  96. className = { `${className} copy-button${isClicked ? ' clicked' : ''}` }
  97. onClick = { onClick }
  98. onMouseOut = { onHoverOut }
  99. onMouseOver = { onHoverIn }>
  100. { renderContent() }
  101. </div>
  102. );
  103. }
  104. CopyButton.defaultProps = {
  105. className: ''
  106. };
  107. export default translate(CopyButton);