@gitlab/ui 91.12.0 → 91.14.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 (48) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/components/base/form/form_date/form_date.js +2 -2
  3. package/dist/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_menu/duo_chat_context_item_menu_search_item.js +81 -0
  4. package/dist/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_menu/duo_chat_context_item_menu_search_items.js +10 -5
  5. package/dist/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_popover/duo_chat_context_item_popover.js +19 -15
  6. package/dist/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_selections/duo_chat_context_item_selections.js +5 -5
  7. package/dist/components/experimental/duo/chat/components/duo_chat_context/mock_context_data.js +4 -1
  8. package/dist/components/experimental/duo/chat/components/duo_chat_context/utils.js +9 -1
  9. package/dist/index.css +1 -1
  10. package/dist/index.css.map +1 -1
  11. package/dist/tailwind.css +1 -1
  12. package/dist/tailwind.css.map +1 -1
  13. package/dist/tokens/build/js/tokens.dark.js +4 -1
  14. package/dist/tokens/build/js/tokens.js +4 -1
  15. package/dist/tokens/css/tokens.css +3 -0
  16. package/dist/tokens/css/tokens.dark.css +3 -0
  17. package/dist/tokens/js/tokens.dark.js +3 -0
  18. package/dist/tokens/js/tokens.js +3 -0
  19. package/dist/tokens/json/tokens.dark.json +63 -0
  20. package/dist/tokens/json/tokens.json +63 -0
  21. package/dist/tokens/scss/_tokens.dark.scss +3 -0
  22. package/dist/tokens/scss/_tokens.scss +3 -0
  23. package/dist/tokens/scss/_tokens_custom_properties.scss +3 -0
  24. package/dist/tokens/tailwind/tokens.cjs +3 -0
  25. package/package.json +5 -5
  26. package/src/components/base/form/form_character_count/form_character_count.md +2 -2
  27. package/src/components/base/form/form_character_count/form_character_count.vue +2 -2
  28. package/src/components/base/form/form_date/form_date.vue +2 -2
  29. package/src/components/base/form/form_textarea/form_textarea.vue +2 -2
  30. package/src/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_menu/duo_chat_context_item_menu_search_item.vue +71 -0
  31. package/src/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_menu/duo_chat_context_item_menu_search_items.vue +19 -12
  32. package/src/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_popover/duo_chat_context_item_popover.vue +24 -20
  33. package/src/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_selections/duo_chat_context_item_selections.vue +12 -12
  34. package/src/components/experimental/duo/chat/components/duo_chat_context/mock_context_data.js +4 -0
  35. package/src/components/experimental/duo/chat/components/duo_chat_context/utils.js +12 -0
  36. package/src/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.scss +2 -2
  37. package/src/tokens/background.tokens.json +13 -0
  38. package/src/tokens/border.tokens.json +8 -0
  39. package/src/tokens/build/css/tokens.css +3 -0
  40. package/src/tokens/build/css/tokens.dark.css +3 -0
  41. package/src/tokens/build/js/tokens.dark.js +3 -0
  42. package/src/tokens/build/js/tokens.js +3 -0
  43. package/src/tokens/build/json/tokens.dark.json +63 -0
  44. package/src/tokens/build/json/tokens.json +63 -0
  45. package/src/tokens/build/scss/_tokens.dark.scss +3 -0
  46. package/src/tokens/build/scss/_tokens.scss +3 -0
  47. package/src/tokens/build/scss/_tokens_custom_properties.scss +3 -0
  48. package/src/tokens/build/tailwind/tokens.cjs +3 -0
@@ -1868,6 +1868,47 @@
1868
1868
  "disabled"
1869
1869
  ]
1870
1870
  },
