@gitlab/ui 124.1.1 → 124.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/base/breadcrumb/breadcrumb.js +33 -2
- package/dist/components/index.js +1 -0
- package/dist/components/shared_components/clipboard_button/clipboard_button.js +100 -0
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/package.json +1 -1
- package/src/components/base/breadcrumb/breadcrumb.scss +6 -1
- package/src/components/base/breadcrumb/breadcrumb.vue +53 -9
- package/src/components/index.js +3 -0
- package/src/components/shared_components/clipboard_button/clipboard_button.vue +78 -0
- package/translations.js +3 -0
package/package.json
CHANGED
|
@@ -20,7 +20,7 @@ $breadcrumb-max-width: $grid-size * 16;
|
|
|
20
20
|
@apply gl-leading-normal;
|
|
21
21
|
@apply gl-shrink-0;
|
|
22
22
|
|
|
23
|
-
&:not(:last-child)::after {
|
|
23
|
+
&:not(:last-child, :has(+ .gl-breadcrumb-clipboard-button))::after {
|
|
24
24
|
color: var(--gl-breadcrumb-separator-color);
|
|
25
25
|
@apply gl-px-3;
|
|
26
26
|
content: '/';
|
|
@@ -75,3 +75,8 @@ $breadcrumb-max-width: $grid-size * 16;
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
+
|
|
79
|
+
.gl-breadcrumb-clipboard-button {
|
|
80
|
+
@apply gl-leading-normal;
|
|
81
|
+
@apply gl-shrink-0;
|
|
82
|
+
}
|
|
@@ -6,6 +6,7 @@ import GlAvatar from '../avatar/avatar.vue';
|
|
|
6
6
|
import GlDisclosureDropdown from '../new_dropdowns/disclosure/disclosure_dropdown.vue';
|
|
7
7
|
import { GlTooltipDirective } from '../../../directives/tooltip/tooltip';
|
|
8
8
|
import { breadCrumbSizeOptions } from '../../../utils/constants';
|
|
9
|
+
import ClipboardButton from '../../shared_components/clipboard_button/clipboard_button.vue';
|
|
9
10
|
import GlBreadcrumbItem from './breadcrumb_item.vue';
|
|
10
11
|
|
|
11
12
|
export default {
|
|
@@ -14,6 +15,7 @@ export default {
|
|
|
14
15
|
GlBreadcrumbItem,
|
|
15
16
|
GlAvatar,
|
|
16
17
|
GlDisclosureDropdown,
|
|
18
|
+
ClipboardButton,
|
|
17
19
|
},
|
|
18
20
|
directives: {
|
|
19
21
|
GlTooltip: GlTooltipDirective,
|
|
@@ -64,6 +66,30 @@ export default {
|
|
|
64
66
|
default: breadCrumbSizeOptions.sm,
|
|
65
67
|
validator: (value) => Object.keys(breadCrumbSizeOptions).includes(value),
|
|
66
68
|
},
|
|
69
|
+
/**
|
|
70
|
+
* Copy to clipboard button for breadcrumbs path.
|
|
71
|
+
*/
|
|
72
|
+
showClipboardButton: {
|
|
73
|
+
type: Boolean,
|
|
74
|
+
required: false,
|
|
75
|
+
default: false,
|
|
76
|
+
},
|
|
77
|
+
/**
|
|
78
|
+
* Custom path for copy to clipboard button. By default, it resolves to all items text values with `/` separator.
|
|
79
|
+
*/
|
|
80
|
+
pathToCopy: {
|
|
81
|
+
type: String,
|
|
82
|
+
required: false,
|
|
83
|
+
default: null,
|
|
84
|
+
},
|
|
85
|
+
/**
|
|
86
|
+
* Custom tooltip text for clipboard button.
|
|
87
|
+
*/
|
|
88
|
+
clipboardTooltipText: {
|
|
89
|
+
type: String,
|
|
90
|
+
required: false,
|
|
91
|
+
default: null,
|
|
92
|
+
},
|
|
67
93
|
},
|
|
68
94
|
data() {
|
|
69
95
|
return {
|
|
@@ -94,6 +120,12 @@ export default {
|
|
|
94
120
|
avatarSize() {
|
|
95
121
|
return this.size === 'sm' ? 16 : 24;
|
|
96
122
|
},
|
|
123
|
+
clipboardButtonText() {
|
|
124
|
+
if (this.pathToCopy) return this.pathToCopy;
|
|
125
|
+
|
|
126
|
+
const items = Array.from(this.items, (item) => item.text);
|
|
127
|
+
return items.join('/');
|
|
128
|
+
},
|
|
97
129
|
},
|
|
98
130
|
watch: {
|
|
99
131
|
items: {
|
|
@@ -230,16 +262,28 @@ export default {
|
|
|
230
262
|
:size="size"
|
|
231
263
|
:aria-current="getAriaCurrentAttr(index)"
|
|
232
264
|
:class="[hideItemClass(item), itemClass]"
|
|
233
|
-
><
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
265
|
+
><template #default>
|
|
266
|
+
<gl-avatar
|
|
267
|
+
v-if="item.avatarPath"
|
|
268
|
+
:src="item.avatarPath"
|
|
269
|
+
:size="avatarSize"
|
|
270
|
+
aria-hidden="true"
|
|
271
|
+
class="gl-breadcrumb-avatar-tile gl-border gl-mr-2 !gl-rounded-default"
|
|
272
|
+
shape="rect"
|
|
273
|
+
data-testid="avatar"
|
|
274
|
+
/><span class="gl-align-middle">{{ item.text }}</span>
|
|
275
|
+
</template>
|
|
242
276
|
</gl-breadcrumb-item>
|
|
277
|
+
|
|
278
|
+
<li v-if="showClipboardButton" class="gl-breadcrumb-clipboard-button">
|
|
279
|
+
<clipboard-button
|
|
280
|
+
data-testid="copy-to-clipboard-button"
|
|
281
|
+
class="gl-ml-2"
|
|
282
|
+
:text="clipboardButtonText"
|
|
283
|
+
v-bind="clipboardTooltipText ? { title: clipboardTooltipText } : {}"
|
|
284
|
+
:size="dropdownSize"
|
|
285
|
+
/>
|
|
286
|
+
</li>
|
|
243
287
|
</ol>
|
|
244
288
|
</nav>
|
|
245
289
|
</template>
|
package/src/components/index.js
CHANGED
|
@@ -102,6 +102,9 @@ export { default as GlDashboardPanel } from './dashboards/dashboard_panel/dashbo
|
|
|
102
102
|
// Experimental
|
|
103
103
|
export { default as GlExperimentBadge } from './experimental/experiment_badge/experiment_badge.vue';
|
|
104
104
|
|
|
105
|
+
// Shared components
|
|
106
|
+
export { default as GlClipboardButton } from './shared_components/clipboard_button/clipboard_button.vue';
|
|
107
|
+
|
|
105
108
|
// Utilities
|
|
106
109
|
export { default as GlAnimatedNumber } from './utilities/animated_number/animated_number.vue';
|
|
107
110
|
export { default as GlFriendlyWrap } from './utilities/friendly_wrap/friendly_wrap.vue';
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { GlTooltipDirective } from '../../../directives/tooltip/tooltip';
|
|
3
|
+
import GlButton from '../../base/button/button.vue';
|
|
4
|
+
import { translate } from '../../../utils/i18n';
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
name: 'ClipboardButton',
|
|
8
|
+
components: {
|
|
9
|
+
GlButton,
|
|
10
|
+
},
|
|
11
|
+
directives: {
|
|
12
|
+
GlTooltip: GlTooltipDirective,
|
|
13
|
+
},
|
|
14
|
+
props: {
|
|
15
|
+
/**
|
|
16
|
+
* The text to copy to clipboard
|
|
17
|
+
*/
|
|
18
|
+
text: {
|
|
19
|
+
type: String,
|
|
20
|
+
required: true,
|
|
21
|
+
},
|
|
22
|
+
/**
|
|
23
|
+
* The tooltip text shown on hover
|
|
24
|
+
*/
|
|
25
|
+
title: {
|
|
26
|
+
type: String,
|
|
27
|
+
required: false,
|
|
28
|
+
default: () => translate('ClipboardButton.title', 'Copy to clipboard'),
|
|
29
|
+
},
|
|
30
|
+
/**
|
|
31
|
+
* Button size
|
|
32
|
+
*/
|
|
33
|
+
size: {
|
|
34
|
+
type: String,
|
|
35
|
+
required: false,
|
|
36
|
+
default: 'medium',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
data() {
|
|
40
|
+
return {
|
|
41
|
+
localTitle: this.title,
|
|
42
|
+
titleTimeout: null,
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
methods: {
|
|
46
|
+
updateTooltip(title) {
|
|
47
|
+
this.localTitle = title;
|
|
48
|
+
|
|
49
|
+
clearTimeout(this.titleTimeout);
|
|
50
|
+
|
|
51
|
+
this.titleTimeout = setTimeout(() => {
|
|
52
|
+
this.localTitle = this.title;
|
|
53
|
+
}, 1000);
|
|
54
|
+
},
|
|
55
|
+
async handleClick() {
|
|
56
|
+
try {
|
|
57
|
+
await navigator.clipboard.writeText(this.text);
|
|
58
|
+
this.updateTooltip(translate('ClipboardButton.copied', 'Copied'));
|
|
59
|
+
} catch {
|
|
60
|
+
this.updateTooltip(translate('ClipboardButton.error', 'Copy failed'));
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
</script>
|
|
66
|
+
|
|
67
|
+
<template>
|
|
68
|
+
<gl-button
|
|
69
|
+
v-gl-tooltip.hover.focus.top
|
|
70
|
+
variant="default"
|
|
71
|
+
category="tertiary"
|
|
72
|
+
icon="copy-to-clipboard"
|
|
73
|
+
:size="size"
|
|
74
|
+
:title="localTitle"
|
|
75
|
+
:aria-label="localTitle"
|
|
76
|
+
@click="handleClick"
|
|
77
|
+
/>
|
|
78
|
+
</template>
|
package/translations.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/* eslint-disable import/no-default-export */
|
|
2
2
|
export default {
|
|
3
3
|
'ClearIconButton.title': 'Clear',
|
|
4
|
+
'ClipboardButton.copied': 'Copied',
|
|
5
|
+
'ClipboardButton.error': 'Copy failed',
|
|
6
|
+
'ClipboardButton.title': 'Copy to clipboard',
|
|
4
7
|
'CloseButton.title': 'Close',
|
|
5
8
|
'GlAlert.closeButtonTitle': 'Dismiss',
|
|
6
9
|
'GlBanner.closeButtonTitle': 'Dismiss',
|