@atlaskit/avatar 21.4.3 → 21.4.5

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,10 +1,22 @@
1
1
  # @atlaskit/avatar
2
2
 
3
+ ## 21.4.5
4
+
5
+ ### Patch Changes
6
+
7
+ - [#67339](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/67339) [`33c37b4c2c1e`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/33c37b4c2c1e) - [ux] Remove nested images introduced in 21.4.3
8
+
9
+ ## 21.4.4
10
+
11
+ ### Patch Changes
12
+
13
+ - [#64854](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/64854) [`61b09a38c764`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/61b09a38c764) - [ux] Adds label to custom avatars using the render prop API.
14
+
3
15
  ## 21.4.3
4
16
 
5
17
  ### Patch Changes
6
18
 
7
- - [#63807](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/63807) [`538c46e739b6`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/538c46e739b6) - [ux] Add accessible name to non-interactive avatars.
19
+ - [#63807](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/63807) [`538c46e739b6`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/538c46e739b6) - [ux] Add accessible name to non-interactive avatars. If you are a making a test that relies on there being only a single element containing the avatar's expected text, skipping any elements with a `hidden` attribute will narrow down your search to only the visible element; this will make the test act the same as it would before this change.
8
20
 
9
21
  ## 21.4.2
10
22
 
@@ -23,7 +23,7 @@ var _templateObject;
23
23
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
24
24
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
25
25
  var packageName = "@atlaskit/avatar";
26
- var packageVersion = "21.4.3";
26
+ var packageVersion = "21.4.5";
27
27
 
28
28
  // eslint-disable-next-line @repo/internal/react/consistent-types-definitions
29
29
 
@@ -139,12 +139,13 @@ var Avatar = /*#__PURE__*/(0, _react.forwardRef)(function (_ref2, ref) {
139
139
 
140
140
  // add presence or status to the label by default if presence and status are passed as a string
141
141
  // if status or presence are nodes this is not added to the label by default
142
- var defaultLabel = "".concat(name || '', " ").concat(isStatus && !customStatusNode ? "(".concat(status, ")") : '', " ").concat(isPresence && !customPresenceNode ? "(".concat(presence, ")") : '').trim();
142
+ var defaultLabel = [name, isStatus && !customStatusNode && "(".concat(status, ")"), isPresence && !customPresenceNode && "(".concat(presence, ")")].filter(Boolean).join(' ');
143
143
  var isInteractive = onClick || href || isDisabled;
144
+ var containerShouldBeImage = Boolean(!isInteractive && defaultLabel);
144
145
  return (0, _react2.jsx)(AvatarContainer, {
145
146
  "data-testid": testId,
146
- role: isInteractive || !defaultLabel ? undefined : 'img',
147
- "aria-labelledby": isInteractive || !defaultLabel ? undefined : "".concat(uuid, "-label"),
147
+ role: containerShouldBeImage ? 'img' : undefined,
148
+ "aria-labelledby": containerShouldBeImage ? "".concat(uuid, "-label") : undefined,
148
149
  style: {
149
150
  display: 'inline-block',
150
151
  position: 'relative',
@@ -163,14 +164,14 @@ var Avatar = /*#__PURE__*/(0, _react.forwardRef)(function (_ref2, ref) {
163
164
  isInteractive: Boolean(href || onClick) && !isDisabled,
164
165
  isDisabled: isDisabled
165
166
  })
166
- }, componentProps()), testId && getTestId(testId, children)), isInteractive && {
167
+ }, componentProps()), testId && getTestId(testId, children)), (isInteractive || children) && {
167
168
  'aria-label': label || defaultLabel
168
169
  }), {}, {
169
170
  children: (0, _react2.jsx)(_AvatarImage.default
170
- // Only pass the name if there is an image provided. We want the
171
- // icons to be presentational if they don't show anything important.
171
+ // Only pass in the name if an image is provded and the
172
+ // container is not being used as an `img` role
172
173
  , {
173
- alt: src ? name : undefined,
174
+ alt: !containerShouldBeImage && src ? name : undefined,
174
175
  appearance: appearance,
175
176
  size: size,
176
177
  src: src,
@@ -190,7 +191,7 @@ var Avatar = /*#__PURE__*/(0, _react.forwardRef)(function (_ref2, ref) {
190
191
  borderColor: borderColor,
191
192
  status: typeof status === 'string' ? status : undefined,
192
193
  testId: testId
193
- }, customStatusNode), !isInteractive && defaultLabel ? (0, _react2.jsx)("span", {
194
+ }, customStatusNode), containerShouldBeImage ? (0, _react2.jsx)("span", {
194
195
  id: "".concat(uuid, "-label"),
195
196
  hidden: true
196
197
  }, defaultLabel) : undefined);
@@ -59,6 +59,7 @@ var AvatarImage = function AvatarImage(_ref3) {
59
59
  hasImageErrored = _useState2[0],
60
60
  setHasImageErrored = _useState2[1];
61
61
  var borderRadius = appearance === 'circle' ? '50%' : "".concat(_constants.AVATAR_RADIUS[size], "px");
62
+ var isHidden = !alt ? true : undefined;
62
63
 
63
64
  // If src changes, reset state
64
65
  (0, _react.useEffect)(function () {
@@ -71,12 +72,14 @@ var AvatarImage = function AvatarImage(_ref3) {
71
72
  label: alt,
72
73
  primaryColor: ICON_BACKGROUND,
73
74
  secondaryColor: ICON_COLOR,
74
- testId: testId && "".concat(testId, "--person")
75
+ testId: testId && "".concat(testId, "--person"),
76
+ "aria-hidden": isHidden
75
77
  }) : (0, _react2.jsx)(_ship.default, {
76
78
  label: alt,
77
79
  primaryColor: ICON_BACKGROUND,
78
80
  secondaryColor: ICON_COLOR,
79
- testId: testId && "".concat(testId, "--ship")
81
+ testId: testId && "".concat(testId, "--ship"),
82
+ "aria-hidden": isHidden
80
83
  }));
81
84
  }
82
85
  return (0, _react2.jsx)("img", {
@@ -89,7 +92,8 @@ var AvatarImage = function AvatarImage(_ref3) {
89
92
  },
90
93
  onError: function onError() {
91
94
  return setHasImageErrored(true);
92
- }
95
+ },
96
+ "aria-hidden": isHidden
93
97
  });
94
98
  };
95
99
  var _default = exports.default = AvatarImage;
@@ -74,7 +74,7 @@ var AvatarPresence = function AvatarPresence(_ref) {
74
74
  viewBox: "0 0 8 8",
75
75
  width: "100%",
76
76
  xmlns: "http://www.w3.org/2000/svg"
77
- }, /*#__PURE__*/_react.default.createElement("title", null, "(".concat(presence, ")")), getPresence(presence)) : children);
77
+ }, getPresence(presence)) : children);
78
78
  };