1871
+ "overlap": {
1872
+ "value": "#fff",
1873
+ "$type": "color",
1874
+ "comment": "Used for components, like tooltips and drawers, and content, like a sticky header, that overlap other content.",
1875
+ "filePath": "src/tokens/background.tokens.json",
1876
+ "isSource": true,
1877
+ "original": {
1878
+ "value": {
1879
+ "default": "{color.neutral.0}",
1880
+ "dark": "{color.neutral.800}"
1881
+ },
1882
+ "$type": "color",
1883
+ "comment": "Used for components, like tooltips and drawers, and content, like a sticky header, that overlap other content."
1884
+ },
1885
+ "name": "BACKGROUND_COLOR_OVERLAP",
1886
+ "attributes": {},
1887
+ "path": [
1888
+ "background",
1889
+ "color",
1890
+ "overlap"
1891
+ ]
1892
+ },
1893
+ "section": {
1894
+ "value": "#fff",
1895
+ "$type": "color",
1896
+ "comment": "Used for containers, like a card header, that are visually distinct from the default page background only when necessary to maintain affordance and hierarchy in different modes.",
1897
+ "filePath": "src/tokens/background.tokens.json",
1898
+ "isSource": true,
1899
+ "original": {
1900
+ "value": "{background.color.overlap}",
1901
+ "$type": "color",
1902
+ "comment": "Used for containers, like a card header, that are visually distinct from the default page background only when necessary to maintain affordance and hierarchy in different modes."
1903
+ },
1904
+ "name": "BACKGROUND_COLOR_SECTION",
1905
+ "attributes": {},
1906
+ "path": [
1907
+ "background",
1908
+ "color",
1909
+ "section"
1910
+ ]
1911
+ },
1871
1912
  "overlay": {
1872
1913
  "value": "rgba(05, 05, 06, 0.24)",
1873
1914
  "$type": "color",
@@ -1960,6 +2001,28 @@
1960
2001
  "strong"
1961
2002
  ]
1962
2003
  },
