@gitlab/ui 126.3.0 → 126.3.2

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 (46) hide show
  1. package/dist/components/base/avatars_inline/avatars_inline.js +21 -0
  2. package/dist/components/base/badge/badge.js +10 -7
  3. package/dist/components/base/button/button.js +4 -1
  4. package/dist/components/base/drawer/drawer.js +19 -0
  5. package/dist/components/base/dropdown/dropdown_item.js +34 -0
  6. package/dist/components/base/filtered_search/filtered_search.js +4 -2
  7. package/dist/components/base/form/form_input_group/form_input_group.js +6 -0
  8. package/dist/components/base/icon/icon.js +4 -2
  9. package/dist/components/base/illustration/illustration.js +4 -2
  10. package/dist/components/base/label/label.js +26 -6
  11. package/dist/components/base/modal/modal.js +4 -1
  12. package/dist/components/base/new_dropdowns/base_dropdown/base_dropdown.js +8 -4
  13. package/dist/components/base/new_dropdowns/listbox/listbox.js +4 -3
  14. package/dist/components/base/popover/popover.js +15 -0
  15. package/dist/components/base/progress_bar/progress_bar.js +15 -0
  16. package/dist/components/base/search_box_by_type/search_box_by_type.js +20 -0
  17. package/dist/components/base/table/table.js +4 -1
  18. package/dist/components/base/tabs/tab/tab.js +33 -2
  19. package/dist/components/base/token/token.js +3 -0
  20. package/dist/components/dashboards/dashboard_layout/dashboard_layout.js +27 -1
  21. package/dist/components/dashboards/dashboard_layout/grid_layout/grid_layout.js +28 -6
  22. package/dist/utils/utils.js +14 -7
  23. package/package.json +4 -4
  24. package/src/components/base/avatars_inline/avatars_inline.vue +22 -0
  25. package/src/components/base/badge/badge.vue +9 -8
  26. package/src/components/base/button/button.vue +4 -4
  27. package/src/components/base/drawer/drawer.vue +23 -0
  28. package/src/components/base/dropdown/dropdown.vue +2 -2
  29. package/src/components/base/dropdown/dropdown_item.vue +35 -0
  30. package/src/components/base/filtered_search/filtered_search.vue +3 -2
  31. package/src/components/base/form/form_input_group/form_input_group.vue +6 -0
  32. package/src/components/base/icon/icon.vue +2 -2
  33. package/src/components/base/illustration/illustration.vue +4 -2
  34. package/src/components/base/label/label.vue +26 -6
  35. package/src/components/base/modal/modal.vue +8 -8
  36. package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.vue +7 -4
  37. package/src/components/base/new_dropdowns/listbox/listbox.vue +3 -3
  38. package/src/components/base/popover/popover.vue +20 -1
  39. package/src/components/base/progress_bar/progress_bar.vue +15 -0
  40. package/src/components/base/search_box_by_type/search_box_by_type.vue +18 -0
  41. package/src/components/base/table/table.vue +1 -1
  42. package/src/components/base/tabs/tab/tab.vue +47 -2
  43. package/src/components/base/token/token.vue +4 -0
  44. package/src/components/dashboards/dashboard_layout/dashboard_layout.vue +29 -0
  45. package/src/components/dashboards/dashboard_layout/grid_layout/grid_layout.vue +29 -6
  46. package/src/utils/utils.js +10 -5
@@ -1,5 +1,7 @@
1
1
  import isPlainObject from 'lodash/isPlainObject';
2
2
  import { BTab } from '../../../../vendor/bootstrap-vue/src/components/tabs/tab';
3
+ import GlBadge from '../../badge/badge';
4
+ import { logWarning } from '../../../../utils/utils';
3
5
  import { DEFAULT_TAB_TITLE_LINK_CLASS } from '../constants';
4
6
  import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
5
7
 
