@gitlab/ui 66.23.0 → 66.24.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.
Files changed (26) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/components/base/new_dropdowns/disclosure/disclosure_dropdown_group.js +2 -2
  3. package/dist/components/base/new_dropdowns/listbox/listbox.js +1 -1
  4. package/dist/components/experimental/duo/chat/components/duo_chat_loader/duo_chat_loader.js +100 -0
  5. package/dist/components/experimental/duo/chat/constants.js +2 -1
  6. package/dist/components/experimental/duo/user_feedback/user_feedback.js +1 -1
  7. package/dist/index.css +1 -1
  8. package/dist/index.css.map +1 -1
  9. package/dist/tokens/css/tokens.css +1 -1
  10. package/dist/tokens/css/tokens.dark.css +1 -1
  11. package/dist/tokens/js/tokens.dark.js +1 -1
  12. package/dist/tokens/js/tokens.js +1 -1
  13. package/dist/tokens/scss/_tokens.dark.scss +1 -1
  14. package/dist/tokens/scss/_tokens.scss +1 -1
  15. package/package.json +2 -2
  16. package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown_group.vue +2 -2
  17. package/src/components/base/new_dropdowns/listbox/listbox.stories.js +1 -1
  18. package/src/components/base/new_dropdowns/listbox/listbox.vue +1 -1
  19. package/src/components/experimental/duo/chat/components/duo_chat_loader/duo_chat_loader.md +1 -0
  20. package/src/components/experimental/duo/chat/components/duo_chat_loader/duo_chat_loader.scss +67 -0
  21. package/src/components/experimental/duo/chat/components/duo_chat_loader/duo_chat_loader.spec.js +70 -0
  22. package/src/components/experimental/duo/chat/components/duo_chat_loader/duo_chat_loader.stories.js +31 -0
  23. package/src/components/experimental/duo/chat/components/duo_chat_loader/duo_chat_loader.vue +94 -0
  24. package/src/components/experimental/duo/chat/constants.js +2 -0
  25. package/src/components/experimental/duo/user_feedback/user_feedback.vue +1 -0
  26. package/src/scss/components.scss +1 -0
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Tue, 03 Oct 2023 12:19:27 GMT
3
+ * Generated on Thu, 05 Oct 2023 10:12:46 GMT
4
4
  */
5
5
 