2004
+ "section": {
2005
+ "value": "#dcdcde",
2006
+ "$type": "color",
2007
+ "comment": "Used for the border color that surrounds content or elements when they appear as a closed container or closed section of the page.",
2008
+ "filePath": "src/tokens/border.tokens.json",
2009
+ "isSource": true,
2010
+ "original": {
2011
+ "value": {
2012
+ "default": "{border.color.default}",
2013
+ "dark": "{background.color.default}"
2014
+ },
2015
+ "$type": "color",
2016
+ "comment": "Used for the border color that surrounds content or elements when they appear as a closed container or closed section of the page."
2017
+ },
2018
+ "name": "BORDER_COLOR_SECTION",
2019
+ "attributes": {},
2020
+ "path": [
2021
+ "border",
2022
+ "color",
2023
+ "section"
2024
+ ]
2025
+ },
1963
2026
  "transparent": {
1964
2027
  "value": "transparent",
1965
2028
  "$type": "color",
@@ -721,6 +721,7 @@ $gl-border-color-strong: $gl-color-neutral-400; // Used for a distinct border th
721
721
  $gl-border-color-subtle: $gl-color-neutral-900; // Used for a subtle border in combination with the default background.
722
722
  $gl-border-color-default: $gl-color-neutral-800; // Used for the default border color.
723
723
  $gl-background-color-overlay: rgba(0,0,0,0.64); // Used for an overlay that covers other content.
724
+ $gl-background-color-overlap: $gl-color-neutral-800; // Used for components, like tooltips and drawers, and content, like a sticky header, that overlap other content.
724
725
  $gl-background-color-disabled: $gl-color-neutral-900; // Used to identify a disabled section.
725
726
  $gl-background-color-strong: $gl-color-neutral-800; // Used to make the background easily stand out from the default.
726
727
  $gl-background-color-subtle: $gl-color-neutral-900; // Used to slightly differentiate the background from the default.
@@ -834,6 +835,8 @@ $gl-alert-info-background-color: $gl-background-color-subtle; // Used for the ba
834
835
  $gl-alert-info-title-color: $gl-color-blue-300; // Used for the title color of an info alert.
835
836
  $gl-alert-neutral-background-color: $gl-feedback-neutral-background-color; // Used for the background color of a neutral alert.
836
837
  $gl-alert-neutral-title-color: $gl-text-color-heading; // Used for the title color of a neutral alert.
838
+ $gl-border-color-section: $gl-background-color-default; // Used for the border color that surrounds content or elements when they appear as a closed container or closed section of the page.
839
+ $gl-background-color-section: $gl-background-color-overlap; // Used for containers, like a card header, that are visually distinct from the default page background only when necessary to maintain affordance and hierarchy in different modes.
837
840
  $gl-action-strong-neutral-border-color-hover: $gl-action-strong-neutral-border-color-default; // Used for the border of a strong neutral action in the hover state.
838
841
  $gl-action-strong-neutral-foreground-color-hover: $gl-action-strong-neutral-foreground-color-default; // Used for the foreground of a strong neutral action in the hover state.
839
842
  $gl-action-strong-neutral-background-color-focus: $gl-action-strong-neutral-background-color-hover; // Used for the background of a strong neutral action in the focus state.
@@ -721,6 +721,7 @@ $gl-border-color-strong: $gl-color-neutral-400; // Used for a distinct border th
721
721
  $gl-border-color-subtle: $gl-color-neutral-50; // Used for a subtle border in combination with the default background.
722
722
  $gl-border-color-default: $gl-color-neutral-100; // Used for the default border color.
723
723
  $gl-background-color-overlay: $gl-color-alpha-dark-24; // Used for an overlay that covers other content.
724
+ $gl-background-color-overlap: $gl-color-neutral-0; // Used for components, like tooltips and drawers, and content, like a sticky header, that overlap other content.
724
725
  $gl-background-color-disabled: $gl-color-neutral-10; // Used to identify a disabled section.
725
726
  $gl-background-color-strong: $gl-color-neutral-50; // Used to make the background easily stand out from the default.
726
727
  $gl-background-color-subtle: $gl-color-neutral-10; // Used to slightly differentiate the background from the default.
@@ -834,6 +835,8 @@ $gl-alert-info-background-color: $gl-feedback-info-background-color; // Used for
834
835
  $gl-alert-info-title-color: $gl-text-color-heading; // Used for the title color of an info alert.
835
836
  $gl-alert-neutral-background-color: $gl-feedback-neutral-background-color; // Used for the background color of a neutral alert.
836
837
  $gl-alert-neutral-title-color: $gl-text-color-heading; // Used for the title color of a neutral alert.
838
+ $gl-border-color-section: $gl-border-color-default; // Used for the border color that surrounds content or elements when they appear as a closed container or closed section of the page.
839
+ $gl-background-color-section: $gl-background-color-overlap; // Used for containers, like a card header, that are visually distinct from the default page background only when necessary to maintain affordance and hierarchy in different modes.
837
840
  $gl-action-strong-neutral-border-color-hover: $gl-action-strong-neutral-border-color-default; // Used for the border of a strong neutral action in the hover state.
838
841
  $gl-action-strong-neutral-foreground-color-hover: $gl-action-strong-neutral-foreground-color-default; // Used for the foreground of a strong neutral action in the hover state.
839
842
  $gl-action-strong-neutral-background-color-focus: $gl-action-strong-neutral-background-color-hover; // Used for the background of a strong neutral action in the focus state.
@@ -82,10 +82,13 @@ $gl-background-color-default: var(--gl-background-color-default);
82
82
  $gl-background-color-subtle: var(--gl-background-color-subtle);
83
83
  $gl-background-color-strong: var(--gl-background-color-strong);
84
84
  $gl-background-color-disabled: var(--gl-background-color-disabled);
85
+ $gl-background-color-overlap: var(--gl-background-color-overlap);
86
+ $gl-background-color-section: var(--gl-background-color-section);
85
87
  $gl-background-color-overlay: var(--gl-background-color-overlay);
86
88
  $gl-border-color-default: var(--gl-border-color-default);
87
89
  $gl-border-color-subtle: var(--gl-border-color-subtle);
88
90
  $gl-border-color-strong: var(--gl-border-color-strong);
91
+ $gl-border-color-section: var(--gl-border-color-section);
89
92
  $gl-border-color-transparent: var(--gl-border-color-transparent);
90
93
  $gl-color-alpha-0: var(--gl-color-alpha-0);
91
94
  $gl-color-alpha-dark-2: var(--gl-color-alpha-dark-2);
@@ -218,6 +218,8 @@ const backgroundColors = {
218
218
  subtle: 'var(--gl-background-color-subtle, var(--gl-color-neutral-10, #fbfafd))',
219
219
  strong: 'var(--gl-background-color-strong, var(--gl-color-neutral-50, #ececef))',
220
220
  disabled: 'var(--gl-background-color-disabled, var(--gl-color-neutral-10, #fbfafd))',
221
+ overlap: 'var(--gl-background-color-overlap, var(--gl-color-neutral-0, #fff))',
222
+ section: 'var(--gl-background-color-section, var(--gl-background-color-overlap, #fff))',
221
223
  overlay:
222
224
  'var(--gl-background-color-overlay, var(--gl-color-alpha-dark-24, rgba(05, 05, 06, 0.24)))',
223
225
  };
@@ -225,6 +227,7 @@ const borderColors = {
225
227
  default: 'var(--gl-border-color-default, var(--gl-color-neutral-100, #dcdcde))',
226
228
  subtle: 'var(--gl-border-color-subtle, var(--gl-color-neutral-50, #ececef))',
227
229
  strong: 'var(--gl-border-color-strong, var(--gl-color-neutral-400, #89888d))',
230
+ section: 'var(--gl-border-color-section, var(--gl-border-color-default, #dcdcde))',
228
231
  transparent: 'var(--gl-border-color-transparent, var(--gl-color-alpha-0, transparent))',
229
232
  };
230
233
  const iconColors = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "91.12.0",
3
+ "version": "91.14.0",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -111,7 +111,7 @@
111
111
  "@babel/preset-env": "^7.25.4",
112
112
  "@babel/preset-react": "^7.24.7",
113
113
  "@cypress/grep": "^4.0.1",
114
- "@gitlab/eslint-plugin": "20.1.0",
114
+ "@gitlab/eslint-plugin": "20.2.1",
115
115
  "@gitlab/fonts": "^1.3.0",
116
116
  "@gitlab/stylelint-config": "6.2.1",
117
117
  "@gitlab/svgs": "3.114.0",
@@ -148,7 +148,7 @@
148
148
  "babel-loader": "^8.0.5",
149
149
  "bootstrap": "4.6.2",
150
150
  "cobertura-merge": "^1.0.4",
151
- "cypress": "13.14.1",
151
+ "cypress": "13.14.2",
152
152
  "cypress-axe": "^1.4.0",
153
153
  "cypress-real-events": "^1.11.0",
154
154
  "dompurify": "^3.1.2",
@@ -172,8 +172,8 @@
172
172
  "module-alias": "^2.2.2",
173
173
  "npm-run-all": "^4.1.5",
174
174
  "pikaday": "^1.8.0",
175
- "playwright": "^1.46.1",
176
- "playwright-core": "^1.46.1",
175
+ "playwright": "^1.47.0",
176
+ "playwright-core": "^1.47.0",
177
177
  "plop": "^2.5.4",
178
178
  "postcss": "8.4.28",
179
179
  "postcss-loader": "^7.0.2",
@@ -23,10 +23,10 @@ count separate from the input, use `GlFormCharacterCount`.
23
23
  },