@@ -8,7 +10,8 @@ import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
8
10
  var script = {
9
11
  name: 'GlTab',
10
12
  components: {
11
- BTab
13
+ BTab,
14
+ GlBadge
12
15
  },
13
16
  inheritAttrs: false,
14
17
  props: {
@@ -24,6 +27,24 @@ var script = {
24
27
  type: String,
25
28
  required: false,
26
29
  default: null
30
+ },
31
+ /**
32
+ * Display a count badge next to the tab title.
33
+ */
34
+ tabCount: {
35
+ type: Number,
36
+ required: false,
37
+ default: null
38
+ },
39
+ /**
40
+ * Screen reader text to provide context for the tab count value.
41
+ * Should be the result of calling n__() with the count.
42
+ * Example: :tab-count-sr-text="n__('%d changed file', '%d changed files', count)"
43
+ */
44
+ tabCountSrText: {
45
+ type: String,
46
+ required: false,
47
+ default: null
27
48
  }
28
49
  },
29
50
  computed: {
@@ -41,6 +62,16 @@ var script = {
41
62
  };
42
63
  }
43
64
  return `${titleLinkClass} ${DEFAULT_TAB_TITLE_LINK_CLASS}`.trim();
65
+ },
66
+ hasTabCount() {
67
+ return this.tabCount != null && this.tabCount >= 0;
68
+ }
69
+ },
70
+ created() {
71
+ if (this.hasTabCount && !this.tabCountSrText) {
72
+ logWarning('When using "tab-count", you should also provide "tab-count-sr-text" for screen reader accessibility. Example: :tab-count-sr-text="n__(\'%d item\', \'%d items\', count)"', {
73
+ name: 'GlTab'
74
+ });
44
75
  }
45
76
  }
46
77
  };
@@ -49,7 +80,7 @@ var script = {
49
80
  const __vue_script__ = script;
50
81
 
51
82
  /* template */
52
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('b-tab',_vm._g(_vm._b({attrs:{"title-link-class":_vm.linkClass,"query-param-value":_vm.queryParamValue},scopedSlots:_vm._u([_vm._l((Object.keys(_vm.$slots)),function(slot){return {key:slot,fn:function(){return [_vm._t(slot)]},proxy:true}})],null,true)},'b-tab',_vm.$attrs,false),_vm.$listeners))};
83
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('b-tab',_vm._g(_vm._b({attrs:{"title":_vm.hasTabCount ? null : _vm.$attrs.title,"title-link-class":_vm.linkClass,"query-param-value":_vm.queryParamValue},scopedSlots:_vm._u([(_vm.hasTabCount)?{key:"title",fn:function(){return [_vm._t("title",function(){return [_vm._v(_vm._s(_vm.$attrs.title))]}),_vm._v(" "),_c('gl-badge',{staticClass:"gl-ml-2",attrs:{"variant":"neutral","aria-hidden":"true","data-testid":"tab-counter-badge"}},[_vm._v("\n "+_vm._s(_vm.tabCount)+"\n ")]),_vm._v(" "),(_vm.tabCountSrText)?_c('span',{staticClass:"gl-sr-only"},[_vm._v(_vm._s(_vm.tabCountSrText))]):_vm._e()]},proxy:true}:null,_vm._l((Object.keys(_vm.$scopedSlots)),function(slot){return {key:slot,fn:function(){return [_vm._t(slot)]},proxy:true}})],null,true)},'b-tab',_vm.$attrs,false),_vm.$listeners))};
53
84
  var __vue_staticRenderFns__ = [];
54
85
 
55
86
  /* style */
@@ -11,6 +11,9 @@ var script = {
11
11
  CloseButton
12
12
  },