79
79
  var _default = exports.default = AvatarPresence;
80
80
  /**
@@ -72,7 +72,7 @@ var AvatarStatus = function AvatarStatus(_ref) {
72
72
  viewBox: "0 0 8 8",
73
73
  width: "100%",
74
74
  xmlns: "http://www.w3.org/2000/svg"
75
- }, /*#__PURE__*/_react.default.createElement("title", null, "(".concat(status, ")")), getStatus(status)) : children);
75
+ }, getStatus(status)) : children);
76
76
  };
77
77
  var _default = exports.default = AvatarStatus;
78
78
  /**
@@ -11,7 +11,7 @@ import { PresenceWrapper } from './Presence';
11
11
  import { StatusWrapper } from './Status';
12
12
  import { getButtonProps, getCustomElement, getLinkProps } from './utilities';
13
13
  const packageName = "@atlaskit/avatar";
14
- const packageVersion = "21.4.3";
14
+ const packageVersion = "21.4.5";
15
15
 
16
16
  // eslint-disable-next-line @repo/internal/react/consistent-types-definitions
17
17
 
@@ -215,12 +215,13 @@ const Avatar = /*#__PURE__*/forwardRef(({
215
215
 
216
216
  // add presence or status to the label by default if presence and status are passed as a string
217
217
  // if status or presence are nodes this is not added to the label by default
218
- const defaultLabel = `${name || ''} ${isStatus && !customStatusNode ? `(${status})` : ''} ${isPresence && !customPresenceNode ? `(${presence})` : ''}`.trim();
218
+ const defaultLabel = [name, isStatus && !customStatusNode && `(${status})`, isPresence && !customPresenceNode && `(${presence})`].filter(Boolean).join(' ');
219
219
  const isInteractive = onClick || href || isDisabled;
220
+ const containerShouldBeImage = Boolean(!isInteractive && defaultLabel);
220
221
  return jsx(AvatarContainer, {
221
222
  "data-testid": testId,
222
- role: isInteractive || !defaultLabel ? undefined : 'img',
223
- "aria-labelledby": isInteractive || !defaultLabel ? undefined : `${uuid}-label`,
223
+ role: containerShouldBeImage ? 'img' : undefined,
224
+ "aria-labelledby": containerShouldBeImage ? `${uuid}-label` : undefined,
224
225
  style: {
225
226
  display: 'inline-block',
226
227
  position: 'relative',
@@ -242,14 +243,14 @@ const Avatar = /*#__PURE__*/forwardRef(({
242
243
  }),
243
244
  ...componentProps(),
244
245
  ...(testId && getTestId(testId, children)),
245
- ...(isInteractive && {
246
+ ...((isInteractive || children) && {
246
247
  'aria-label': label || defaultLabel
247
248
  }),
248
249
  children: jsx(AvatarImage
249
- // Only pass the name if there is an image provided. We want the
250
- // icons to be presentational if they don't show anything important.
250
+ // Only pass in the name if an image is provded and the
251
+ // container is not being used as an `img` role
251
252
  , {
252
- alt: src ? name : undefined,
253
+ alt: !containerShouldBeImage && src ? name : undefined,
253
254
  appearance: appearance,
254
255
  size: size,
255
256
  src: src,
@@ -269,7 +270,7 @@ const Avatar = /*#__PURE__*/forwardRef(({
269
270
  borderColor: borderColor,
270
271
  status: typeof status === 'string' ? status : undefined,
271
272
  testId: testId
272
- }, customStatusNode), !isInteractive && defaultLabel ? jsx("span", {
273
+ }, customStatusNode), containerShouldBeImage ? jsx("span", {
273
274
  id: `${uuid}-label`,
274
275
  hidden: true
275
276
  }, defaultLabel) : undefined);
@@ -47,6 +47,7 @@ const AvatarImage = ({
47
47
  }) => {
48
48
  const [hasImageErrored, setHasImageErrored] = useState(false);
49
49
  const borderRadius = appearance === 'circle' ? '50%' : `${AVATAR_RADIUS[size]}px`;
50
+ const isHidden = !alt ? true : undefined;
50
51
 
51
52
  // If src changes, reset state
52
53
  useEffect(() => {
@@ -59,12 +60,14 @@ const AvatarImage = ({
59
60
  label: alt,
60
61
  primaryColor: ICON_BACKGROUND,
61
62
  secondaryColor: ICON_COLOR,
62
- testId: testId && `${testId}--person`
63
+ testId: testId && `${testId}--person`,
64
+ "aria-hidden": isHidden
63
65
  }) : jsx(ShipIcon, {
64
66
  label: alt,
65
67
  primaryColor: ICON_BACKGROUND,
66
68
  secondaryColor: ICON_COLOR,
67
- testId: testId && `${testId}--ship`
69
+ testId: testId && `${testId}--ship`,
70
+ "aria-hidden": isHidden
68
71
  }));
69
72
  }
70
73
  return jsx("img", {
@@ -75,7 +78,8 @@ const AvatarImage = ({
75
78
  style: {
76
79
  borderRadius: borderRadius
77
80
  },
78
- onError: () => setHasImageErrored(true)
81
+ onError: () => setHasImageErrored(true),
82
+ "aria-hidden": isHidden
79
83
  });
80
84
  };
81
85
  export default AvatarImage;
@@ -63,7 +63,7 @@ const AvatarPresence = ({
63
63
  viewBox: "0 0 8 8",
64
64
  width: "100%",
65
65
  xmlns: "http://www.w3.org/2000/svg"
66
- }, /*#__PURE__*/React.createElement("title", null, `(${presence})`), getPresence(presence)) : children);
66
+ }, getPresence(presence)) : children);
67
67
  export default AvatarPresence;
68
68
  /**
69
69
  * __Presence wrapper__
@@ -61,7 +61,7 @@ const AvatarStatus = ({
61
61
  viewBox: "0 0 8 8",
62
62
  width: "100%",
63
63
  xmlns: "http://www.w3.org/2000/svg"
64
- }, /*#__PURE__*/React.createElement("title", null, `(${status})`), getStatus(status)) : children);
64
+ }, getStatus(status)) : children);
65
65
  export default AvatarStatus;
66
66
  /**
67
67
  * Status wrapper**
@@ -16,7 +16,7 @@ import { PresenceWrapper } from './Presence';
16
16
  import { StatusWrapper } from './Status';
17
17
  import { getButtonProps, getCustomElement, getLinkProps } from './utilities';
18
18
  var packageName = "@atlaskit/avatar";
19
- var packageVersion = "21.4.3";
19
+ var packageVersion = "21.4.5";
20
20
 
21
21
  // eslint-disable-next-line @repo/internal/react/consistent-types-definitions
22
22
 
@@ -132,12 +132,13 @@ var Avatar = /*#__PURE__*/forwardRef(function (_ref2, ref) {
132
132
 
133
133
  // add presence or status to the label by default if presence and status are passed as a string
134
134
  // if status or presence are nodes this is not added to the label by default
135
- var defaultLabel = "".concat(name || '', " ").concat(isStatus && !customStatusNode ? "(".concat(status, ")") : '', " ").concat(isPresence && !customPresenceNode ? "(".concat(presence, ")") : '').trim();
135
+ var defaultLabel = [name, isStatus && !customStatusNode && "(".concat(status, ")"), isPresence && !customPresenceNode && "(".concat(presence, ")")].filter(Boolean).join(' ');
136
136
  var isInteractive = onClick || href || isDisabled;
137
+ var containerShouldBeImage = Boolean(!isInteractive && defaultLabel);
137
138
  return jsx(AvatarContainer, {
138
139
  "data-testid": testId,
139
- role: isInteractive || !defaultLabel ? undefined : 'img',
140
- "aria-labelledby": isInteractive || !defaultLabel ? undefined : "".concat(uuid, "-label"),
140
+ role: containerShouldBeImage ? 'img' : undefined,
141
+ "aria-labelledby": containerShouldBeImage ? "".concat(uuid, "-label") : undefined,
141
142
  style: {
142
143
  display: 'inline-block',
143
144
  position: 'relative',
@@ -156,14 +157,14 @@ var Avatar = /*#__PURE__*/forwardRef(function (_ref2, ref) {
156
157
  isInteractive: Boolean(href || onClick) && !isDisabled,
157
158
  isDisabled: isDisabled
158
159
  })
159
- }, componentProps()), testId && getTestId(testId, children)), isInteractive && {
160
+ }, componentProps()), testId && getTestId(testId, children)), (isInteractive || children) && {
160
161
  'aria-label': label || defaultLabel
161
162
  }), {}, {
162
163
  children: jsx(AvatarImage
163
- // Only pass the name if there is an image provided. We want the
164
- // icons to be presentational if they don't show anything important.
164
+ // Only pass in the name if an image is provded and the
165
+ // container is not being used as an `img` role
165
166
  , {
166
- alt: src ? name : undefined,
167
+ alt: !containerShouldBeImage && src ? name : undefined,
167
168
  appearance: appearance,
168
169
  size: size,
169
170
  src: src,
@@ -183,7 +184,7 @@ var Avatar = /*#__PURE__*/forwardRef(function (_ref2, ref) {
183
184
  borderColor: borderColor,
184
185
  status: typeof status === 'string' ? status : undefined,
185
186
  testId: testId
186
- }, customStatusNode), !isInteractive && defaultLabel ? jsx("span", {
187
+ }, customStatusNode), containerShouldBeImage ? jsx("span", {
187
188
  id: "".concat(uuid, "-label"),
188
189
  hidden: true
189
190
  }, defaultLabel) : undefined);
@@ -54,6 +54,7 @@ var AvatarImage = function AvatarImage(_ref3) {
54
54
  hasImageErrored = _useState2[0],
55
55
  setHasImageErrored = _useState2[1];
56
56
  var borderRadius = appearance === 'circle' ? '50%' : "".concat(AVATAR_RADIUS[size], "px");
57
+ var isHidden = !alt ? true : undefined;
57
58
 
58
59
  // If src changes, reset state
59
60
  useEffect(function () {
@@ -66,12 +67,14 @@ var AvatarImage = function AvatarImage(_ref3) {
66
67
  label: alt,
67
68
  primaryColor: ICON_BACKGROUND,
68
69
  secondaryColor: ICON_COLOR,
69
- testId: testId && "".concat(testId, "--person")
70
+ testId: testId && "".concat(testId, "--person"),
71
+ "aria-hidden": isHidden
70
72
  }) : jsx(ShipIcon, {
71
73
  label: alt,
72
74
  primaryColor: ICON_BACKGROUND,
73
75
  secondaryColor: ICON_COLOR,
74
- testId: testId && "".concat(testId, "--ship")
76
+ testId: testId && "".concat(testId, "--ship"),
77
+ "aria-hidden": isHidden
75
78
  }));
76
79
  }
77
80
  return jsx("img", {
@@ -84,7 +87,8 @@ var AvatarImage = function AvatarImage(_ref3) {
84
87
  },
85
88
  onError: function onError() {
86
89
  return setHasImageErrored(true);
87
- }
90
+ },
91
+ "aria-hidden": isHidden
88
92
  });
89
93
  };
90
94
  export default AvatarImage;
@@ -63,7 +63,7 @@ var AvatarPresence = function AvatarPresence(_ref) {
63
63
  viewBox: "0 0 8 8",
64
64
  width: "100%",
65
65
  xmlns: "http://www.w3.org/2000/svg"
66
- }, /*#__PURE__*/React.createElement("title", null, "(".concat(presence, ")")), getPresence(presence)) : children);
66
+ }, getPresence(presence)) : children);
67
67
  };
