21
21
:fileType =" fileType"
22
22
>{{ fileName }}
23
23
</Filename >
24
- <div class =" container-general" >
24
+ <div class =" container-general" ref = " scrollContainer " >
25
25
<button
26
+ v-show =" showCopyButton"
26
27
class =" copy-button"
27
- :class =" { copied: isCopied }"
28
+ ref =" copyButton"
29
+ :class =" { copied: isCopied, visible: buttonPositioned }"
28
30
@click =" copyToClipboard"
31
+ @update =" handleScroll"
29
32
aria-label =" Copy code to clipboard"
30
33
>
31
34
<svg
68
71
</template >
69
72
70
73
<script >
74
+ import debounce from ' docc-render/utils/debounce' ;
71
75
import { escapeHtml } from ' docc-render/utils/strings' ;
72
76
import Language from ' docc-render/constants/Language' ;
73
77
import CodeBlock from ' docc-render/components/CodeBlock.vue' ;
@@ -82,8 +86,20 @@ export default {
82
86
return {
83
87
syntaxHighlightedLines: [],
84
88
isCopied: false ,
89
+ showCopyButton: true ,
90
+ buttonPositioned: false ,
91
+ scrollTimeout: null ,
85
92
};
86
93
},
94
+ mounted () {
95
+ this .$nextTick (() => {
96
+ this .updateCopyButtonPosition ();
97
+ const container = this .$refs .scrollContainer ;
98
+ if (container) {
99
+ container .addEventListener (' scroll' , this .handleScroll , { passive: true });
100
+ }
101
+ });
102
+ },
87
103
props: {
88
104
fileName: String ,
89
105
isFileNameActionable: {
@@ -149,6 +165,29 @@ export default {
149
165
line === ' ' ? ' \n ' : line
150
166
));
151
167
},
168
+ updateCopyButtonPosition () {
169
+ const container = this .$refs .scrollContainer ;
170
+ const button = this .$refs .copyButton ;
171
+
172
+ if (! container || ! button) return ;
173
+
174
+ const { scrollLeft } = container;
175
+
176
+ button .style .transform = ` translateX(${ scrollLeft} px)` ;
177
+ this .buttonPositioned = true ;
178
+ },
179
+ handleScroll: debounce (function handleScroll () {
180
+ this .showCopyButton = false ;
181
+ this .updateCopyButtonPosition ();
182
+
183
+ if (this .scrollTimeout ) {
184
+ clearTimeout (this .scrollTimeout );
185
+ }
186
+
187
+ this .scrollTimeout = window .setTimeout (() => {
188
+ this .showCopyButton = true ;
189
+ }, 500 );
190
+ }, 100 ),
152
191
copyToClipboard () {
153
192
const lines = this .content ;
154
193
const text = lines .join (' \n ' );
@@ -249,17 +288,23 @@ pre {
249
288
250
289
.copy-button {
251
290
position : absolute ;
252
- top : 1em ;
253
- right : 1em ;
291
+ top : 0.5em ;
292
+ right : 0.5em ;
293
+ transform : translateX (0 );
254
294
background : var (--color-fill-gray-tertiary );
255
295
border : none ;
256
296
border-radius : 6px ;
257
297
padding : 7px 6px ;
258
298
cursor : pointer ;
259
299
display : none ;
300
+ opacity : 0 ;
260
301
transition : all 0.2s ease-in-out ;
261
302
}
262
303
304
+ .copy-button.visible {
305
+ opacity : 1 ;
306
+ }
307
+
263
308
.copy-button svg {
264
309
width : 24px ;
265
310
height : 24px ;
0 commit comments