@gitlab/ui 33.1.2 → 34.0.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,20 @@
1
+ # [34.0.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v33.1.2...v34.0.0) (2022-01-28)
2
+
3
+
4
+ ### Features
5
+
6
+ * **GlAvatarsInline:** Add badgeSrOnlyText prop ([bcb0d29](https://gitlab.com/gitlab-org/gitlab-ui/commit/bcb0d299e9468e13cc7d565784388e3b9585e4a0))
7
+
8
+
9
+ ### BREAKING CHANGES
10
+
11
+ * **GlAvatarsInline:** This change adds a required
12
+ property named badgeSrOnlyText that ensures
13
+ that badge displayed when avatars inline is
14
+ collapsed, provides a screen reader only
15
+ label that gives contextual information
16
+ for users that use this form factor
17
+
1
18
  ## [33.1.2](https://gitlab.com/gitlab-org/gitlab-ui/compare/v33.1.1...v33.1.2) (2022-01-27)
2
19
 
3
20
 
@@ -1,4 +1,4 @@
1
- var avatars_inline = "Use `<avatars-inline />` to display multiple avatars organized in a single row.\n\n### Basic usage\n\nThe `avatars` property accepts an array of objects that contains the avatar properties. By default,\n`<avatars-inline />` expects each object contained in the array to have the same shape as the\nproperties of the `<avatar />` component. You can customize the display of each avatar by\noverriding the default slot:\n\n```html\n<gl-avatars-inline :avatars=\"avatars\">\n <template #avatar=\"{ avatar }\">\n <gl-avatar-link v-gl-tooltip target=\"blank\" :href=\"avatar.href\" :title=\"avatar.tooltip\">\n <gl-avatar :src=\"avatar.src\" :size=\"32\" />\n </gl-avatar-link>\n </template>\n</gl-avatars-inline>\n```\n\nIn the example above, the avatars displayed inside `<avatars-inline />` are links pointing to a URL\nstored in each avatar object. Each avatar also displays a tooltip. If you override\n`<inline-avatars />` default display, you can pass an array of objects with any desired shape to\nthe `avatars` property.\n\n### Collapsing\n\nWhen the `collapse` property value is `true` and the `maxVisible` property value is a number less\nthan the length of the `avatars` property array, `<avatars-inline>` will hide the overflown avatars\nand display a badge instead.\n\n### Supported sizes\n\n`<avatars-inline>` only supports avatars with `24` or `32` size.\n";
1
+ var avatars_inline = "Use `<avatars-inline />` to display multiple avatars organized in a single row.\n\n### Basic usage\n\nThe `avatars` property accepts an array of objects that contains the avatar properties. By default,\n`<avatars-inline />` expects each object contained in the array to have the same shape as the\nproperties of the `<avatar />` component. You can customize the display of each avatar by\noverriding the default slot:\n\n```html\n<gl-avatars-inline :avatars=\"avatars\">\n <template #avatar=\"{ avatar }\">\n <gl-avatar-link v-gl-tooltip target=\"blank\" :href=\"avatar.href\" :title=\"avatar.tooltip\">\n <gl-avatar :src=\"avatar.src\" :size=\"32\" />\n </gl-avatar-link>\n </template>\n</gl-avatars-inline>\n```\n\nIn the example above, the avatars displayed inside `<avatars-inline />` are links pointing to a URL\nstored in each avatar object. Each avatar also displays a tooltip. If you override\n`<inline-avatars />` default display, you can pass an array of objects with any desired shape to\nthe `avatars` property.\n\n### Collapsing\n\nWhen the `collapse` property value is `true` and the `maxVisible` property value is a number less\nthan the length of the `avatars` property array, `<avatars-inline>` will hide the overflown avatars\nand display a badge instead.\n\n### Badge description in screen readers\n\nThe `badgeSrOnlyText` property provides a meaningful description of the badge that appears\nwhen avatars are collapsed for screen reader users.\n\n### Supported sizes\n\n`<avatars-inline>` only supports avatars with `24` or `32` size.\n";
2
2
 
3
3
  var description = /*#__PURE__*/Object.freeze({
4
4
  __proto__: null,
@@ -30,6 +30,10 @@ var script = {
30
30
  required: false,
31
31
  default: false
32
32
  },
33
+ badgeSrOnlyText: {
34
+ type: String,
35
+ required: true
36
+ },
33
37
  badgeTooltipProp: {
34
38
  type: String,
35
39
  required: false,
@@ -100,7 +104,7 @@ var script = {
100
104
  const __vue_script__ = script;
101
105
 
102
106
  /* template */
103
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{class:['gl-avatars-inline', { collapsed: _vm.collapsed }],style:(_vm.containerSizeStyles)},[_vm._l((_vm.visibleAvatars),function(avatar,index){return _c('div',{key:index,staticClass:"gl-avatars-inline-child",style:(_vm.calcAvatarPosition(index))},[_vm._t("avatar",[_c('gl-avatar',_vm._b({attrs:{"size":_vm.avatarSize}},'gl-avatar',avatar,false))],{"avatar":avatar})],2)}),_vm._v(" "),(_vm.collapsed && _vm.collapsable)?_c('div',{staticClass:"gl-avatars-inline-child",style:(_vm.calcAvatarPosition(_vm.visibleAvatars.length))},[(_vm.badgeTooltipProp)?_c('gl-tooltip',{attrs:{"target":function () { return _vm.$refs.badge; }}},[_vm._v("\n "+_vm._s(_vm.badgeTooltipTitle)+"\n ")]):_vm._e(),_vm._v(" "),_c('span',{ref:"badge",class:['gl-avatars-inline-badge', _vm.badgeSize]},[_vm._v("\n "+_vm._s(_vm.badgeLabel)+"\n ")])],1):_vm._e()],2)};
107
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{class:['gl-avatars-inline', { collapsed: _vm.collapsed }],style:(_vm.containerSizeStyles)},[_vm._l((_vm.visibleAvatars),function(avatar,index){return _c('div',{key:index,staticClass:"gl-avatars-inline-child",style:(_vm.calcAvatarPosition(index))},[_vm._t("avatar",[_c('gl-avatar',_vm._b({attrs:{"size":_vm.avatarSize}},'gl-avatar',avatar,false))],{"avatar":avatar})],2)}),_vm._v(" "),(_vm.collapsed && _vm.collapsable)?_c('div',{staticClass:"gl-avatars-inline-child",style:(_vm.calcAvatarPosition(_vm.visibleAvatars.length))},[(_vm.badgeTooltipProp)?_c('gl-tooltip',{attrs:{"target":function () { return _vm.$refs.badge; }}},[_vm._v("\n "+_vm._s(_vm.badgeTooltipTitle)+"\n ")]):_vm._e(),_vm._v(" "),_c('span',{ref:"badge",class:['gl-avatars-inline-badge', _vm.badgeSize],attrs:{"data-testid":"collapsed-avatars-badge","aria-hidden":"true"}},[_vm._v("\n "+_vm._s(_vm.badgeLabel)+"\n ")]),_vm._v(" "),_c('span',{staticClass:"sr-only",attrs:{"data-testid":"badge-sr-only-text"}},[_vm._v(_vm._s(_vm.badgeSrOnlyText))])],1):_vm._e()],2)};
104
108
  var __vue_staticRenderFns__ = [];
105
109
 
106
110
  /* style */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "33.1.2",
3
+ "version": "34.0.0",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -91,15 +91,15 @@
91
91
  "@rollup/plugin-commonjs": "^11.1.0",
92
92
  "@rollup/plugin-node-resolve": "^7.1.3",
93
93
  "@rollup/plugin-replace": "^2.3.2",
94
- "@storybook/addon-a11y": "6.4.14",
95
- "@storybook/addon-docs": "6.4.14",
96
- "@storybook/addon-essentials": "6.4.14",
94
+ "@storybook/addon-a11y": "6.4.15",
95
+ "@storybook/addon-docs": "6.4.15",
96
+ "@storybook/addon-essentials": "6.4.15",
97
97
  "@storybook/addon-knobs": "6.4.0",
98
- "@storybook/addon-storyshots": "6.4.14",
99
- "@storybook/addon-storyshots-puppeteer": "6.4.14",
100
- "@storybook/addon-viewport": "6.4.14",
101
- "@storybook/theming": "6.4.14",
102
- "@storybook/vue": "6.4.14",
98
+ "@storybook/addon-storyshots": "6.4.15",
99
+ "@storybook/addon-storyshots-puppeteer": "6.4.15",
100
+ "@storybook/addon-viewport": "6.4.15",
101
+ "@storybook/theming": "6.4.15",
102
+ "@storybook/vue": "6.4.15",
103
103
  "@vue/test-utils": "1.3.0",
104
104
  "autoprefixer": "^9.7.6",
105
105
  "babel-jest": "^26.6.3",
@@ -28,6 +28,11 @@ When the `collapse` property value is `true` and the `maxVisible` property value
28
28
  than the length of the `avatars` property array, `<avatars-inline>` will hide the overflown avatars
29
29
  and display a badge instead.
30
30
 
31
+ ### Badge description in screen readers
32
+
33
+ The `badgeSrOnlyText` property provides a meaningful description of the badge that appears
34
+ when avatars are collapsed for screen reader users.
35
+
31
36
  ### Supported sizes
32
37
 
33
38
  `<avatars-inline>` only supports avatars with `24` or `32` size.
@@ -11,10 +11,14 @@ describe('avatars inline', () => {
11
11
  { src: 'avatar 2', tooltip: 'Avatar 2' },
12
12
  { src: 'avatar 3', tooltip: 'Avatar 3' },
13
13
  ];
14
+ const badgeSrOnlyText = 'additional users';
14
15
 
15
16
  const buildWrapper = (propsData = {}) => {
16
17
  wrapper = shallowMount(AvatarsInline, {
17
- propsData,
18
+ propsData: {
19
+ badgeSrOnlyText,
20
+ ...propsData,
21
+ },
18
22
  stubs: {
19
23
  GlTooltip,
20
24
  },
@@ -107,4 +111,20 @@ describe('avatars inline', () => {
107
111
  });
108
112
  });
109
113
  });
114
+
115
+ describe('a11y', () => {
116
+ it('renders screen reader only text for the collapse badge', () => {
117
+ buildWrapper({ avatars, maxVisible: 1, collapsed: true, avatarSize: 32 });
118
+
119
+ expect(wrapper.find('[data-testid="badge-sr-only-text"]').text()).toBe(badgeSrOnlyText);
120
+ });
121
+
122
+ it('hides badge text for screen readers', () => {
123
+ buildWrapper({ avatars, maxVisible: 1, collapsed: true, avatarSize: 32 });
124
+
125
+ expect(
126
+ wrapper.find('[data-testid="collapsed-avatars-badge"]').attributes('aria-hidden')
127
+ ).toBe('true');
128
+ });
129
+ });
110
130
  });
