@gitlab/ui 40.3.0 → 40.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "40.3.0",
3
+ "version": "40.4.0",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -1,7 +1,7 @@
1
1
  $gl-avatar-identicon-bgs: $red-50, $purple-50, $theme-indigo-50, $blue-50, $green-50, $orange-50,
2
2
  $gray-50;
3
3
 
4
- .gl-avatar {
4
+ @mixin gl-avatar {
5
5
  @include gl-border-1;
6
6
  @include gl-border-solid;
7
7
  @include gl-border-gray-a-08;
@@ -9,7 +9,7 @@ $gl-avatar-identicon-bgs: $red-50, $purple-50, $theme-indigo-50, $blue-50, $gree
9
9
  @include gl-flex-shrink-0;
10
10
  }
11
11
 
12
- .gl-avatar-s16 {
12
+ @mixin gl-avatar-s16 {
13
13
  @include gl-w-5;
14
14
  @include gl-h-5;
15
15
  @include gl-font-sm;
@@ -17,7 +17,7 @@ $gl-avatar-identicon-bgs: $red-50, $purple-50, $theme-indigo-50, $blue-50, $gree
17
17
  @include gl-rounded-small;
18
18
  }
19
19
 
20
- .gl-avatar-s24 {
20
+ @mixin gl-avatar-s24 {
21
21
  @include gl-w-6;
22
22
  @include gl-h-6;
23
23
  @include gl-font-sm;
@@ -25,7 +25,7 @@ $gl-avatar-identicon-bgs: $red-50, $purple-50, $theme-indigo-50, $blue-50, $gree
25
25
  @include gl-rounded-base;
26
26
  }
27
27
 
28
- .gl-avatar-s32 {
28
+ @mixin gl-avatar-s32 {
29
29
  @include gl-w-7;
30
30
  @include gl-h-7;
31
31
  @include gl-font-base;
@@ -33,7 +33,7 @@ $gl-avatar-identicon-bgs: $red-50, $purple-50, $theme-indigo-50, $blue-50, $gree
33
33
  @include gl-rounded-base;
34
34
  }
35
35
 
36
- .gl-avatar-s48 {
36
+ @mixin gl-avatar-s48 {
37
37
  @include gl-w-9;
38
38
  @include gl-h-9;
39
39
  @include gl-font-size-h2;
@@ -41,7 +41,7 @@ $gl-avatar-identicon-bgs: $red-50, $purple-50, $theme-indigo-50, $blue-50, $gree
41
41
  @include gl-rounded-lg;
42
42
  }
43
43
 
44
- .gl-avatar-s64 {
44
+ @mixin gl-avatar-s64 {
45
45
  @include gl-w-11;
46
46
  @include gl-h-11;
47
47
  @include gl-font-size-h-display;
@@ -49,7 +49,7 @@ $gl-avatar-identicon-bgs: $red-50, $purple-50, $theme-indigo-50, $blue-50, $gree
49
49
  @include gl-rounded-lg;
50
50
  }
51
51
 
52
- .gl-avatar-s96 {
52
+ @mixin gl-avatar-s96 {
53
53
  @include gl-w-13;
54
54
  @include gl-h-13;
55
55
  @include gl-font-size-h-display-xl;
@@ -57,6 +57,142 @@ $gl-avatar-identicon-bgs: $red-50, $purple-50, $theme-indigo-50, $blue-50, $gree
57
57
  @include gl-rounded-lg;
58
58
  }
59
59
 
60
+ .gl-avatar {
61
+ @include gl-avatar;
62
+ }
63
+
64
+ .gl-avatar-s16 {
65
+ @include gl-avatar-s16;
66
+ }
67
+
68
+ .gl-avatar-s24 {
69
+ @include gl-avatar-s24;
70
+ }
71
+
72
+ .gl-avatar-s32 {
73
+ @include gl-avatar-s32;
74
+ }
75
+
76
+ .gl-avatar-s48 {
77
+ @include gl-avatar-s48;
78
+ }
79
+
80
+ .gl-avatar-s64 {
81
+ @include gl-avatar-s64;
82
+ }
83
+
84
+ .gl-avatar-s96 {
85
+ @include gl-avatar-s96;
86
+ }
87
+
88
+ .gl-sm-avatar-s16 {
89
+ @include gl-media-breakpoint-up(sm) {
90
+ @include gl-avatar-s16;
91
+ }
92
+ }
93
+
94
+ .gl-md-avatar-s16 {
95
+ @include gl-media-breakpoint-up(md) {
96
+ @include gl-avatar-s16;
97
+ }
98
+ }
99
+
100
+ .gl-lg-avatar-s16 {
101
+ @include gl-media-breakpoint-up(lg) {
102
+ @include gl-avatar-s16;
103
+ }
104
+ }
105
+
106
+ .gl-sm-avatar-s24 {
107
+ @include gl-media-breakpoint-up(sm) {
108
+ @include gl-avatar-s24;
109
+ }
110
+ }
111
+
112
+ .gl-md-avatar-s24 {
113
+ @include gl-media-breakpoint-up(md) {
114
+ @include gl-avatar-s24;
115
+ }
116
+ }
117
+
118
+ .gl-lg-avatar-s24 {
119
+ @include gl-media-breakpoint-up(lg) {
120
+ @include gl-avatar-s24;
121
+ }
122
+ }
123
+
124
+ .gl-sm-avatar-s32 {
125
+ @include gl-media-breakpoint-up(sm) {
126
+ @include gl-avatar-s32;
127
+ }
128
+ }
129
+
130
+ .gl-md-avatar-s32 {
131
+ @include gl-media-breakpoint-up(md) {
132
+ @include gl-avatar-s32;
133
+ }
134
+ }
135
+
136
+ .gl-lg-avatar-s32 {
137
+ @include gl-media-breakpoint-up(lg) {
138
+ @include gl-avatar-s32;
139
+ }
140
+ }
141
+
142
+ .gl-sm-avatar-s48 {
143
+ @include gl-media-breakpoint-up(sm) {
144
+ @include gl-avatar-s48;
145
+ }
146
+ }
147
+
148
+ .gl-md-avatar-s48 {
149
+ @include gl-media-breakpoint-up(md) {
150
+ @include gl-avatar-s48;
151
+ }
152
+ }
153
+
154
+ .gl-lg-avatar-s48 {
155
+ @include gl-media-breakpoint-up(lg) {
156
+ @include gl-avatar-s48;
157
+ }
158
+ }
159
+
160
+ .gl-sm-avatar-s64 {
161
+ @include gl-media-breakpoint-up(sm) {
162
+ @include gl-avatar-s64;
163
+ }
164
+ }
165
+
166
+ .gl-md-avatar-s64 {
167
+ @include gl-media-breakpoint-up(md) {
168
+ @include gl-avatar-s64;
169
+ }
170
+ }
171
+
172
+ .gl-lg-avatar-s64 {
173
+ @include gl-media-breakpoint-up(lg) {
174
+ @include gl-avatar-s64;
175
+ }
176
+ }
177
+
178
+ .gl-sm-avatar-s96 {
179
+ @include gl-media-breakpoint-up(sm) {
180
+ @include gl-avatar-s96;
181
+ }
182
+ }
183
+
184
+ .gl-md-avatar-s96 {
185
+ @include gl-media-breakpoint-up(md) {
186
+ @include gl-avatar-s96;
187
+ }
188
+ }
189
+
190
+ .gl-lg-avatar-s96 {
191
+ @include gl-media-breakpoint-up(lg) {
192
+ @include gl-avatar-s96;
193
+ }
194
+ }
195
+
60
196
  .gl-avatar-circle {
61
197
  @include gl-rounded-full;
62
198
  }
@@ -18,16 +18,42 @@ describe('GlAvatar', () => {
18
18
  expect(wrapper.props('size')).toBe(avatarSizeOptions[1]);
19
19
  });
20
20
 
21
- it.each([96, 64, 48, 32, 24, 16])('accepts size %s', (size) => {
22
- createWrapper({ size });
21
+ describe('when number is passed', () => {
22
+ it.each([96, 64, 48, 32, 24, 16])('accepts size %s', (size) => {
23
+ createWrapper({ size });
23
24
 
24
- expect(wrapper.props('size')).toBe(size);
25
+ expect(wrapper.props('size')).toBe(size);
26
+ });
27
+
28
+ it.each([12, 28, 36, 54, 98])('displays an error for size %s', (size) => {
29
+ createWrapper({ size });
30
+
31
+ expect(wrapper).toHaveLoggedVueErrors();
32
+ });
33
+
34
+ it('adds correct CSS class to avatar', () => {
35
+ createWrapper({ size: 16 });
36
+
37
+ expect(wrapper.classes()).toContain('gl-avatar-s16');
38
+ });
25
39
  });
26
40
 
27
- it.each([12, 28, 36, 54, 98])('displays an error for size %s', (size) => {
28
- createWrapper({ size });
41
+ describe('when object is passed', () => {
42
+ it('displays error if any of the sizes are invalid', () => {
43
+ createWrapper({ size: { default: 16, md: 32, lg: 65 } });
44
+
45
+ expect(wrapper).toHaveLoggedVueErrors();
46
+ });
47
+
48
+ it('adds correct CSS classes to avatar', () => {
49
+ createWrapper({ size: { default: 16, md: 32, lg: 64 } });
29
50
 
30
- expect(wrapper).toHaveLoggedVueErrors();
51
+ expect(wrapper.classes()).toContain(
52
+ 'gl-avatar-s16',
53
+ 'gl-md-avatar-s32',
54
+ 'gl-lg-avatar-s64'
55
+ );
56
+ });
31
57
  });
32
58
  });
33
59
  });
@@ -59,6 +59,22 @@ export const Image = (args, { argTypes }) => ({
59
59
  });
60
60
  Image.args = generateImageProps();
61
61
 
62
+ export const ResponsiveImage = (args, { argTypes }) => ({
63
+ components,
64
+ props: Object.keys(argTypes),
65
+ template: `
66
+ <gl-avatar
67
+ :size="size"
68
+ :shape="shape"
69
+ src="https://about.gitlab.com/images/press/gitlab-summit-south-africa.jpg"
70
+ />
71
+ `,
72
+ });
73
+ ResponsiveImage.args = generateImageProps({ size: { default: 24, sm: 32, md: 48, lg: 96 } });
74
+ ResponsiveImage.argTypes = {
75
+ size: { control: 'object' },
76
+ };
77
+
62
78
  export const ProjectFallback = (args, { argTypes }) => ({
63
79
  components,
64
80
  props: Object.keys(argTypes),
@@ -1,5 +1,6 @@
1
1
  <!-- eslint-disable vue/multi-word-component-names -->
2
2
  <script>
3
+ import { isNumber } from 'lodash';
3
4
  import { avatarShapeOptions, avatarSizeOptions } from '../../../utils/constants';
4
5
  import { getAvatarChar } from '../../../utils/string_utils';
5
6
 
@@ -28,18 +29,24 @@ export default {
28
29
  default: 'avatar',
29
30
  },
30
31
  size: {
31
- type: Number,
32
+ type: [Number, Object],
32
33
  required: false,
33
34
  default: avatarSizeOptions[1],
34
35
  validator: (value) => {
35
- const isValidSize = avatarSizeOptions.includes(value);
36
+ const sizes = isNumber(value) ? [value] : Object.values(value);
37
+
38
+ const areValidSizes = sizes.every((size) => {
39
+ const isValidSize = avatarSizeOptions.includes(size);
40
+
41
+ if (!isValidSize) {
42
+ /* eslint-disable-next-line no-console */
43
+ console.error(`Avatar size should be one of [${avatarSizeOptions}], received: ${size}`);
44
+ }
36
45
 
37
- if (!isValidSize) {
38
- /* eslint-disable-next-line no-console */
39
- console.error(`Avatar size should be one of [${avatarSizeOptions}], received: ${value}`);
40
- }
46
+ return isValidSize;
47
+ });
41
48
 
42
- return isValidSize;
49
+ return areValidSizes;
43
50
  },
44
51
  },
45
52
  shape: {
@@ -49,8 +56,19 @@ export default {
49
56
  },
50
57
  },
51
58
  computed: {
52
- sizeClass() {
53
- return `gl-avatar-s${this.size}`;
59
+ sizeClasses() {
60
+ if (isNumber(this.size)) {
61
+ return `gl-avatar-s${this.size}`;
62
+ }
63
+
64
+ const { default: defaultSize, ...nonDefaultSizes } = this.size;
65
+
66
+ return [
67
+ `gl-avatar-s${defaultSize || avatarSizeOptions[1]}`,
68
+ ...Object.entries(nonDefaultSizes).map(
69
+ ([breakpoint, size]) => `gl-${breakpoint}-avatar-s${size}`
70
+ ),
71
+ ];
54
72
  },
55
73
  isCircle() {
56
74
  return this.shape === avatarShapeOptions.circle;
@@ -74,14 +92,14 @@ export default {
74
92
  v-if="src"
75
93
  :src="src"
76
94
  :alt="alt"
77
- :class="['gl-avatar', { 'gl-avatar-circle': isCircle }, sizeClass]"
95
+ :class="['gl-avatar', { 'gl-avatar-circle': isCircle }, sizeClasses]"
78
96
  />
79
97
  <div
80
98
  v-else
81
99
  :class="[
82
100
  'gl-avatar gl-avatar-identicon',
83
101
  { 'gl-avatar-circle': isCircle },
84
- sizeClass,
102
+ sizeClasses,
85
103
  identiconBackgroundClass,
86
104
  ]"
87
105
  >