@gitlab/ui 53.1.0 → 53.3.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/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [53.3.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v53.2.0...v53.3.0) (2023-01-24)
2
+
3
+
4
+ ### Features
5
+
6
+ * **GlDisclosureDropdown:** Allow to provide custom toggle id ([b696ea2](https://gitlab.com/gitlab-org/gitlab-ui/commit/b696ea2ef34a9efca894260cfa45b7ff36aefd56))
7
+
8
+ # [53.2.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v53.1.0...v53.2.0) (2023-01-23)
9
+
10
+
11
+ ### Features
12
+
13
+ * **GlDisclosureDropdown:** Allow to provide custom item template for groups ([c3034b8](https://gitlab.com/gitlab-org/gitlab-ui/commit/c3034b87ae093daae7b0817a2535abefa0a7dcad))
14
+
1
15
  # [53.1.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v53.0.1...v53.1.0) (2023-01-23)
2
16
 
3
17
 
@@ -97,6 +97,15 @@ var script = {
97
97
  required: false,
98
98
  default: false
99
99
  },
100
+ /**
101
+ * Custom toggle id.
102
+ * Fot instance, it can be referenced by tooltip or popover
103
+ */
104
+ toggleId: {
105
+ type: String,
106
+ required: false,
107
+ default: _uniqueId('dropdown-toggle-btn-')
108
+ },
100
109
  /**
101
110
  * Additional CSS classes to customize toggle appearance
102
111
  */
@@ -143,7 +152,6 @@ var script = {
143
152
  },
144
153
  data() {
145
154
  return {
146
- toggleId: _uniqueId('dropdown-toggle-btn-'),
147
155
  disclosureId: _uniqueId('disclosure-'),
148
156
  nextFocusedItemIndex: null
149
157
  };
@@ -257,7 +265,7 @@ var script = {
257
265
  const __vue_script__ = script;
258
266
 
259
267
  /* template */
260
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-base-dropdown',{ref:"baseDropdown",staticClass:"gl-disclosure-dropdown",attrs:{"aria-labelledby":_vm.toggleAriaLabelledBy,"toggle-id":_vm.toggleId,"toggle-text":_vm.toggleText,"toggle-class":_vm.toggleClass,"text-sr-only":_vm.textSrOnly,"category":_vm.category,"variant":_vm.variant,"size":_vm.size,"icon":_vm.icon,"disabled":_vm.disabled,"loading":_vm.loading,"no-caret":_vm.noCaret,"placement":_vm.placement},on:_vm._d({},[_vm.$options.events.GL_DROPDOWN_SHOWN,_vm.onShow,_vm.$options.events.GL_DROPDOWN_HIDDEN,_vm.onHide]),scopedSlots:_vm._u([(_vm.hasCustomToggle)?{key:"toggle",fn:function(){return [_vm._t("toggle")]},proxy:true}:null],null,true)},[_vm._v(" "),_vm._t("header"),_vm._v(" "),_c(_vm.disclosureOptions.tag,{ref:"content",tag:"component",staticClass:"gl-dropdown-contents gl-list-style-none gl-pl-0 gl-mb-0",attrs:{"id":_vm.disclosureId,"role":_vm.disclosureOptions.role,"aria-labelledby":_vm.listAriaLabelledBy || _vm.toggleId,"data-testid":"disclosure-content","tabindex":"-1"},on:{"keydown":_vm.onKeydown}},[_vm._t("default",function(){return [_vm._l((_vm.items),function(item,index){return [(_vm.isItem(item))?[_c('gl-disclosure-dropdown-item',{key:item.text,attrs:{"item":item},on:{"action":_vm.handleAction}},[_vm._t("list-item",null,{"item":item})],2)]:[_c('gl-disclosure-dropdown-group',{key:item.name,attrs:{"bordered":index !== 0,"group":item},on:{"action":_vm.handleAction},scopedSlots:_vm._u([(_vm.$scopedSlots['group-label'])?{key:"group-label",fn:function(){return [_vm._t("group-label",null,{"group":item})]},proxy:true}:null,{key:"list-item",fn:function(){return [_vm._t("list-item")]},proxy:true}],null,true)})]]})]})],2),_vm._v(" "),_vm._t("footer")],2)};
268
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-base-dropdown',{ref:"baseDropdown",staticClass:"gl-disclosure-dropdown",attrs:{"aria-labelledby":_vm.toggleAriaLabelledBy,"toggle-id":_vm.toggleId,"toggle-text":_vm.toggleText,"toggle-class":_vm.toggleClass,"text-sr-only":_vm.textSrOnly,"category":_vm.category,"variant":_vm.variant,"size":_vm.size,"icon":_vm.icon,"disabled":_vm.disabled,"loading":_vm.loading,"no-caret":_vm.noCaret,"placement":_vm.placement},on:_vm._d({},[_vm.$options.events.GL_DROPDOWN_SHOWN,_vm.onShow,_vm.$options.events.GL_DROPDOWN_HIDDEN,_vm.onHide]),scopedSlots:_vm._u([(_vm.hasCustomToggle)?{key:"toggle",fn:function(){return [_vm._t("toggle")]},proxy:true}:null],null,true)},[_vm._v(" "),_vm._t("header"),_vm._v(" "),_c(_vm.disclosureOptions.tag,{ref:"content",tag:"component",staticClass:"gl-dropdown-contents gl-list-style-none gl-pl-0 gl-mb-0",attrs:{"id":_vm.disclosureId,"role":_vm.disclosureOptions.role,"aria-labelledby":_vm.listAriaLabelledBy || _vm.toggleId,"data-testid":"disclosure-content","tabindex":"-1"},on:{"keydown":_vm.onKeydown}},[_vm._t("default",function(){return [_vm._l((_vm.items),function(item,index){return [(_vm.isItem(item))?[_c('gl-disclosure-dropdown-item',{key:item.text,attrs:{"item":item},on:{"action":_vm.handleAction}},[_vm._t("list-item",null,{"item":item})],2)]:[_c('gl-disclosure-dropdown-group',{key:item.name,attrs:{"bordered":index !== 0,"group":item},on:{"action":_vm.handleAction},scopedSlots:_vm._u([(_vm.$scopedSlots['group-label'])?{key:"group-label",fn:function(){return [_vm._t("group-label",null,{"group":item})]},proxy:true}:null],null,true)},[_vm._v(" "),(_vm.$scopedSlots['list-item'])?_vm._l((item.items),function(groupItem){return _c('gl-disclosure-dropdown-item',{key:groupItem.text,on:{"action":_vm.handleAction}},[_vm._t("list-item",null,{"item":groupItem})],2)}):_vm._e()],2)]]})]})],2),_vm._v(" "),_vm._t("footer")],2)};
261
269
  var __vue_staticRenderFns__ = [];
262
270
 
263
271
  /* style */
@@ -42,6 +42,18 @@ const mockItemsCustomItem = [{
42
42
  rel: 'nofollow'
43
43
  }
44
44
  }];
45
+ const mockGroupsCustomItem = [{
46
+ name: 'Merge requests',
47
+ items: [{
48
+ text: 'Assigned to you',
49
+ href: 'https://gitlab.com/dashboard/merge_requests?assignee_username=root',
50
+ count: 1
51
+ }, {
52
+ text: 'Review requests from you',
53
+ href: 'https://gitlab.com/dashboard/merge_requests?reviewer_username=root',
54
+ count: 4
55
+ }]
56
+ }];
45
57
  const mockGroups = [{
46
58
  name: 'This project',
47
59
  items: [{
@@ -125,4 +137,4 @@ const mockProfileGroups = [{
125
137
  }]
126
138
  }];
127
139
 
128
- export { mockGroups, mockItems, mockItemsCustomItem, mockProfileGroups };
140
+ export { mockGroups, mockGroupsCustomItem, mockItems, mockItemsCustomItem, mockProfileGroups };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "53.1.0",
3
+ "version": "53.3.0",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -33,13 +33,21 @@ describe('GlDisclosureDropdown', () => {
33
33
  const findListItem = (index) => findDisclosureItems().at(index).findComponent(ITEM_SELECTOR);
34
34
 
35
35
  describe('toggle text', () => {
36
- it('should pass toggle text to base dropdown', () => {
36
+ it('should pass toggle text to the base dropdown', () => {
37
37
  const toggleText = 'Merge requests';
38
38
  buildWrapper({ items: mockItems, toggleText });
39
39
  expect(findBaseDropdown().props('toggleText')).toBe(toggleText);
40
40
  });
41
41
  });
42
42
 
43
+ describe('custom toggle id', () => {
44
+ it('should pass toggle id to the base dropdown', () => {
45
+ const toggleId = 'custom-toggle';
46
+ buildWrapper({ items: mockItems, toggleId });
47
+ expect(findBaseDropdown().props('toggleId')).toBe(toggleId);
48
+ });
49
+ });
50
+
43
51
  describe('ARIA attributes', () => {
44
52
  it('should provide `toggleId` to the base dropdown and reference it in`aria-labelledby` attribute of the list container`', async () => {
45
53
  await buildWrapper({ items: mockItems });
@@ -13,10 +13,17 @@ import {
13
13
  GlAvatar,
14
14
  GlModal,
15
15
  GlIcon,
16
+ GlTooltip,
16
17
  } from '../../../../index';
17
18
  import { makeContainer } from '../../../../utils/story_decorators/container';
18
19
  import readme from './disclosure_dropdown.md';
19
- import { mockItems, mockItemsCustomItem, mockGroups, mockProfileGroups } from './mock_data';
20
+ import {
21
+ mockItems,
22
+ mockItemsCustomItem,
23
+ mockGroups,
24
+ mockProfileGroups,
25
+ mockGroupsCustomItem,
26
+ } from './mock_data';
20
27
 
21
28
  const defaultValue = (prop) => GlDisclosureDropdown.props[prop].default;
22
29
 
@@ -29,6 +36,7 @@ const generateProps = ({
29
36
  loading = defaultValue('loading'),
30
37
  noCaret = defaultValue('noCaret'),
31
38
  placement = defaultValue('placement'),
39
+ toggleId = defaultValue('toggleId'),
32
40
  toggleText,
33
41
  textSrOnly = defaultValue('textSrOnly'),
34
42
  icon = '',
@@ -44,6 +52,7 @@ const generateProps = ({
44
52
  loading,
45
53
  noCaret,
46
54
  placement,
55
+ toggleId,
47
56
  toggleText,
48
57
  textSrOnly,
49
58
  icon,
@@ -62,6 +71,7 @@ const makeBindings = (overrides = {}) =>
62
71
  ':loading': 'loading',
63
72
  ':no-caret': 'noCaret',
64
73
  ':placement': 'placement',
74
+ ':toggle-id': 'toggleId',
65
75
  ':toggle-text': 'toggleText',
66
76
  ':text-sr-only': 'textSrOnly',
67
77
  ':icon': 'icon',
@@ -87,23 +97,34 @@ const template = (content, { bindingOverrides = {} } = {}) => `
87
97
  </gl-disclosure-dropdown>
88
98
  `;
89
99
 
100
+ const TOGGLE_ID = 'custom-toggle-id';
90
101
  export const Default = (args, { argTypes }) => ({
102
+ toggleId: TOGGLE_ID,
91
103
  props: Object.keys(argTypes),
92
104
  components: {
93
105
  GlDisclosureDropdown,
106
+ GlTooltip,
94
107
  },
95
108
  mounted() {
96
109
  if (this.startOpened) {
97
110
  openDisclosure(this);
98
111
  }
99
112
  },
100
- template: template(),
113
+ template: `
114
+ <div>
115
+ ${template()}
116
+ <gl-tooltip :target="$options.toggleId" placement="right">
117
+ This is a default disclosure
118
+ </gl-tooltip>
119
+ </div>
120
+ `,
101
121
  });
102
122
  Default.args = generateProps({
103
123
  icon: 'ellipsis_v',
104
124
  noCaret: true,
105
125
  toggleText: 'Disclosure',
106
126
  textSrOnly: true,
127
+ toggleId: TOGGLE_ID,
107
128
  });
108
129
  Default.decorators = [makeContainer({ height: '200px' })];
109
130
 
@@ -185,6 +206,51 @@ Groups.args = generateProps({
185
206
  textSrOnly: true,
186
207
  });
187
208
 
209
+ export const CustomGroupsAndItems = (args, { argTypes }) => ({
210
+ props: Object.keys(argTypes),
211
+ components: {
212
+ GlDisclosureDropdown,
213
+ GlBadge,
214
+ },
215
+ mounted() {
216
+ if (this.startOpened) {
217
+ openDisclosure(this);
218
+ }
219
+ },
220
+ methods: {
221
+ navigate() {
222
+ this.$refs.link.click();
223
+ },
224
+ getTotalMrs(items) {
225
+ return items.reduce((acc, item) => acc + item.count, 0);
226
+ },
227
+ },
228
+ template: template(
229
+ `
230
+ <template #group-label="{ group }">
231
+ {{ group.name }} <gl-badge size="sm">{{ getTotalMrs(group.items) }}</gl-badge>
232
+ </template>
233
+ <template #list-item="{ item }">
234
+ <a ref="link" class="gl-display-flex gl-align-items-center gl-justify-content-space-between gl-hover-text-gray-900 gl-hover-text-decoration-none gl-text-gray-900" :href="item.href" v-bind="item.extraAttrs">
235
+ {{item.text}}
236
+ <gl-badge pill size="sm" v-if="item.count">{{item.count}}</gl-badge>
237
+ </a>
238
+ </template>
239
+ `,
240
+ {
241
+ bindingOverrides: {
242
+ '@action': 'navigate',
243
+ },
244
+ }
245
+ ),
246
+ });
247
+
248
+ CustomGroupsAndItems.args = generateProps({
249
+ items: mockGroupsCustomItem,
250
+ toggleText: 'Merge requests',
251
+ });
252
+ CustomGroupsAndItems.decorators = [makeContainer({ height: '200px' })];
253
+
188
254
  export const CustomGroupsItemsAndToggle = makeGroupedExample({
189
255
  template: template(`
190
256
  <template #toggle>
@@ -109,6 +109,15 @@ export default {
109
109
  required: false,
110
110
  default: false,
111
111
  },
112
+ /**
113
+ * Custom toggle id.
114
+ * Fot instance, it can be referenced by tooltip or popover
115
+ */
116
+ toggleId: {
117
+ type: String,
118
+ required: false,
119
+ default: uniqueId('dropdown-toggle-btn-'),
120
+ },
112
121
  /**
113
122
  * Additional CSS classes to customize toggle appearance
114
123
  */
@@ -155,7 +164,6 @@ export default {
155
164
  },
156
165
  data() {
157
166
  return {
158
- toggleId: uniqueId('dropdown-toggle-btn-'),
159
167
  disclosureId: uniqueId('disclosure-'),
160
168
  nextFocusedItemIndex: null,
161
169
  };
@@ -328,9 +336,15 @@ export default {
328
336
  <slot name="group-label" :group="item"></slot>
329
337
  </template>
330
338
 
331
- <template #list-item>
332
- <!-- @slot Custom template of the disclosure dropdown item -->
333
- <slot name="list-item"></slot>
339
+ <template v-if="$scopedSlots['list-item']">
340
+ <gl-disclosure-dropdown-item
341
+ v-for="groupItem in item.items"
342
+ :key="groupItem.text"
343
+ @action="handleAction"
344
+ >
345
+ <!-- @slot Custom template of the disclosure dropdown item -->
346
+ <slot name="list-item" :item="groupItem"></slot>
347
+ </gl-disclosure-dropdown-item>
334
348
  </template>
335
349
  </gl-disclosure-dropdown-group>
336
350
  </template>
@@ -51,6 +51,24 @@ export const mockItemsCustomItem = [
51
51
  },
52
52
  ];
53
53
 
54
+ export const mockGroupsCustomItem = [
55
+ {
56
+ name: 'Merge requests',
57
+ items: [
58
+ {
59
+ text: 'Assigned to you',
60
+ href: 'https://gitlab.com/dashboard/merge_requests?assignee_username=root',
61
+ count: 1,
62
+ },
63
+ {
64
+ text: 'Review requests from you',
65
+ href: 'https://gitlab.com/dashboard/merge_requests?reviewer_username=root',
66
+ count: 4,
67
+ },
68
+ ],
69
+ },
70
+ ];
71
+
54
72
  export const mockGroups = [
55
73
  {
56
74
  name: 'This project',