Selaa lähdekoodia

ui: create reusable copy button

j8
Tudor-Ovidiu Avram 4 vuotta sitten
vanhempi
commit
0fc748dc44

+ 37
- 0
css/buttons/copy.scss Näytä tiedosto

@@ -0,0 +1,37 @@
1
+.copy-button {
2
+    display: flex;
3
+    justify-content: space-between;
4
+    align-items: center;
5
+    padding: 8px 8px 8px 16px;
6
+    margin-top: 8px;
7
+    width: calc(100% - 24px);
8
+    height: 24px;
9
+
10
+    background: #0376DA;
11
+    border-radius: 4px;
12
+    cursor: pointer;
13
+
14
+    &:hover {
15
+        background: #278ADF;
16
+        font-weight: 600;
17
+    }
18
+
19
+    &-content {
20
+        overflow: hidden;
21
+        text-overflow: ellipsis;
22
+        white-space: nowrap;
23
+        max-width: 292px;
24
+
25
+        &.selected {
26
+            font-weight: 600;
27
+        }
28
+    }
29
+
30
+    &.clicked {
31
+        background: #31B76A;
32
+    }
33
+
34
+    & > div > svg > path {
35
+        fill: #fff;
36
+    }
37
+}

+ 1
- 0
css/main.scss Näytä tiedosto

@@ -33,6 +33,7 @@ $flagsImagePath: "../images/";
33 33
 @import 'inlay';
34 34
 @import 'reload_overlay/reload_overlay';
35 35
 @import 'mini_toolbox';
36
+@import 'buttons/copy.scss';
36 37
 @import 'modals/desktop-picker/desktop-picker';
37 38
 @import 'modals/device-selection/device-selection';
38 39
 @import 'modals/dialog';

+ 0
- 38
css/modals/invite/_invite_more.scss Näytä tiedosto

@@ -67,44 +67,6 @@
67 67
             }
68 68
         }
69 69
 
70
-        &.copy-link {
71
-            display: flex;
72
-            justify-content: space-between;
73
-            align-items: center;
74
-            padding: 8px 8px 8px 16px;
75
-            margin-top: 8px;
76
-            width: calc(100% - 24px);
77
-            height: 24px;
78
-
79
-            background: #0376DA;
80
-            border-radius: 4px;
81
-            cursor: pointer;
82
-
83
-            &:hover {
84
-                background: #278ADF;
85
-                font-weight: 600;
86
-            }
87
-
88
-            &-text {
89
-                overflow: hidden;
90
-                text-overflow: ellipsis;
91
-                white-space: nowrap;
92
-                max-width: 292px;
93
-
94
-                &.selected {
95
-                    font-weight: 600;
96
-                }
97
-            }
98
-
99
-            &.clicked {
100
-                background: #31B76A;
101
-            }
102
-
103
-            & > div > svg > path {
104
-                fill: #fff;
105
-            }
106
-        }
107
-
108 70
         &.separator {
109 71
             margin: 24px 0 24px -20px;
110 72
             padding: 0 20px;

+ 125
- 0
react/features/base/buttons/CopyButton.js Näytä tiedosto

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

+ 9
- 78
react/features/invite/components/add-people-dialog/web/CopyMeetingLinkSection.js Näytä tiedosto

@@ -1,10 +1,10 @@
1 1
 // @flow
2 2
 
3
-import React, { useState } from 'react';
3
+import React from 'react';
4 4
 
5
+import CopyButton from '../../../../base/buttons/CopyButton';
5 6
 import { translate } from '../../../../base/i18n';
6
-import { Icon, IconCheck, IconCopy } from '../../../../base/icons';
7
-import { copyText, getDecodedURI } from '../../../../base/util';
7
+import { getDecodedURI } from '../../../../base/util';
8 8
 
9 9
 
10 10
 type Props = {
@@ -26,84 +26,15 @@ type Props = {
26 26
  * @returns {React$Element<any>}
27 27
  */
28 28
 function CopyMeetingLinkSection({ t, url }: Props) {
29
-    const [ isClicked, setIsClicked ] = useState(false);
30
-    const [ isHovered, setIsHovered ] = useState(false);
31
-
32
-    /**
33
-     * Click handler for the element.
34
-     *
35
-     * @returns {void}
36
-     */
37
-    function onClick() {
38
-        setIsHovered(false);
39
-        if (copyText(url)) {
40
-            setIsClicked(true);
41
-
42
-            setTimeout(() => {
43
-                setIsClicked(false);
44
-            }, 2500);
45
-        }
46
-    }
47
-
48
-    /**
49
-     * Hover handler for the element.
50
-     *
51
-     * @returns {void}
52
-     */
53
-    function onHoverIn() {
54
-        if (!isClicked) {
55
-            setIsHovered(true);
56
-        }
57
-    }
58
-
59
-    /**
60
-     * Hover handler for the element.
61
-     *
62
-     * @returns {void}
63
-     */
64
-    function onHoverOut() {
65
-        setIsHovered(false);
66
-    }
67
-
68
-    /**
69
-     * Renders the content of the link based on the state.
70
-     *
71
-     * @returns {React$Element<any>}
72
-     */
73
-    function renderLinkContent() {
74
-        if (isClicked) {
75
-            return (
76
-                <>
77
-                    <div className = 'invite-more-dialog copy-link-text selected'>
78
-                        {t('addPeople.linkCopied')}
79
-                    </div>
80
-                    <Icon src = { IconCheck } />
81
-                </>
82
-            );
83
-        }
84
-
85
-        const displayUrl = getDecodedURI(url);
86
-
87
-        return (
88
-            <>
89
-                <div className = 'invite-more-dialog invite-more-dialog-conference-url copy-link-text'>
90
-                    {isHovered ? t('addPeople.copyLink') : displayUrl}
91
-                </div>
92
-                <Icon src = { IconCopy } />
93
-            </>
94
-        );
95
-    }
96
-
97 29
     return (
98 30
         <>
99 31
             <span>{t('addPeople.shareLink')}</span>
100
-            <div
101
-                className = { `invite-more-dialog copy-link${isClicked ? ' clicked' : ''}` }
102
-                onClick = { onClick }
103
-                onMouseOut = { onHoverOut }
104
-                onMouseOver = { onHoverIn }>
105
-                { renderLinkContent() }
106
-            </div>
32
+            <CopyButton
33
+                className = 'invite-more-dialog-conference-url'
34
+                displayedText = { getDecodedURI(url) }
35
+                textOnCopySuccess = { t('addPeople.linkCopied') }
36
+                textOnHover = { t('addPeople.copyLink') }
37
+                textToCopy = { url } />
107 38
         </>
108 39
     );
109 40
 }

Loading…
Peruuta
Tallenna