@@ -1,37 +1,49 @@
1
+ import { GlAvatarsInline, GlAvatar, GlAvatarLink, GlTooltipDirective } from '../../../../index';
1
2
  import { avatarsInlineSizeOptions } from '../../../utils/constants';
2
3
  import readme from './avatars_inline.md';
3
4
 
4
5
  const defaultAvatars = [
5
- { src: 'https://picsum.photos/id/1005/32' },
6
- { src: 'https://picsum.photos/id/1006/32' },
7
- { src: 'https://picsum.photos/id/1009/32' },
8
- { src: 'https://picsum.photos/id/1011/32' },
9
- { src: 'https://picsum.photos/id/1012/32' },
6
+ { src: 'https://picsum.photos/id/1005/32', alt: 'Administrator’s user avatar' },
7
+ { src: 'https://picsum.photos/id/1006/32', alt: 'Ops Manager’s user avatar' },
8
+ { src: 'https://picsum.photos/id/1009/32', alt: 'Developer’s user avatar' },
9
+ { src: 'https://picsum.photos/id/1011/32', alt: 'Business Admin’s user avatar' },
10
+ { src: 'https://picsum.photos/id/1012/32', alt: 'Product designer’s user avatar' },
10
11
  ];
11
12
 
12
13
  const generateProps = (
13
14
  avatars = defaultAvatars,
14
- { maxVisible = 2, collapsed = true, avatarSize = 24 } = {}
15
+ {
16
+ maxVisible = 2,
17
+ collapsed = true,
18
+ avatarSize = 24,
19
+ badgeTooltipProp = '',
20
+ badgeSrOnlyText = `${avatars.length - maxVisible} additional users`,
21
+ } = {}
15
22
  ) => ({
16
23
  maxVisible,
17
24
  collapsed,
18
25
  avatarSize,
19
26
  avatars,
27
+ badgeTooltipProp,
28
+ badgeSrOnlyText,
20
29
  });