13
13
  props: {
14
+ /**
15
+ * When true, hides the close button and makes the token non-removable.
16
+ */
14
17
  viewOnly: {
15
18
  type: Boolean,
16
19
  required: false,
@@ -34,6 +34,32 @@ var script = {
34
34
  type: Boolean,
35
35
  required: false,
36
36
  default: true
37
+ },
38
+ /**
39
+ * Adjusts the cell height of the grid. Setting this too high can leave unwanted whitespace
40
+ * between grid panels. Reduce the number to allow for a more compact grid.
41
+ * For more information, see:
42
+ * https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/issues/3051
43
+ */
44
+ cellHeight: {
45
+ type: Number,
46
+ required: false,
47
+ /* Magic number:
48
+ * After allowing for padding, and the panel title row, this leaves us with minimum 48px height for the cell content.
49
+ * This means text/content with our spacing scale can fit up to 49px without scrolling.
50
+ */
51
+ default: 137,
52
+ validator: value => value > 0
53
+ },
54
+ /**
55
+ * Sets a default minimum height for grid panels. This can still be overriden on a per-panel
56
+ * basis by setting `value.panels[].gridAttributes.minHeight`
57
+ */
58
+ minCellHeight: {
59
+ type: Number,
60
+ required: false,
61
+ default: 1,
62
+ validator: value => value > 0
37
63
  }
38
64
  },
39
65
  computed: {
@@ -56,7 +82,7 @@ var script = {
56
82
  const __vue_script__ = script;
57
83
 
58
84
  /* template */
59
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('section',{staticClass:"gl-my-4 gl-flex gl-items-center"},[_vm._t("header",function(){return [_c('div',{staticClass:"gl-flex gl-w-full gl-flex-col"},[_c('div',{staticClass:"gl-flex gl-items-center"},[_vm._t("title",function(){return [_c('h2',{staticClass:"gl-my-0",attrs:{"data-testid":"title"}},[_vm._v(_vm._s(_vm.config.title))])]})],2),_vm._v(" "),(_vm.dashboardHasDescription)?_c('div',{staticClass:"gl-mt-3 gl-flex"},[_vm._t("description",function(){return [_c('p',{staticClass:"gl-mb-0",attrs:{"data-testid":"description"}},[_vm._v("\n "+_vm._s(_vm.config.description)+"\n ")])]})],2):_vm._e()])]}),_vm._v(" "),(_vm.$scopedSlots.actions)?_c('div',{attrs:{"data-testid":"actions-container"}},[_vm._t("actions")],2):_vm._e()],2),_vm._v(" "),_c('div',{staticClass:"gl-flex"},[_c('div',{staticClass:"gl-flex gl-grow gl-flex-col"},[_vm._t("alert"),_vm._v(" "),(_vm.$scopedSlots.filters)?_c('section',{staticClass:"gl-flex gl-flex-row gl-flex-wrap gl-gap-5 gl-pb-3 gl-pt-4",attrs:{"data-testid":"filters-container"}},[_vm._t("filters")],2):_vm._e(),_vm._v(" "),(_vm.dashboardHasPanels)?_c('grid-layout',{staticClass:"-gl-mx-3",attrs:{"value":_vm.config,"is-static-grid":_vm.isStaticGrid},on:{"input":_vm.emitChanges},scopedSlots:_vm._u([{key:"panel",fn:function(ref){
85
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('section',{staticClass:"gl-my-4 gl-flex gl-items-center"},[_vm._t("header",function(){return [_c('div',{staticClass:"gl-flex gl-w-full gl-flex-col"},[_c('div',{staticClass:"gl-flex gl-items-center"},[_vm._t("title",function(){return [_c('h2',{staticClass:"gl-my-0",attrs:{"data-testid":"title"}},[_vm._v(_vm._s(_vm.config.title))])]})],2),_vm._v(" "),(_vm.dashboardHasDescription)?_c('div',{staticClass:"gl-mt-3 gl-flex"},[_vm._t("description",function(){return [_c('p',{staticClass:"gl-mb-0",attrs:{"data-testid":"description"}},[_vm._v("\n "+_vm._s(_vm.config.description)+"\n ")])]})],2):_vm._e()])]}),_vm._v(" "),(_vm.$scopedSlots.actions)?_c('div',{attrs:{"data-testid":"actions-container"}},[_vm._t("actions")],2):_vm._e()],2),_vm._v(" "),_c('div',{staticClass:"gl-flex"},[_c('div',{staticClass:"gl-flex gl-grow gl-flex-col"},[_vm._t("alert"),_vm._v(" "),(_vm.$scopedSlots.filters)?_c('section',{staticClass:"gl-flex gl-flex-row gl-flex-wrap gl-gap-5 gl-pb-3 gl-pt-4",attrs:{"data-testid":"filters-container"}},[_vm._t("filters")],2):_vm._e(),_vm._v(" "),(_vm.dashboardHasPanels)?_c('grid-layout',{staticClass:"-gl-mx-3",attrs:{"value":_vm.config,"is-static-grid":_vm.isStaticGrid,"cell-height":_vm.cellHeight,"min-cell-height":_vm.minCellHeight},on:{"input":_vm.emitChanges},scopedSlots:_vm._u([{key:"panel",fn:function(ref){
60
86
  var panel = ref.panel;
61
87
  return [_vm._t("panel",null,null,{ panel: panel })]}}],null,true)}):_vm._t("empty-state")],2)]),_vm._v(" "),_vm._t("footer")],2)};
62
88
  var __vue_staticRenderFns__ = [];
@@ -33,6 +33,32 @@ var script = {
33
33
  type: Boolean,
34
34
  required: false,
35
35
  default: true
36
+ },
37
+ /**
38
+ * Adjusts the cell height of the grid. Setting this too high can leave unwanted whitespace
39
+ * between grid panels. Reduce the number to allow for a more compact grid.
40
+ * For more information, see:
41
+ * https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/issues/3051
42
+ */
43
+ cellHeight: {
44
+ type: Number,
45
+ required: false,
46
+ /* Magic number:
47
+ * After allowing for padding, and the panel title row, this leaves us with minimum 48px height for the cell content.
48
+ * This means text/content with our spacing scale can fit up to 49px without scrolling.
49
+ */
50
+ default: 137,
51
+ validator: value => value > 0
52
+ },
53
+ /**
54
+ * Sets a default minimum height for grid panels. This can still be overriden on a per-panel
55
+ * basis by setting `value.panels[].gridAttributes.minHeight`
56
+ */
57
+ minCellHeight: {
58
+ type: Number,
59
+ required: false,
60
+ default: 1,
61
+ validator: value => value > 0
36
62
  }
37
63
  },
38
64
  data() {
@@ -144,11 +170,6 @@ var script = {
144
170
  margin: '8px',
145
171
  // CSS Selector for finding the drag handle element
146
172
  handle: '.grid-stack-item-handle',
147
- /* Magic number:
148
- * After allowing for padding, and the panel title row, this leaves us with minimum 48px height for the cell content.
149
- * This means text/content with our spacing scale can fit up to 49px without scrolling.
150
- */
151
- cellHeight: '137px',
152
173
  // Setting 1 in minRow prevents the grid collapsing when all panels are removed
153
174
  minRow: 1,
154
175
  // Define the number of columns for anything below a set width, defaults to fill the available space
@@ -158,6 +179,7 @@ var script = {
158
179
  c: 1
159
180
  }]
160
181
  },
182
+ cellHeight: this.cellHeight,
161
183
  alwaysShowResizeHandle: true,
162
184
  animate: true,
163
185
  float: true,
@@ -206,7 +228,7 @@ var script = {
206
228
  y: yPos,
207
229
  w: width,
208
230
  h: height,
209
- minH: minHeight,
231
+ minH: minHeight || this.minCellHeight,
210
232
  minW: minWidth,
211
233
  maxH: maxHeight,
212
234
  maxW: maxWidth,
@@ -157,14 +157,21 @@ function isDev() {
157
157
 
158
158
  /**
159
159
  * Prints a warning message to the console in non-test and non-production environments.
160
- * @param {string} message message to print to the console
161
- * @param {HTMLElement} element component that triggered the warning
160
+ * @param {string} message Message to print to the console.
161
+ * @param {Object} [context] Optional object with additional context.
162
+ * @param {string} [context.name] The name of the context of the message. Usually the component's name.
163
+ * @param {HTMLElement} [context.element] The element relevant to the message.
162
164
  */
163
- function logWarning() {
164
- let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
165
- let element = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
166
- if (message.length && isDev()) {
167
- console.warn(message, element); // eslint-disable-line no-console
165
+ function logWarning(message) {
166
+ let context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
167
+ if (isDev()) {
168
+ const {
169
+ name,
170
+ element
171
+ } = context;
172
+ const formattedMessage = name ? `[${name}] ${message}` : message;
173
+ const args = element ? [formattedMessage, element] : [formattedMessage];
174
+ console.warn(...args); // eslint-disable-line no-console
168
175
  }
169
176
  }
170
177
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "126.3.0",
3
+ "version": "126.3.2",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -146,8 +146,8 @@
146
146
  "mockdate": "^3.0.5",
147
147
  "module-alias": "^2.2.3",
148
148
  "pikaday": "^1.8.0",
149
- "playwright": "^1.55.1",
150
- "playwright-core": "^1.55.1",
149
+ "playwright": "^1.57.0",
150
+ "playwright-core": "^1.57.0",
151
151
  "postcss": "8.5.6",
152
152
  "postcss-loader": "8.2.0",
153
153
  "postcss-scss": "4.0.9",
@@ -159,7 +159,7 @@
159
159
  "rollup-plugin-string": "^3.0.0",
160
160
  "rollup-plugin-svg": "^2.0.0",
161
161
  "rollup-plugin-vue": "^5.1.9",
162
- "sass": "^1.94.1",
162
+ "sass": "^1.94.2",
163
163
  "sass-loader": "^10.5.2",
164
164
  "sass-true": "^9",
165
165
  "start-server-and-test": "^2.1.3",
@@ -12,33 +12,54 @@ export default {
12
12
  GlTooltip,
13
13
  },
14
14
  props: {
15
+ /**
16
+ * Array of avatar objects to display
17
+ */
15
18
  avatars: {
16
19
  type: Array,
17
20
  required: true,
18
21
  },
22
+ /**
23
+ * Maximum number of avatars to display before collapsing
24
+ */
19
25
  maxVisible: {
20
26
  type: Number,
21
27
  required: true,
22
28
  },
29
+ /**
30
+ * Size of each avatar in pixels
31
+ */
23
32
  avatarSize: {
24
33
  type: Number,
25
34
  required: true,
26
35
  validator: (value) => avatarsInlineSizeOptions.includes(value),
27
36
  },
37
+ /**
38
+ * Whether to show the avatars in collapsed state
39
+ */
28
40
  collapsed: {
29
41
  type: Boolean,
30
42
  required: false,
31
43
  default: false,
32
44
  },
45
+ /**
46
+ * Screen reader text for the collapsed avatars badge
47
+ */
33
48
  badgeSrOnlyText: {
34
49
  type: String,
35
50
  required: true,
36
51
  },
52
+ /**
53
+ * Property name to extract tooltip text from each hidden avatar object
54
+ */
37
55
  badgeTooltipProp: {
38
56
  type: String,
39
57
  required: false,
40
58
  default: '',
41
59
  },
60
+ /**
61
+ * Maximum number of characters to display in the badge tooltip
62
+ */
42
63
  badgeTooltipMaxChars: {
43
64
  type: Number,
44
65
  required: false,
@@ -88,6 +109,7 @@ export default {
88
109
  <template>
89
110
  <div class="gl-avatars-inline" :class="`gl-avatars-inline-${badgeSize}`">
90
111
  <div v-for="(avatar, index) in visibleAvatars" :key="index" class="gl-avatars-inline-child">
112
+ <!-- @slot Custom avatar rendering. Provide avatar object as slot prop. -->
91
113
  <slot name="avatar" :avatar="avatar">
92
114
  <gl-avatar v-bind="avatar" :size="avatarSize" />
93
115
  </slot>
@@ -7,6 +7,7 @@ import {
7
7
  linkVariantUnstyled,
8
8
  } from '../../../utils/constants';
9
9
  import GlIcon from '../icon/icon.vue';
10
+ import { logWarning } from '../../../utils/utils';
10
11
 
11
12
  const variantClass = {
12
13
  [badgeVariantOptions.neutral]: 'badge-neutral',
@@ -120,13 +121,6 @@ export default {
120
121
  role() {
121
122
  return this.hasIconOnly ? 'img' : undefined;
122
123
  },
123
- ariaLabel() {
124
- if (this.$attrs['aria-label']) {
125
- return this.$attrs['aria-label'];
126
- }
127
-
128
- return this.role === 'img' ? this.icon : undefined;
129
- },
130
124
  iconSizeComputed() {
131
125
  return badgeIconSizeOptions[this.iconSize];
132
126
  },
@@ -152,6 +146,14 @@ export default {
152
146
  ];
153
147
  },
154
148
  },
149
+ mounted() {
150
+ if (this.hasIconOnly && !this.$attrs['aria-label']) {
151
+ logWarning(
152
+ 'Icon-only badges require an aria-label for accessibility. The label should describe the metadata (e.g., "Due date", "Open issue"), not the icon name. See https://design.gitlab.com/components/badge#using-icon-only-badges',
153
+ { name: 'GlBadge', element: this.$el },
154
+ );
155
+ }
156
+ },
155
157
  };
156
158
  </script>
157
159
 
@@ -161,7 +163,6 @@ export default {
161
163
  v-bind="computedProps"
162
164
  :class="classes"
163
165
  :role="role"
164
- :aria-label="ariaLabel"
165
166
  v-on="$listeners"
166
167
  >
167
168
  <gl-icon
@@ -369,10 +369,10 @@ export default {
369
369
  mounted() {
370
370
  // eslint-disable-next-line @gitlab/vue-prefer-dollar-scopedslots
371
371
  if (!this.$slots.default && !this.$attrs['aria-label'] && !this.$props.label) {
372
- logWarning(
373
- '[gl-button]: Accessible name missing. Please add inner text or aria-label.',
374
- this.$el,
375
- );
372
+ logWarning('Accessible name missing. Please add inner text or aria-label.', {
373
+ name: 'GlButton',
374
+ element: this.$el,
375
+ });
376
376
  }
377
377
  },
378
378
  methods: {
@@ -10,25 +10,40 @@ export default {
10
10
  GlButton,
11
11
  },
12
12
  props: {
13
+ /**
14
+ * Controls the visibility state of the drawer.
15
+ */
13
16
  open: {
14
17
  type: Boolean,
15
18
  required: true,
16
19
  },
20
+ /**
21
+ * Height of the header element (e.g., '64px'). Used to position the drawer below a fixed header.
22
+ */
17
23
  headerHeight: {
18
24
  type: String,
19
25
  required: false,
20
26
  default: '',
21
27
  },
28
+ /**
29
+ * When true, makes the drawer header sticky so it remains visible when scrolling the drawer content.
30
+ */
22
31
  headerSticky: {
23
32
  type: Boolean,
24
33
  required: false,
25
34
  default: false,
26
35
  },
36
+ /**
37
+ * Z-index value for the drawer. Useful for controlling stacking order with other elements.
38
+ */
27
39
  zIndex: {
28
40
  type: Number,
29
41
  required: false,
30
42
  default: maxZIndex,
31
43
  },
44
+ /**
45
+ * Visual variant of the drawer.
46
+ */
32
47
  variant: {
33
48
  type: String,
34
49
  required: false,
@@ -93,6 +108,10 @@ export default {
93
108
  const ESC = 27;
94
109
 
95
110
  if (this.open && e.keyCode === ESC) {
111
+ /**
112
+ * Emits when drawer gets closed (by pressing ESC or clicking the close button).
113
+ * @event close
114
+ */
96
115
  this.$emit('close');
97
116
  }
98
117
  },
@@ -108,6 +127,7 @@ export default {
108
127
  :class="{ 'gl-drawer-header-sticky': headerSticky }"
109
128
  >
110
129
  <div class="gl-drawer-title">
130
+ <!-- @slot Content for the drawer title area in the header. -->
111
131
  <slot name="title"></slot>
112
132
  <gl-button
113
133
  category="tertiary"
@@ -118,6 +138,7 @@ export default {
118
138
  @click="$emit('close')"
119
139
  />
120
140
  </div>
141
+ <!-- @slot Additional content below the title in the header section. -->
121
142
  <slot name="header"></slot>
122
143
  </div>
123
144
  <div
@@ -127,6 +148,7 @@ export default {
127
148
  'gl-drawer-body-scrim': !shouldRenderFooter,
128
149
  }"
129
150
  >
151
+ <!-- @slot Main content of the drawer body. -->
130
152
  <slot></slot>
131
153
  </div>
132
154
  <div
@@ -134,6 +156,7 @@ export default {
134
156
  class="gl-drawer-footer gl-drawer-footer-sticky gl-drawer-body-scrim-on-footer"
135
157
  :style="{ zIndex }"
136
158
  >
159
+ <!-- @slot Content for the sticky footer at the bottom of the drawer. -->
137
160
  <slot name="footer"></slot>
138
161
  </div>
139
162
  </aside>
@@ -247,8 +247,8 @@ export default {
247
247
  isIconOnly() {
248
248
  return Boolean(
249
249
  this.icon &&
250
- (!this.text?.length || this.textSrOnly) &&
251
- !this.hasSlotContents('button-text'),
250
+ (!this.text?.length || this.textSrOnly) &&
251
+ !this.hasSlotContents('button-text'),
252
252
  );
253
253
  },
254
254
  isIconWithText() {
@@ -15,51 +15,81 @@ export default {
15
15
  },
16
16
  inheritAttrs: false,
17
17
  props: {
18
+ /**
19
+ * URL for the avatar image to display
20
+ */
18
21
  avatarUrl: {
19
22
  type: String,
20
23
  required: false,
21
24
  default: '',
22
25
  },
26
+ /**
27
+ * Color variant for the icon on the left side
28
+ */
23
29
  iconColor: {
24
30
  type: String,
25
31
  required: false,
26
32
  default: '',
27
33
  },
34
+ /**
35
+ * Name of the icon to display on the left side
36
+ */
28
37
  iconName: {
29
38
  type: String,
30
39
  required: false,
31
40
  default: '',
32
41
  },
42
+ /**
43
+ * Aria label for the right icon button
44
+ */
33
45
  iconRightAriaLabel: {
34
46
  type: String,
35
47
  required: false,
36
48
  default: '',
37
49
  },
50
+ /**
51
+ * Name of the icon to display on the right side
52
+ */
38
53
  iconRightName: {
39
54
  type: String,
40
55
  required: false,
41
56
  default: '',
42
57
  },
58
+ /**
59
+ * Whether the dropdown item is checked
60
+ */
43
61
  isChecked: {
44
62
  type: Boolean,
45
63
  required: false,
46
64
  default: false,
47
65
  },
66
+ /**
67
+ * Whether to show a check icon for this item
68
+ */
48
69
  isCheckItem: {
49
70
  type: Boolean,
50
71
  required: false,
51
72
  default: false,
52
73
  },
74
+ /**
75
+ * Whether to center the check icon vertically
76
+ */
53
77
  isCheckCentered: {
54
78
  type: Boolean,
55
79
  required: false,
56
80
  default: false,
57
81
  },
82
+ /**
83
+ * Secondary text to display below the main content
84
+ */
58
85
  secondaryText: {
59
86
  type: String,
60
87
  required: false,
61
88
  default: '',
62
89
  },
90
+ /**
91
+ * ARIA role for the dropdown item
92
+ */
63
93
  role: {
64
94
  type: String,
65
95
  required: false,
@@ -93,6 +123,10 @@ export default {
93
123
  },
94
124
  methods: {
95
125
  handleClickIconRight() {
126
+ /**
127
+ * Emitted when right icon is clicked.
128
+ * @event handleClickIconRight
129
+ */
96
130
  this.$emit('click-icon-right');
97
131
  },
98
132
  },
@@ -115,6 +149,7 @@ export default {
115
149
  <gl-icon v-if="iconName" :name="iconName" :class="['gl-dropdown-item-icon', iconColorCss]" />
116
150
  <gl-avatar v-if="avatarUrl" :size="32" :src="avatarUrl" />
117
151
  <div class="gl-dropdown-item-text-wrapper">
152
+ <!-- @slot Main content of the dropdown item. -->
118
153
  <p class="gl-dropdown-item-text-primary"><slot></slot></p>
119
154
  <p v-if="secondaryText" class="gl-dropdown-item-text-secondary">{{ secondaryText }}</p>
120
155
  </div>
@@ -3,6 +3,7 @@ import isEqual from 'lodash/isEqual';
3
3
  import cloneDeep from 'lodash/cloneDeep';
4
4
  import { PortalTarget } from 'portal-vue';
5
5
  import { GlTooltipDirective } from '../../../directives/tooltip/tooltip';
6
+ import { logWarning } from '../../../utils/utils';
6
7
  import GlIcon from '../icon/icon.vue';
7
8
  import GlSearchBoxByClick from '../search_box_by_click/search_box_by_click.vue';
8
9
  import GlFilteredSearchTerm from './filtered_search_term.vue';
@@ -72,9 +73,9 @@ export default {
72
73
  // eslint-disable-next-line no-underscore-dangle
73
74
  const isOk = Array.isArray(value) && value.every(({ token }) => !token || token.__v_skip);
74
75
  if (!isOk) {
75
- // eslint-disable-next-line no-console
76
- console.warn(
76
+ logWarning(
77
77
  'You are using Vue3. In Vue3 each token component passed to filtered search must be wrapped into markRaw',
78
+ { name: 'GlFilteredSearch' },
78
79
  );
79
80
  }
80
81
 
@@ -31,11 +31,17 @@ export default {
31
31
  default: () => [{ value: '', name: '' }],
32
32
  validator: (options) => options.every((opt) => Object.keys(opt).includes('name', 'value')),
33
33
  },
34
+ /**
35
+ * Accessible label for the input field. Used for the aria-label attribute.
36
+ */
34
37
  label: {
35
38
  type: String,
36
39
  required: false,
37
40
  default: undefined,
38
41
  },
42
+ /**
43
+ * Additional CSS class(es) to apply to the input element.
44
+ */
39
45
  inputClass: {
40
46
  type: [String, Array, Object],
41
47
  required: false,
@@ -2,6 +2,7 @@
2
2
  <script>
3
3
  import iconsPath from '@gitlab/svgs/dist/icons.svg';
4
4
  import iconsInfo from '@gitlab/svgs/dist/icons.json';
5
+ import { logWarning } from '../../../utils/utils';
5
6
  import { iconSizeOptions, iconVariantOptions } from '../../../utils/constants';
6
7
 
7
8
  const knownIcons = new Set(iconsInfo.icons);
@@ -36,8 +37,7 @@ export default {
36
37
  if (knownIcons.has(value)) {
37
38
  return true;
38
39
  }
39
- // eslint-disable-next-line no-console
40
- console.warn(`Icon '${value}' is not a known icon of @gitlab/svgs`);
40
+ logWarning(`Icon '${value}' is not a known icon of @gitlab/svgs`, { name: 'GlIcon' });
41
41
  return false;
42
42
  },
43
43
  },
@@ -2,6 +2,7 @@
2
2
  <script>
3
3
  import illustrationsPath from '@gitlab/svgs/dist/illustrations.svg';
4
4
  import illustrationsInfo from '@gitlab/svgs/dist/illustrations.json';
5
+ import { logWarning } from '../../../utils/utils';
5
6
 
6
7
  const knownIllustrations = illustrationsInfo.icons;
7
8
 
@@ -24,8 +25,9 @@ export default {
24
25
  if (knownIllustrations.some((obj) => obj.name === value)) {
25
26
  return true;
26
27
  }
27
- // eslint-disable-next-line no-console
28
- console.warn(`Illustration '${value}' is not a known illustration of @gitlab/svgs`);
28
+ logWarning(`Illustration '${value}' is not a known illustration of @gitlab/svgs`, {
29
+ name: 'GlIllustration',
30
+ });
29
31
  return false;
30
32
  },
31
33
  },