24
24
  methods: {
25
25
  remainingCountText(count) {
26
- return n__('%d character remaining', '%d characters remaining', count)
26
+ return n__('%d character remaining.', '%d characters remaining.', count)
27
27
  },
28
28
  overLimitText(count) {
29
- return n__('%d character over limit', '%d characters over limit', count);
29
+ return n__('%d character over limit.', '%d characters over limit.', count);
30
30
  },
31
31
  },
32
32
  }
@@ -73,12 +73,12 @@ export default {
73
73
  <div>
74
74
  <small :class="['form-text', countTextClass]" aria-hidden="true">
75
75
  <!--
76
- @slot Internationalized over limit text. Example: `<template #over-limit-text="{ count }">{{ n__('%d character over limit', '%d characters over limit', count) }}</template>`
76
+ @slot Internationalized over limit text. Example: `<template #over-limit-text="{ count }">{{ n__('%d character over limit.', '%d characters over limit.', count) }}</template>`
77
77
  @binding {number} count
78
78
  -->
79
79
  <slot v-if="isOverLimit" name="over-limit-text" :count="Math.abs(remainingCount)"></slot>
80
80
  <!--
81
- @slot Internationalized character count text. Example: `<template #remaining-count-text="{ count }">{{ n__('%d character remaining', '%d characters remaining', count) }}</template>`
81
+ @slot Internationalized character count text. Example: `<template #remaining-count-text="{ count }">{{ n__('%d character remaining.', '%d characters remaining.', count) }}</template>`
82
82
  @binding {number} count
83
83
  -->
84
84
 
@@ -31,12 +31,12 @@ export default {
31
31
  minInvalidFeedback: {
32
32
  type: String,
33
33
  required: false,
34
- default: 'Must be after minimum date',
34
+ default: 'Must be after minimum date.',
35
35
  },
36
36
  maxInvalidFeedback: {
37
37
  type: String,
38
38
  required: false,
39
- default: 'Must be before maximum date',
39
+ default: 'Must be before maximum date.',
40
40
  },
41
41
  value: {
42
42
  type: String,
@@ -116,7 +116,7 @@ export default {
116
116
  >
117
117
  <template #over-limit-text="{ count }">
118
118
  <!--
119
- @slot Internationalized over character count text. Example: `<template #character-count-over-limit-text="{ count }">{{ n__('%d character over limit', '%d characters over limit', count) }}</template>`
119
+ @slot Internationalized over character count text. Example: `<template #character-count-over-limit-text="{ count }">{{ n__('%d character over limit.', '%d characters over limit.', count) }}</template>`
120
120
  @binding {number} count
121
121
  -->
122
122
  <slot name="character-count-over-limit-text" :count="count"></slot>
@@ -124,7 +124,7 @@ export default {
124
124
 
125
125
  <template #remaining-count-text="{ count }">
126
126
  <!--
127
- @slot Internationalized character count text. Example: `<template #remaining-character-count-text="{ count }">{{ n__('%d character remaining', '%d characters remaining', count) }}</template>`
127
+ @slot Internationalized character count text. Example: `<template #remaining-character-count-text="{ count }">{{ n__('%d character remaining.', '%d characters remaining.', count) }}</template>`
128
128
  @binding {number} count
129
129
  -->
130
130
 
@@ -0,0 +1,71 @@
1
+ <script>
2
+ import GlDuoChatContextItemPopover from '../duo_chat_context_item_popover/duo_chat_context_item_popover.vue';
3
+ import GlIcon from '../../../../../../base/icon/icon.vue';
4
+ import {
5
+ categoryValidator,
6
+ contextItemValidator,
7
+ formatIssueId,
8
+ formatMergeRequestId,
9
+ } from '../utils';
10
+ import {
11
+ CONTEXT_ITEM_TYPE_ISSUE,
12
+ CONTEXT_ITEM_TYPE_MERGE_REQUEST,
13
+ CONTEXT_ITEM_TYPE_PROJECT_FILE,
14
+ } from '../constants';
15
+
16
+ export default {
17
+ name: 'GlDuoChatContextItemMenuSearchItem',
18
+ components: { GlIcon, GlDuoChatContextItemPopover },
19
+ props: {
20
+ category: {
21
+ type: Object,
22
+ required: true,
23
+ validator: categoryValidator,
24
+ },
25
+ contextItem: {
26
+ type: Object,
27
+ required: true,
28
+ validator: contextItemValidator,
29
+ },
30
+ },
31
+ computed: {
32
+ title() {
33
+ return this.contextItem.metadata?.name || '';
34
+ },
35
+ secondaryText() {
36
+ switch (this.category.value) {
37
+ case CONTEXT_ITEM_TYPE_PROJECT_FILE:
38
+ return this.contextItem.metadata.info.relFilePath;
39
+ case CONTEXT_ITEM_TYPE_ISSUE:
40
+ return formatIssueId(this.contextItem.metadata.info.iid);
41
+ case CONTEXT_ITEM_TYPE_MERGE_REQUEST:
42
+ return formatMergeRequestId(this.contextItem.metadata.info.iid);
43
+ default:
44
+ return '';
45
+ }
46
+ },
47
+ },
48
+ };
49
+ </script>
50
+ <template>
51
+ <div class="gl-flex gl-flex-col">
52
+ <div class="gl-flex gl-items-center">
53
+ <gl-icon :name="category.icon" class="gl-mr-2 gl-shrink-0" data-testid="category-icon" />
54
+ <span>{{ title }}</span>
55
+ <gl-icon
56
+ :id="`info-icon-${contextItem.id}`"
57
+ name="information-o"
58
+ class="gl-ml-2 gl-shrink-0 gl-cursor-pointer gl-text-secondary"
59
+ :size="12"
60
+ />
61
+ <gl-duo-chat-context-item-popover
62
+ :context-item="contextItem"
63
+ :target="`info-icon-${contextItem.id}`"
64
+ placement="left"
65
+ />
66
+ </div>
67
+ <div class="gl-mt-1 gl-shrink-0 gl-whitespace-nowrap gl-text-secondary">
68
+ {{ secondaryText }}
69
+ </div>
70
+ </div>
71
+ </template>
@@ -5,14 +5,16 @@ import GlAlert from '../../../../../../base/alert/alert.vue';
5
5
  import { sprintf, translate } from '../../../../../../../utils/i18n';
6
6
  import { categoryValidator, contextItemsValidator } from '../utils';
7
7
  import GlDuoChatContextItemMenuSearchItemsLoading from './duo_chat_context_item_menu_search_items_loading.vue';
8
+ import GlDuoChatContextItemMenuSearchItem from './duo_chat_context_item_menu_search_item.vue';
8
9
 
9
10
  export default {
10
11
  name: 'GlDuoChatContextItemMenuSearchItems',
11
12
  components: {
12
13
  GlAlert,
13
- GlFormInput,
14
14
  GlDropdownItem,
15
+ GlDuoChatContextItemMenuSearchItem,
15
16
  GlDuoChatContextItemMenuSearchItemsLoading,
17
+ GlFormInput,
16
18
  },
17
19
  model: {
18
20
  prop: 'searchQuery',
@@ -77,8 +79,8 @@ export default {
77
79
  },
78
80
  },
79
81
  methods: {
80
- selectItem(item) {
81
- this.$emit('select', item);
82
+ selectItem(contextItem) {
83
+ this.$emit('select', contextItem);
82
84
  this.userInitiatedSearch = false;
83
85
  },
84
86
  setActiveIndex(index) {
@@ -114,20 +116,25 @@ export default {
114
116
  </div>
115
117
  <ul v-else class="gl-mb-1 gl-list-none gl-flex-row gl-pl-0">
116
118
  <gl-dropdown-item
117
- v-for="(item, index) in results"
119
+ v-for="(contextItem, index) in results"
118
120
  :id="`dropdown-item-${index}`"
119
- :key="item.id"
120
- :class="[{ 'active-command': index === activeIndex, disabled: !item.isEnabled }]"
121
- :tabindex="!item.isEnabled ? -1 : undefined"
121
+ :key="contextItem.id"
122
+ :class="{
123
+ 'active-command': index === activeIndex,
124
+ 'gl-cursor-not-allowed [&>button]:focus-within:!gl-shadow-none': !contextItem.isEnabled,
125
+ }"
126
+ :tabindex="!contextItem.isEnabled ? -1 : undefined"
122
127
  class="duo-chat-context-search-result-item"
123
128
  data-testid="search-result-item"
124
- @click="selectItem(item)"
129
+ @click="selectItem(contextItem)"
125
130
  >
126
131
  <div @mouseenter="setActiveIndex(index)">
127
- <div data-testid="search-result-item-details">
128
- <!-- Placeholder for upcoming GlDuoChatContextItemMenuSearchItem component -->
129
- {{ item.metadata.name }} {{ item.isEnabled ? '' : '(disabled)' }}
130
- </div>
132
+ <gl-duo-chat-context-item-menu-search-item
133
+ :context-item="contextItem"
134
+ :category="category"
135
+ :class="{ 'gl-text-secondary': !contextItem.isEnabled }"
136
+ data-testid="search-result-item-details"
137
+ />
131
138
  </div>
132
139
  </gl-dropdown-item>
133
140
  </ul>
@@ -6,11 +6,7 @@ import {
6
6
  CONTEXT_ITEM_TYPE_MERGE_REQUEST,
7
7
  CONTEXT_ITEM_TYPE_PROJECT_FILE,
8
8
  } from '../constants';
9
-
10
- const ID_PREFIXES = {
11
- issue: '#',
12
- merge_request: '!',
13
- };
9
+ import { formatIssueId, formatMergeRequestId } from '../utils';
14
10
 
15
11
  export default {
16
12
  name: 'DuoChatContextItemPopover',
@@ -19,9 +15,9 @@ export default {
19
15
  },
20
16
  props: {
21
17
  /**
22
- * The context item to display in the popover.
18
+ * The context contextItem to display in the popover.
23
19
  */
24
- item: {
20
+ contextItem: {
25
21
  type: Object,
26
22
  required: true,
27
23
  },
@@ -43,28 +39,36 @@ export default {
43
39
  },
44
40
  computed: {
45
41
  itemInfo() {
46
- return this.item.metadata?.info || {};
42
+ return this.contextItem.metadata?.info || {};
47
43
  },
48
44
  id() {
49
45
  const isIssuable =
50
- this.item.type === CONTEXT_ITEM_TYPE_ISSUE ||
51
- this.item.type === CONTEXT_ITEM_TYPE_MERGE_REQUEST;
46
+ this.contextItem.type === CONTEXT_ITEM_TYPE_ISSUE ||
47
+ this.contextItem.type === CONTEXT_ITEM_TYPE_MERGE_REQUEST;
52
48
  return isIssuable ? this.itemInfo.iid || '' : null;
53
49
  },
54
- idPrefix() {
55
- return ID_PREFIXES[this.item.type] || '';
50
+ formattedId() {
51
+ switch (this.contextItem.type) {
52
+ case CONTEXT_ITEM_TYPE_ISSUE:
53
+ return formatIssueId(this.id);
54
+ case CONTEXT_ITEM_TYPE_MERGE_REQUEST:
55
+ return formatMergeRequestId(this.id);
56
+ default:
57
+ return '';
58
+ }
56
59
  },
57
60
  filePath() {
58
- return this.item.type === CONTEXT_ITEM_TYPE_PROJECT_FILE
61
+ return this.contextItem.type === CONTEXT_ITEM_TYPE_PROJECT_FILE
59
62
  ? this.itemInfo.relFilePath || ''
60
63
  : null;
61
64
  },
62
65
  isEnabled() {
63
- return this.item.isEnabled !== false;
66
+ return this.contextItem.isEnabled !== false;
64
67
  },
65
68
  disabledMessage() {
66
- return Array.isArray(this.item.disabledReasons) && this.item.disabledReasons.length > 0
67
- ? this.item.disabledReasons.join(', ')
69
+ return Array.isArray(this.contextItem.disabledReasons) &&
70
+ this.contextItem.disabledReasons.length > 0
71
+ ? this.contextItem.disabledReasons.join(', ')
68
72
  : translate('DuoChatContextItemPopover.DisabledReason', 'This item is disabled');
69
73
  },
70
74
  },
@@ -78,12 +82,12 @@ export default {
78
82
  :target="target"
79
83
  triggers="hover focus"
80
84
  :placement="placement"
81
- :title="item.metadata.name"
85
+ :title="contextItem.metadata.name"
82
86
  custom-class="gl-duo-chat-item-popover"
83
87
  >
84
88
  <template #title>
85
89
  <span class="gl-text-sm gl-text-gray-500" data-testid="chat-context-popover-title">{{
86
- item.metadata.name
90
+ contextItem.metadata.name
87
91
  }}</span>
88
92
  </template>
89
93
  <div class="gl-p-3">
@@ -101,13 +105,13 @@ export default {
101
105
  </div>
102
106
  <div v-if="id !== null" class="gl-mb-2">
103
107
  <strong class="gl-mr-1">{{ translate('DuoChatContextItemPopover.IdLabel', 'ID:') }}</strong>
104
- <span>{{ idPrefix }}{{ id }}</span>
108
+ <span>{{ formattedId }}</span>
105
109
  </div>
106
110
  <div class="gl-mb-2">
107
111
  <strong class="gl-mr-1">{{
108
112
  translate('DuoChatContextItemPopover.TypeLabel', 'Type:')
109
113
  }}</strong>
110
- <span>{{ item.type }}</span>
114
+ <span>{{ contextItem.type }}</span>
111
115
  </div>
112
116
  <div v-if="!isEnabled" class="gl-text-red-500" data-testid="chat-context-popover-disabled">
113
117
  <strong class="gl-mr-1">{{
@@ -72,12 +72,12 @@ export default {
72
72
  toggleCollapse() {
73
73
  this.isCollapsed = !this.isCollapsed;
74
74
  },
75
- onRemoveItem(item) {
75
+ onRemoveItem(contextItem) {
76
76
  /**
77
- * Emitted when a context item should be removed.
78
- * @property {Object} item - The context item to be removed
77
+ * Emitted when a context contextItem should be removed.
78
+ * @property {Object} item - The context contextItem to be removed
79
79
  */
80
- this.$emit('remove', item);
80
+ this.$emit('remove', contextItem);
81
81
  },
82
82
  },
83
83
  };
@@ -99,20 +99,20 @@ export default {
99
99
  data-testid="chat-context-tokens-wrapper"
100
100
  >
101
101
  <gl-token
102
- v-for="item in selections"
103
- :key="item.id"
102
+ v-for="contextItem in selections"
103
+ :key="contextItem.id"
104
104
  :view-only="!removable"
105
105
  variant="default"
106
106
  class="gl-mb-2 gl-mr-2"
107
- @close="onRemoveItem(item)"
107
+ @close="onRemoveItem(contextItem)"
108
108
  >
109
- <div :id="`context-item-${item.id}-${selectionsId}`" class="gl-flex gl-items-center">
110
- <gl-icon :name="getIconName(item.type)" :size="12" class="gl-mr-1" />
111
- {{ item.metadata.name }}
109
+ <div :id="`context-item-${contextItem.id}-${selectionsId}`" class="gl-flex gl-items-center">
110
+ <gl-icon :name="getIconName(contextItem.type)" :size="12" class="gl-mr-1" />
111
+ {{ contextItem.metadata.name }}
112
112
  </div>
113
113
  <gl-duo-chat-context-item-popover
114
- :item="item"
115
- :target="`context-item-${item.id}-${selectionsId}`"
114
+ :context-item="contextItem"
115
+ :target="`context-item-${contextItem.id}-${selectionsId}`"
116
116
  placement="bottom"
117
117
  />
118
118
  </gl-token>
@@ -10,6 +10,10 @@ export const MOCK_CATEGORIES = [
10
10
  { label: 'Merge Requests', value: CONTEXT_ITEM_TYPE_MERGE_REQUEST, icon: 'merge-request' },
11
11
  ];
12
12
 
13
+ export function getMockCategory(categoryValue) {
14
+ return MOCK_CATEGORIES.find((cat) => cat.value === categoryValue);
15
+ }
16
+
13
17
  export const MOCK_CONTEXT_ITEM_FILE = {
14
18
  id: '123e4567-e89b-12d3-a456-426614174000',
15
19
  isEnabled: true,
@@ -27,3 +27,15 @@ export function contextItemValidator(item) {
27
27
  export function contextItemsValidator(items) {
28
28
  return Array.isArray(items) && items.every((item) => contextItemValidator(item));
29
29
  }
30
+
31
+ export function formatIssueId(iid) {
32
+ if (!iid) return '';
33
+
34
+ return `#${iid}`;
35
+ }
36
+
37
+ export function formatMergeRequestId(iid) {
38
+ if (!iid) return '';
39
+
40
+ return `!${iid}`;
41
+ }
@@ -27,7 +27,7 @@
27
27
  position: absolute;
28
28
  @include gl-transition-medium;
29
29
  @include gl-opacity-0;
30
- right: $gl-spacing-scale-4;
30
+ right: $gl-spacing-scale-3;
31
31
  top: $gl-spacing-scale-3;
32
32
  }
33
33
 
@@ -62,4 +62,4 @@
62
62
  copy-code {
63
63
  margin-right: 0;
64
64
  }
65
- }
65
+ }
@@ -33,6 +33,19 @@
33
33
  "$type": "color",
34
34
  "$description": "Used to identify a disabled section."
35
35
  },
36
+ "overlap": {
37
+ "$value": {
38
+ "default": "{color.neutral.0}",
39
+ "dark": "{color.neutral.800}"
40
+ },
41
+ "$type": "color",
42
+ "$description": "Used for components, like tooltips and drawers, and content, like a sticky header, that overlap other content."
43
+ },
44
+ "section": {
45
+ "$value": "{background.color.overlap}",
46
+ "$type": "color",
47
+ "$description": "Used for containers, like a card header, that are visually distinct from the default page background only when necessary to maintain affordance and hierarchy in different modes."
48
+ },
36
49
  "overlay": {
37
50
  "$value": {
38
51
  "default": "{color.alpha.dark.24}",
@@ -25,6 +25,14 @@
25
25
  "$type": "color",
26
26
  "$description": "Used for a distinct border that emphasizes an edge or boundaries."
27
27
  },
28
+ "section": {
29
+ "$value": {
30
+ "default": "{border.color.default}",
31
+ "dark": "{background.color.default}"
32
+ },
33
+ "$type": "color",
34
+ "$description": "Used for the border color that surrounds content or elements when they appear as a closed container or closed section of the page."
35
+ },
28
36
  "transparent": {
29
37
  "$value": "{color.alpha.0}",
30
38
  "$type": "color",
@@ -723,6 +723,7 @@
723
723
  --gl-border-color-subtle: var(--gl-color-neutral-50); /* Used for a subtle border in combination with the default background. */
724
724
  --gl-border-color-default: var(--gl-color-neutral-100); /* Used for the default border color. */
725
725
  --gl-background-color-overlay: var(--gl-color-alpha-dark-24); /* Used for an overlay that covers other content. */
726
+ --gl-background-color-overlap: var(--gl-color-neutral-0); /* Used for components, like tooltips and drawers, and content, like a sticky header, that overlap other content. */
726
727
  --gl-background-color-disabled: var(--gl-color-neutral-10); /* Used to identify a disabled section. */
727
728
  --gl-background-color-strong: var(--gl-color-neutral-50); /* Used to make the background easily stand out from the default. */
728
729
  --gl-background-color-subtle: var(--gl-color-neutral-10); /* Used to slightly differentiate the background from the default. */
@@ -836,6 +837,8 @@
836
837
  --gl-alert-info-title-color: var(--gl-text-color-heading); /* Used for the title color of an info alert. */
837
838
  --gl-alert-neutral-background-color: var(--gl-feedback-neutral-background-color); /* Used for the background color of a neutral alert. */
838
839
  --gl-alert-neutral-title-color: var(--gl-text-color-heading); /* Used for the title color of a neutral alert. */
840
+ --gl-border-color-section: var(--gl-border-color-default); /* Used for the border color that surrounds content or elements when they appear as a closed container or closed section of the page. */
841
+ --gl-background-color-section: var(--gl-background-color-overlap); /* Used for containers, like a card header, that are visually distinct from the default page background only when necessary to maintain affordance and hierarchy in different modes. */
839
842
  --gl-action-strong-neutral-border-color-hover: var(--gl-action-strong-neutral-border-color-default); /* Used for the border of a strong neutral action in the hover state. */
840
843
  --gl-action-strong-neutral-foreground-color-hover: var(--gl-action-strong-neutral-foreground-color-default); /* Used for the foreground of a strong neutral action in the hover state. */
841
844
  --gl-action-strong-neutral-background-color-focus: var(--gl-action-strong-neutral-background-color-hover); /* Used for the background of a strong neutral action in the focus state. */