21
30
 
22
31
  export const Default = (args, { argTypes }) => ({
32
+ components: { GlAvatarsInline },
23
33
  props: Object.keys(argTypes),
24
34
  template: `
25
- <gl-avatars-inline :avatars="avatars" :collapsed="collapsed" :avatar-size="avatarSize" :max-visible="maxVisible">
35
+ <gl-avatars-inline :avatars="avatars" :collapsed="collapsed" :avatar-size="avatarSize" :max-visible="maxVisible" :badgeTooltipProp="badgeTooltipProp" :badgeSrOnlyText="badgeSrOnlyText">
26
36
  </gl-avatars-inline>
27
37
  `,
28
38
  });
29
39
  Default.args = generateProps();
30
40
 
31
41
  export const WithLinksAndTooltips = (args, { argTypes }) => ({
42
+ components: { GlAvatarsInline, GlAvatar, GlAvatarLink },
43
+ directives: { GlTooltip: GlTooltipDirective },
32
44
  props: Object.keys(argTypes),
33
45
  template: `
34
- <gl-avatars-inline :avatars="avatars" :collapsed="collapsed" :avatar-size="avatarSize" :max-visible="maxVisible">
46
+ <gl-avatars-inline :avatars="avatars" :collapsed="collapsed" :avatar-size="avatarSize" :max-visible="maxVisible" :badgeTooltipProp="badgeTooltipProp" :badgeSrOnlyText="badgeSrOnlyText">
35
47
  <template #avatar="{ avatar }">
36
48
  <gl-avatar-link target="blank" :href="avatar.href" v-gl-tooltip :title="avatar.tooltip">
37
49
  <gl-avatar :src="avatar.src" :size="avatarSize" />
@@ -45,11 +57,13 @@ WithLinksAndTooltips.args = generateProps(
45
57
  ...avatar,
46
58
  href: '//gitlab.com',
47
59
  tooltip: `Avatar ${index}`,
48
- }))
60
+ })),
61
+ { badgeTooltipProp: 'tooltip' }
49
62
  );
50
63
 
51
64
  export default {
52
65
  title: 'base/avatar/avatars-inline',
66
+ component: GlAvatarsInline,
53
67
  parameters: {
54
68
  knobs: { disable: true },
55
69
  docs: {
@@ -29,6 +29,10 @@ export default {
29
29
  required: false,
30
30
  default: false,
31
31
  },
32
+ badgeSrOnlyText: {
33
+ type: String,
34
+ required: true,
35
+ },
32
36
  badgeTooltipProp: {
33
37
  type: String,
34
38
  required: false,
@@ -111,9 +115,15 @@ export default {
111
115
  <gl-tooltip v-if="badgeTooltipProp" :target="() => $refs.badge">
112
116
  {{ badgeTooltipTitle }}
113
117
  </gl-tooltip>
114
- <span ref="badge" :class="['gl-avatars-inline-badge', badgeSize]">
118
+ <span
119
+ ref="badge"
120
+ data-testid="collapsed-avatars-badge"
121
+ :class="['gl-avatars-inline-badge', badgeSize]"
122
+ aria-hidden="true"
123
+ >
115
124
  {{ badgeLabel }}
116
125
  </span>
126
+ <span data-testid="badge-sr-only-text" class="sr-only">{{ badgeSrOnlyText }}</span>
117
127
  </div>
118
128
  </div>
119
129
  </template>