6
6
  :root {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Tue, 03 Oct 2023 12:19:27 GMT
3
+ * Generated on Thu, 05 Oct 2023 10:12:46 GMT
4
4
  */
5
5
 
6
6
  :root {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Tue, 03 Oct 2023 12:19:27 GMT
3
+ * Generated on Thu, 05 Oct 2023 10:12:46 GMT
4
4
  */
5
5
 
6
6
  export const BLACK = "#fff";
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Tue, 03 Oct 2023 12:19:27 GMT
3
+ * Generated on Thu, 05 Oct 2023 10:12:46 GMT
4
4
  */
5
5
 
6
6
  export const BLACK = "#000";
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly
3
- // Generated on Tue, 03 Oct 2023 12:19:27 GMT
3
+ // Generated on Thu, 05 Oct 2023 10:12:46 GMT
4
4
 
5
5
  $red-950: #fff4f3;
6
6
  $red-900: #fcf1ef;
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly
3
- // Generated on Tue, 03 Oct 2023 12:19:27 GMT
3
+ // Generated on Thu, 05 Oct 2023 10:12:46 GMT
4
4
 
5
5
  $gl-line-height-52: 3.25rem;
6
6
  $gl-line-height-44: 2.75rem;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "66.23.0",
3
+ "version": "66.24.0",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -94,7 +94,7 @@
94
94
  "@gitlab/eslint-plugin": "19.0.0",
95
95
  "@gitlab/fonts": "^1.2.0",
96
96
  "@gitlab/stylelint-config": "5.0.0",
97
- "@gitlab/svgs": "3.63.0",
97
+ "@gitlab/svgs": "3.65.0",
98
98
  "@rollup/plugin-commonjs": "^11.1.0",
99
99
  "@rollup/plugin-node-resolve": "^7.1.3",
100
100
  "@rollup/plugin-replace": "^2.3.2",
@@ -8,8 +8,8 @@ import {
8
8
  } from './constants';
9
9
 
10
10
  export const BORDER_CLASSES = {
11
- [borderPositions.top]: 'gl-border-t gl-pt-2 gl-mt-2',
12
- [borderPositions.bottom]: 'gl-border-b gl-pb-2 gl-mb-2',
11
+ [borderPositions.top]: 'gl-border-t gl-border-t-gray-200 gl-pt-2 gl-mt-2',
12
+ [borderPositions.bottom]: 'gl-border-b gl-border-b-gray-200 gl-pb-2 gl-mb-2',
13
13
  };
14
14
 
15
15
  export default {
@@ -199,7 +199,7 @@ export const HeaderAndFooter = (args, { argTypes }) => ({
199
199
  template: template(
200
200
  `
201
201
  <template #footer>
202
- <div class="gl-border-t-solid gl-border-t-1 gl-border-t-gray-100 gl-display-flex gl-flex-direction-column gl-p-2! gl-pt-0!">
202
+ <div class="gl-border-t-solid gl-border-t-1 gl-border-t-gray-200 gl-display-flex gl-flex-direction-column gl-p-2! gl-pt-0!">
203
203
  <gl-button @click="selectAllItems" category="tertiary" block class="gl-justify-content-start! gl-mt-2!">
204
204
  Select all
205
205
  </gl-button>
@@ -33,7 +33,7 @@ import { isOption, itemsValidator, flattenedOptions } from './utils';
33
33
 
34
34
  export const ITEM_SELECTOR = '[role="option"]';
35
35
  const HEADER_ITEMS_BORDER_CLASSES = ['gl-border-b-1', 'gl-border-b-solid', 'gl-border-b-gray-200'];
36
- const GROUP_TOP_BORDER_CLASSES = ['gl-border-t', 'gl-pt-1', 'gl-mt-2'];
36
+ const GROUP_TOP_BORDER_CLASSES = ['gl-border-t', 'gl-border-t-gray-200', 'gl-pt-1', 'gl-mt-2'];
37
37
  export const SEARCH_INPUT_SELECTOR = '.gl-listbox-search-input';
38
38
 
39
39
  export default {
@@ -0,0 +1 @@
1
+ The Duo Chat loader. Is shown while waiting for the chat response.
@@ -0,0 +1,67 @@
1
+ .duo-chat-loader {
2
+ @include gl-py-3;
3
+ @include gl-px-4;
4
+ @include gl-mb-4;
5
+ @include gl-rounded-lg;
6
+ @include gl-rounded-bottom-left-none;
7
+ @include gl-display-flex;
8
+ @include gl-text-gray-500;
9
+
10
+ .transition {
11
+ transition: width 0.5s ease;
12
+ }
13
+
14
+ .text-enter {
15
+ @include gl-opacity-0;
16
+ }
17
+
18
+ .text-enter-active {
19
+ transition: opacity 1s ease-in; // we intentionally overlap this transition with .text-leave-active by 200ms
20
+ }
21
+
22
+ .text-enter-to {
23
+ @include gl-opacity-10;
24
+ }
25
+
26
+ .text-leave {
27
+ @include gl-opacity-10;
28
+ }
29
+
30
+ .text-leave-active {
31
+ transition: opacity 0.7s linear;
32
+ }
33
+
34
+ .text-leave-to {
35
+ @include gl-opacity-0;
36
+ }
37
+
38
+ &__dot {
39
+ display: inline-block;
40
+ width: 0.3rem;
41
+ height: 0.3rem;
42
+ background-color: $gray-200;
43
+ border-radius: 100%;
44
+ animation: DuoChatLoading 1400ms ease-in-out infinite;
45
+ animation-fill-mode: both;
46
+ }
47
+
48
+ &__dot--1 {
49
+ animation-delay: -0.3s;
50
+ }
51
+
52
+ &__dot--2 {
53
+ animation-delay: -0.15s;
54
+ }
55
+ }
56
+
57
+ @keyframes DuoChatLoading {
58
+ 0%,
59
+ 80%,
60
+ 100% {
61
+ transform: scale(0);
62
+ }
63
+
64
+ 40% {
65
+ transform: scale(1);
66
+ }
67
+ }
@@ -0,0 +1,70 @@
1
+ import { nextTick } from 'vue';
2
+ import { mount } from '@vue/test-utils';
3
+ import { LOADING_TRANSITION_DURATION } from '../../constants';
4
+ import GlDuoChatLoader from './duo_chat_loader.vue';
5
+
6
+ jest.useFakeTimers();
7
+
8
+ describe('GlDuoChatLoader', () => {
9
+ let wrapper;
10
+
11
+ const createComponent = ({ propsData = {} } = {}) => {
12
+ wrapper = mount(GlDuoChatLoader, {
13
+ propsData,
14
+ });
15
+ };
16
+
17
+ const transition = async () => {
18
+ jest.advanceTimersByTime(LOADING_TRANSITION_DURATION);
19
+ await nextTick();
20
+ };
21
+
22
+ const findTransitionText = () => wrapper.find('[data-testid="current-transition"]').text();
23
+ const findToolText = () => wrapper.find('[data-testid="tool"]');
24
+
25
+ describe('rendering', () => {
26
+ const defaultTool = GlDuoChatLoader.props.toolName.default;
27
+
28
+ it('displays a default tool', async () => {
29
+ createComponent();
30
+ await nextTick();
31
+
32
+ expect(findToolText().text()).toBe(defaultTool);
33
+ });
34
+
35
+ it('shows the `toolName` when it is passed', async () => {
36
+ createComponent({
37
+ propsData: {
38
+ toolName: 'foo',
39
+ },
40
+ });
41
+ await nextTick();
42
+
43
+ expect(findToolText().text()).toBe('foo');
44
+ expect(findToolText().text()).not.toBe(defaultTool);
45
+ });
46
+
47
+ it('cycles through transition texts', async () => {
48
+ createComponent();
49
+ await nextTick();
50
+
51
+ expect(findTransitionText()).toEqual('finding');
52
+
53
+ await transition();
54
+
55
+ expect(findTransitionText()).toEqual('working on');
56
+
57
+ await transition();
58
+
59
+ expect(findTransitionText()).toEqual('generating');
60
+
61
+ await transition();
62
+
63
+ expect(findTransitionText()).toEqual('producing');
64
+
65
+ await transition();
66
+
67
+ expect(findTransitionText()).toEqual('finding');
68
+ });
69
+ });
70
+ });
@@ -0,0 +1,31 @@
1
+ import GlDuoChatLoader from './duo_chat_loader.vue';
2
+ import readme from './duo_chat_loader.md';
3
+
4
+ const defaultValue = (prop) => GlDuoChatLoader.props[prop].default;
5
+
6
+ const generateProps = ({ toolName = defaultValue('toolName') } = {}) => ({
7
+ toolName,
8
+ });
9
+
10
+ const Template = (args, { argTypes }) => ({
11
+ components: { GlDuoChatLoader },
12
+ props: Object.keys(argTypes),
13
+ template: `
14
+ <gl-duo-chat-loader :tool-name="toolName" />
15
+ `,
16
+ });
17
+
18
+ export const Default = Template.bind({});
19
+ Default.args = generateProps();
20
+
21
+ export default {
22
+ title: 'experimental/duo/chat/duo_chat_loader',
23
+ component: GlDuoChatLoader,
24
+ parameters: {
25
+ docs: {
26
+ description: {
27
+ component: readme,
28
+ },
29
+ },
30
+ },
31
+ };
@@ -0,0 +1,94 @@
1
+ <script>
2
+ import GlSprintf from '../../../../../utilities/sprintf/sprintf.vue';
3
+ import { LOADING_TRANSITION_DURATION } from '../../constants';
4
+
5
+ export const i18n = {
6
+ LOADER_LOADING_MESSAGE: '%{tool} is %{transition} an answer',
7
+ LOADER_LOADING_TRANSITIONS: ['finding', 'working on', 'generating', 'producing'],
8
+ GITLAB_DUO: 'GitLab Duo',
9
+ };
10
+
11
+ export default {
12
+ name: 'GlDuoChatLoader',
13
+ components: {
14
+ GlSprintf,
15
+ },
16
+ i18n,
17
+ props: {
18
+ /**
19
+ * The message containing the name of the current AI tool working on the answer.
20
+ */
21
+ toolName: {
22
+ type: String,
23
+ required: false,
24
+ default: i18n.GITLAB_DUO,
25
+ },
26
+ },
27
+ data() {
28
+ return {
29
+ loadingSequence: 0,
30
+ timeout: null,
31
+ };
32
+ },
33
+ beforeDestroy() {
34
+ clearTimeout(this.timeout);
35
+ },
36
+ mounted() {
37
+ this.computeTransitionWidth();
38
+ this.enter();
39
+ },
40
+ methods: {
41
+ computeTransitionWidth() {
42
+ const container = this.$refs.transition;
43
+ const active = this.$refs.currentTransition[0]; // There's only one `currentTransition` ref at a time, but refs in v-for loops are always Arrays
44
+ const { width, height } = active.getBoundingClientRect();
45
+ container.$el.style.width = `${width}px`;
46
+ container.$el.style.height = `${height}px`;
47
+ },
48
+ enter() {
49
+ clearTimeout(this.timeout);
50
+ this.timeout = setTimeout(() => {
51
+ this.loadingSequence =
52
+ (this.loadingSequence + 1) % this.$options.i18n.LOADER_LOADING_TRANSITIONS.length;
53
+ this.enter();
54
+ }, LOADING_TRANSITION_DURATION);
55
+ },
56
+ isCurrentTransition(index) {
57
+ return index === this.loadingSequence;
58
+ },
59
+ },
60
+ };
61
+ </script>
62
+
63
+ <template>
64
+ <div class="duo-chat-loader">
65
+ <div class="gl-display-flex gl-align-items-center gl-mr-3">
66
+ <div class="duo-chat-loader__dot duo-chat-loader__dot--1"></div>
67
+ <div class="duo-chat-loader__dot duo-chat-loader__dot--2"></div>
68
+ <div class="duo-chat-loader__dot duo-chat-loader__dot--3"></div>
69
+ </div>
70
+ <gl-sprintf :message="$options.i18n.LOADER_LOADING_MESSAGE">
71
+ <template #tool>
72
+ <strong class="gl-mr-2" data-testid="tool">{{ toolName }}</strong>
73
+ </template>
74
+ <template #transition>
75
+ <transition-group
76
+ ref="transition"
77
+ name="text"
78
+ class="transition gl-display-inline-block gl-mx-2"
79
+ @after-leave="computeTransitionWidth"
80
+ >
81
+ <span
82
+ v-for="(message, index) in $options.i18n.LOADER_LOADING_TRANSITIONS"
83
+ v-show="isCurrentTransition(index)"
84
+ :ref="isCurrentTransition(index) ? 'currentTransition' : ''"
85
+ :key="message"
86
+ :data-testid="isCurrentTransition(index) ? 'current-transition' : ''"
87
+ class="gl-white-space-nowrap"
88
+ >{{ message }}</span
89
+ >
90
+ </transition-group>
91
+ </template>
92
+ </gl-sprintf>
93
+ </div>
94
+ </template>
@@ -1,3 +1,5 @@
1
+ export const LOADING_TRANSITION_DURATION = 7500;
2
+
1
3
  export const DOCUMENTATION_SOURCE_TYPES = {
2
4
  HANDBOOK: {
3
5
  value: 'handbook',
@@ -64,6 +64,7 @@ export default {
64
64
  variant="link"
65
65
  target="_blank"
66
66
  :href="feedbackLinkUrl"
67
+ button-text-classes="gl-white-space-normal! gl-text-left"
67
68
  @click="shouldRenderModal && $refs.feedbackModal.show()"
68
69
  >{{ feedbackLinkText }}</gl-button
69
70
  >
@@ -3,6 +3,7 @@
3
3
  // @import '../components/base/dropdown/dropdown'
4
4
  //
5
5
  // ADD COMPONENT IMPORTS - needed for yarn generate:component. Do not remove
6
+ @import '../components/experimental/duo/chat/components/duo_chat_loader/duo_chat_loader';
6
7
  @import '../components/base/new_dropdowns/disclosure/disclosure_dropdown';
7
8
  @import '../components/base/keyset_pagination/keyset_pagination';
8
9
  @import '../components/charts/gauge/gauge';