68
68
  export default AvatarPresence;
69
69
  /**
@@ -61,7 +61,7 @@ var AvatarStatus = function AvatarStatus(_ref) {
61
61
  viewBox: "0 0 8 8",
62
62
  width: "100%",
63
63
  xmlns: "http://www.w3.org/2000/svg"
64
- }, /*#__PURE__*/React.createElement("title", null, "(".concat(status, ")")), getStatus(status)) : children);
64
+ }, getStatus(status)) : children);
65
65
  };
66
66
  export default AvatarStatus;
67
67
  /**
@@ -2,9 +2,21 @@
2
2
  import { FC } from 'react';
3
3
  import { AppearanceType, SizeType } from './types';
4
4
  export interface SkeletonProps {
5
+ /**
6
+ * Indicates the shape of the avatar skeleton. Most avatars are circular, but square avatars can be used for container objects.
7
+ */
5
8
  appearance?: AppearanceType;
9
+ /**
10
+ * Color of the skeleton. By default, it will inherit the current text color.
11
+ */
6
12
  color?: string;
13
+ /**
14
+ * Defines the size of the avatar skeleton.
15
+ */
7
16
  size?: SizeType;
17
+ /**
18
+ * Defines the opacity of the avatar skeleton. Use `weight="normal"` for the default opacity, or `weight="strong"` for a bolder opacity.
19
+ */
8
20
  weight?: 'normal' | 'strong';
9
21
  }
10
22
  /**
@@ -2,9 +2,21 @@
2
2
  import { FC } from 'react';
3
3
  import { AppearanceType, SizeType } from './types';
4
4
  export interface SkeletonProps {
5
+ /**
6
+ * Indicates the shape of the avatar skeleton. Most avatars are circular, but square avatars can be used for container objects.
7
+ */
5
8
  appearance?: AppearanceType;
9
+ /**
10
+ * Color of the skeleton. By default, it will inherit the current text color.
11
+ */
6
12
  color?: string;
13
+ /**
14
+ * Defines the size of the avatar skeleton.
15
+ */
7
16
  size?: SizeType;
17
+ /**
18
+ * Defines the opacity of the avatar skeleton. Use `weight="normal"` for the default opacity, or `weight="strong"` for a bolder opacity.
19
+ */
8
20
  weight?: 'normal' | 'strong';
9
21
  }
10
22
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/avatar",
3
- "version": "21.4.3",
3
+ "version": "21.4.5",
4
4
  "description": "An avatar is a visual representation of a user or entity.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -46,7 +46,7 @@
46
46
  "@atlaskit/analytics-next": "^9.1.0",
47
47
  "@atlaskit/icon": "^22.0.0",
48
48
  "@atlaskit/theme": "^12.6.0",
49
- "@atlaskit/tokens": "^1.33.0",
49
+ "@atlaskit/tokens": "^1.34.0",
50
50
  "@babel/runtime": "^7.0.0",
51
51
  "@emotion/react": "^11.7.1",
52
52
  "@emotion/serialize": "^1.1.0",
@@ -67,6 +67,7 @@
67
67
  "@testing-library/react": "^12.1.5",
68
68
  "@types/jscodeshift": "^0.11.0",
69
69
  "color-contrast-checker": "^1.5.0",
70
+ "jest-in-case": "^1.0.2",
70
71
  "jscodeshift": "^0.13.0",
71
72
  "react-dom": "^16.8.0",
72
73
  "typescript": "~4.9.5",