@atlaskit/avatar-group 12.10.11 → 12.11.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.
Files changed (25) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/__tests__/playwright/top-layer-focus.spec.tsx +78 -0
  3. package/avatar-group/package.json +1 -8
  4. package/dist/cjs/components/avatar-group-top-layer.js +15 -25
  5. package/dist/es2019/components/avatar-group-top-layer.js +15 -26
  6. package/dist/esm/components/avatar-group-top-layer.js +15 -25
  7. package/package.json +3 -3
  8. package/types/package.json +1 -8
  9. package/dist/types-ts4.5/components/avatar-group-item.d.ts +0 -25
  10. package/dist/types-ts4.5/components/avatar-group-top-layer.d.ts +0 -44
  11. package/dist/types-ts4.5/components/avatar-group.d.ts +0 -127
  12. package/dist/types-ts4.5/components/get-overrides.d.ts +0 -2
  13. package/dist/types-ts4.5/components/grid.d.ts +0 -12
  14. package/dist/types-ts4.5/components/internal/components/focus-manager-context.d.ts +0 -12
  15. package/dist/types-ts4.5/components/internal/components/focus-manager.d.ts +0 -14
  16. package/dist/types-ts4.5/components/internal/components/popup-avatar-group.d.ts +0 -7
  17. package/dist/types-ts4.5/components/internal/hooks/use-register-item-with-focus-manager.d.ts +0 -4
  18. package/dist/types-ts4.5/components/internal/utiles/handle-focus.d.ts +0 -2
  19. package/dist/types-ts4.5/components/more-indicator.d.ts +0 -18
  20. package/dist/types-ts4.5/components/stack.d.ts +0 -14
  21. package/dist/types-ts4.5/components/types.d.ts +0 -32
  22. package/dist/types-ts4.5/components/utils.d.ts +0 -2
  23. package/dist/types-ts4.5/entry-points/avatar-group.d.ts +0 -2
  24. package/dist/types-ts4.5/entry-points/types.d.ts +0 -1
  25. package/dist/types-ts4.5/index.d.ts +0 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @atlaskit/avatar-group
2
2
 
3
+ ## 12.11.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`032135d12186b`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/032135d12186b) -
8
+ Top-layer: fix initial focus regressions on the top-layer adapters for `@atlaskit/avatar-group`
9
+ and `@atlaskit/popup`. Behind the `platform-dst-top-layer` feature gate.
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies
14
+
15
+ ## 12.10.12
16
+
17
+ ### Patch Changes
18
+
19
+ - Updated dependencies
20
+
3
21
  ## 12.10.11
4
22
 
5
23
  ### Patch Changes
@@ -0,0 +1,78 @@
1
+ import { expect, test } from '@af/integration-testing';
2
+
3
+ /**
4
+ * Avatar group: focus contract on the top-layer code path.
5
+ *
6
+ * `AvatarGroup` renders a "more" trigger that opens a `role="menu"` popover
7
+ * listing avatars beyond `maxCount`. The focus contract is:
8
+ *
9
+ * 1. Initial focus moves to the first item in the avatar list on open.
10
+ * 2. Escape closes the popover and restores focus to the more trigger.
11
+ * 3. ArrowDown moves focus between items within the menu.
12
+ *
13
+ * See: `platform/packages/design-system/top-layer/notes/architecture/focus.md`.
14
+ */
15
+
16
+ const featureFlag = 'platform-dst-top-layer';
17
+
18
+ test.describe('Avatar group: top-layer focus contract', () => {
19
+ test('initial focus: focus moves to the first overflow item on open', async ({ page }) => {
20
+ await page.visitExample<typeof import('../../examples/testing-top-layer-focus.tsx')>(
21
+ 'design-system',
22
+ 'avatar-group',
23
+ 'testing-top-layer-focus',
24
+ { featureFlag },
25
+ );
26
+
27
+ const moreTrigger = page.getByTestId('avatar-group--overflow-menu--trigger');
28
+ await moreTrigger.click();
29
+
30
+ const menu = page.getByRole('menu');
31
+ await expect(menu).toBeVisible();
32
+ // avatar-group computes `maxAvatar = total > max ? max - 1 : max` and
33
+ // emits overflow items with testId `${testId}--avatar-group-item-${index + maxAvatar}`.
34
+ // With `data.length=6` and `maxCount=3`, `maxAvatar=2`, so the first
35
+ // overflow item is at index 2.
36
+ const firstItem = page.getByTestId('avatar-group--avatar-group-item-2');
37
+ await expect(firstItem).toBeFocused();
38
+ });
39
+
40
+ test('focus restoration: Escape restores focus to the more trigger', async ({ page }) => {
41
+ await page.visitExample<typeof import('../../examples/testing-top-layer-focus.tsx')>(
42
+ 'design-system',
43
+ 'avatar-group',
44
+ 'testing-top-layer-focus',
45
+ { featureFlag },
46
+ );
47
+
48
+ const moreTrigger = page.getByTestId('avatar-group--overflow-menu--trigger');
49
+ await moreTrigger.focus();
50
+ await page.keyboard.press('ArrowDown');
51
+ await expect(page.getByRole('menu')).toBeVisible();
52
+
53
+ await page.keyboard.press('Escape');
54
+ await expect(moreTrigger).toBeFocused();
55
+ });
56
+
57
+ test('focus movement: ArrowDown moves focus between items within the menu', async ({ page }) => {
58
+ await page.visitExample<typeof import('../../examples/testing-top-layer-focus.tsx')>(
59
+ 'design-system',
60
+ 'avatar-group',
61
+ 'testing-top-layer-focus',
62
+ { featureFlag },
63
+ );
64
+
65
+ const moreTrigger = page.getByTestId('avatar-group--overflow-menu--trigger');
66
+ await moreTrigger.focus();
67
+ await page.keyboard.press('ArrowDown');
68
+
69
+ const menu = page.getByRole('menu');
70
+ await expect(menu).toBeVisible();
71
+
72
+ const items = menu.getByRole('menuitem');
73
+ await expect(items.first()).toBeFocused();
74
+
75
+ await page.keyboard.press('ArrowDown');
76
+ await expect(items.nth(1)).toBeFocused();
77
+ });
78
+ });
@@ -6,12 +6,5 @@
6
6
  "sideEffects": [
7
7
  "**/*.compiled.css"
8
8
  ],
9
- "types": "../dist/types/entry-points/avatar-group.d.ts",
10
- "typesVersions": {
11
- ">=4.5 <5.9": {
12
- "*": [
13
- "../dist/types-ts4.5/entry-points/avatar-group.d.ts"
14
- ]
15
- }
16
- }
9
+ "types": "../dist/types/entry-points/avatar-group.d.ts"
17
10
  }
@@ -11,7 +11,6 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
11
11
  var _react = _interopRequireWildcard(require("react"));
12
12
  var _bindEventListener = require("bind-event-listener");
13
13
  var _keycodes = require("@atlaskit/ds-lib/keycodes");
14
- var _useFocusEvent = _interopRequireDefault(require("@atlaskit/ds-lib/use-focus-event"));
15
14
  var _menu = require("@atlaskit/menu");
16
15
  var _animations = require("@atlaskit/top-layer/animations");
17
16
  var _getAriaForTrigger = require("@atlaskit/top-layer/get-aria-for-trigger");
@@ -107,27 +106,27 @@ function MoreDropdownTopLayer(_ref) {
107
106
 
108
107
  // ArrowDown-to-open: when the trigger is focused and the menu is closed,
109
108
  // pressing ArrowDown opens the menu (WAI-ARIA menu button pattern).
110
- // We track focus on the trigger wrapper to avoid threading onFocus/onBlur
111
- // through the renderMoreButton/MoreIndicator prop plumbing.
112
- var triggerWrapperRef = (0, _react.useRef)(null);
113
- var _useFocus = (0, _useFocusEvent.default)(),
114
- isFocused = _useFocus.isFocused,
115
- triggerFocusBind = _useFocus.bindFocus;
109
+ //
110
+ // Bind the keydown listener directly to the trigger element via its ref so
111
+ // that opening the menu does not trigger a focus-driven re-render of the
112
+ // host component, which would unmount and remount the menu items and drop
113
+ // menuitem focus.
116
114
  (0, _react.useEffect)(function () {
117
- if (!isFocused || isOpen) {
115
+ var trigger = triggerRef.current;
116
+ if (!trigger || isOpen) {
118
117
  return;
119
118
  }
120
- return (0, _bindEventListener.bind)(window, {
119
+ return (0, _bindEventListener.bind)(trigger, {
121
120
  type: 'keydown',
122
- listener: function openOnArrowDown(e) {
123
- if (e.key === _keycodes.KEY_DOWN) {
121
+ listener: function openOnArrowDown(event) {
122
+ if (event.key === _keycodes.KEY_DOWN) {
124
123
  // Prevent page scroll when opening the menu via ArrowDown.
125
- e.preventDefault();
126
- handleTriggerClicked(e);
124
+ event.preventDefault();
125
+ handleTriggerClicked(event);
127
126
  }
128
127
  }
129
128
  });
130
- }, [isFocused, isOpen, handleTriggerClicked]);
129
+ }, [isOpen, handleTriggerClicked]);
131
130
  var triggerAria = (0, _getAriaForTrigger.getAriaForTrigger)({
132
131
  role: 'menu',
133
132
  isOpen: isOpen,
@@ -136,20 +135,11 @@ function MoreDropdownTopLayer(_ref) {
136
135
  var setTriggerRef = (0, _react.useCallback)(function (node) {
137
136
  triggerRef.current = node;
138
137
  }, []);
139
- return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", {
140
- ref: triggerWrapperRef,
141
- onFocus: triggerFocusBind.onFocus,
142
- onBlur: triggerFocusBind.onBlur
143
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- display: contents is a layout-neutral wrapper; it cannot affect visual output.
144
- ,
145
- style: {
146
- display: 'contents'
147
- }
148
- }, renderMoreButton(_objectSpread(_objectSpread({
138
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, renderMoreButton(_objectSpread(_objectSpread({
149
139
  ref: setTriggerRef
150
140
  }, triggerAria), {}, {
151
141
  onClick: handleTriggerClicked
152
- }))), /*#__PURE__*/_react.default.createElement(_popover.Popover, {
142
+ })), /*#__PURE__*/_react.default.createElement(_popover.Popover, {
153
143
  ref: popoverRef,
154
144
  id: popoverId,
155
145
  role: "menu",
@@ -2,7 +2,6 @@ import _extends from "@babel/runtime/helpers/extends";
2
2
  import React, { useCallback, useEffect, useRef } from 'react';
3
3
  import { bind } from 'bind-event-listener';
4
4
  import { KEY_DOWN } from '@atlaskit/ds-lib/keycodes';
5
- import useFocus from '@atlaskit/ds-lib/use-focus-event';
6
5
  import { MenuGroup, Section } from '@atlaskit/menu';
7
6
  import { slideAndFade } from '@atlaskit/top-layer/animations';
8
7
  import { getAriaForTrigger } from '@atlaskit/top-layer/get-aria-for-trigger';
@@ -94,28 +93,27 @@ export function MoreDropdownTopLayer({
94
93
 
95
94
  // ArrowDown-to-open: when the trigger is focused and the menu is closed,
96
95
  // pressing ArrowDown opens the menu (WAI-ARIA menu button pattern).
97
- // We track focus on the trigger wrapper to avoid threading onFocus/onBlur
98
- // through the renderMoreButton/MoreIndicator prop plumbing.
99
- const triggerWrapperRef = useRef(null);
100
- const {
101
- isFocused,
102
- bindFocus: triggerFocusBind
103
- } = useFocus();
96
+ //
97
+ // Bind the keydown listener directly to the trigger element via its ref so
98
+ // that opening the menu does not trigger a focus-driven re-render of the
99
+ // host component, which would unmount and remount the menu items and drop
100
+ // menuitem focus.
104
101
  useEffect(() => {
105
- if (!isFocused || isOpen) {
102
+ const trigger = triggerRef.current;
103
+ if (!trigger || isOpen) {
106
104
  return;
107
105
  }
108
- return bind(window, {
106
+ return bind(trigger, {
109
107
  type: 'keydown',
110
- listener: function openOnArrowDown(e) {
111
- if (e.key === KEY_DOWN) {
108
+ listener: function openOnArrowDown(event) {
109
+ if (event.key === KEY_DOWN) {
112
110
  // Prevent page scroll when opening the menu via ArrowDown.
113
- e.preventDefault();
114
- handleTriggerClicked(e);
111
+ event.preventDefault();
112
+ handleTriggerClicked(event);
115
113
  }
116
114
  }
117
115
  });
118
- }, [isFocused, isOpen, handleTriggerClicked]);
116
+ }, [isOpen, handleTriggerClicked]);
119
117
  const triggerAria = getAriaForTrigger({
120
118
  role: 'menu',
121
119
  isOpen,
@@ -124,20 +122,11 @@ export function MoreDropdownTopLayer({
124
122
  const setTriggerRef = useCallback(node => {
125
123
  triggerRef.current = node;
126
124
  }, []);
127
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
128
- ref: triggerWrapperRef,
129
- onFocus: triggerFocusBind.onFocus,
130
- onBlur: triggerFocusBind.onBlur
131
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- display: contents is a layout-neutral wrapper; it cannot affect visual output.
132
- ,
133
- style: {
134
- display: 'contents'
135
- }
136
- }, renderMoreButton({
125
+ return /*#__PURE__*/React.createElement(React.Fragment, null, renderMoreButton({
137
126
  ref: setTriggerRef,
138
127
  ...triggerAria,
139
128
  onClick: handleTriggerClicked
140
- })), /*#__PURE__*/React.createElement(Popover, {
129
+ }), /*#__PURE__*/React.createElement(Popover, {
141
130
  ref: popoverRef,
142
131
  id: popoverId,
143
132
  role: "menu",
@@ -5,7 +5,6 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
5
5
  import React, { useCallback, useEffect, useRef } from 'react';
6
6
  import { bind } from 'bind-event-listener';
7
7
  import { KEY_DOWN } from '@atlaskit/ds-lib/keycodes';
8
- import useFocus from '@atlaskit/ds-lib/use-focus-event';
9
8
  import { MenuGroup, Section } from '@atlaskit/menu';
10
9
  import { slideAndFade } from '@atlaskit/top-layer/animations';
11
10
  import { getAriaForTrigger } from '@atlaskit/top-layer/get-aria-for-trigger';
@@ -98,27 +97,27 @@ export function MoreDropdownTopLayer(_ref) {
98
97
 
99
98
  // ArrowDown-to-open: when the trigger is focused and the menu is closed,
100
99
  // pressing ArrowDown opens the menu (WAI-ARIA menu button pattern).
101
- // We track focus on the trigger wrapper to avoid threading onFocus/onBlur
102
- // through the renderMoreButton/MoreIndicator prop plumbing.
103
- var triggerWrapperRef = useRef(null);
104
- var _useFocus = useFocus(),
105
- isFocused = _useFocus.isFocused,
106
- triggerFocusBind = _useFocus.bindFocus;
100
+ //
101
+ // Bind the keydown listener directly to the trigger element via its ref so
102
+ // that opening the menu does not trigger a focus-driven re-render of the
103
+ // host component, which would unmount and remount the menu items and drop
104
+ // menuitem focus.
107
105
  useEffect(function () {
108
- if (!isFocused || isOpen) {
106
+ var trigger = triggerRef.current;
107
+ if (!trigger || isOpen) {
109
108
  return;
110
109
  }
111
- return bind(window, {
110
+ return bind(trigger, {
112
111
  type: 'keydown',
113
- listener: function openOnArrowDown(e) {
114
- if (e.key === KEY_DOWN) {
112
+ listener: function openOnArrowDown(event) {
113
+ if (event.key === KEY_DOWN) {
115
114
  // Prevent page scroll when opening the menu via ArrowDown.
116
- e.preventDefault();
117
- handleTriggerClicked(e);
115
+ event.preventDefault();
116
+ handleTriggerClicked(event);
118
117
  }
119
118
  }
120
119
  });
121
- }, [isFocused, isOpen, handleTriggerClicked]);
120
+ }, [isOpen, handleTriggerClicked]);
122
121
  var triggerAria = getAriaForTrigger({
123
122
  role: 'menu',
124
123
  isOpen: isOpen,
@@ -127,20 +126,11 @@ export function MoreDropdownTopLayer(_ref) {
127
126
  var setTriggerRef = useCallback(function (node) {
128
127
  triggerRef.current = node;
129
128
  }, []);
130
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
131
- ref: triggerWrapperRef,
132
- onFocus: triggerFocusBind.onFocus,
133
- onBlur: triggerFocusBind.onBlur
134
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- display: contents is a layout-neutral wrapper; it cannot affect visual output.
135
- ,
136
- style: {
137
- display: 'contents'
138
- }
139
- }, renderMoreButton(_objectSpread(_objectSpread({
129
+ return /*#__PURE__*/React.createElement(React.Fragment, null, renderMoreButton(_objectSpread(_objectSpread({
140
130
  ref: setTriggerRef
141
131
  }, triggerAria), {}, {
142
132
  onClick: handleTriggerClicked
143
- }))), /*#__PURE__*/React.createElement(Popover, {
133
+ })), /*#__PURE__*/React.createElement(Popover, {
144
134
  ref: popoverRef,
145
135
  id: popoverId,
146
136
  role: "menu",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/avatar-group",
3
- "version": "12.10.11",
3
+ "version": "12.11.0",
4
4
  "description": "An avatar group displays a number of avatars grouped together in a stack or grid.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -37,10 +37,10 @@
37
37
  "@atlaskit/menu": "^8.5.0",
38
38
  "@atlaskit/motion": "^6.2.0",
39
39
  "@atlaskit/platform-feature-flags": "^1.1.0",
40
- "@atlaskit/popup": "^4.25.0",
40
+ "@atlaskit/popup": "^4.26.0",
41
41
  "@atlaskit/tokens": "^13.4.0",
42
42
  "@atlaskit/tooltip": "^22.6.0",
43
- "@atlaskit/top-layer": "^0.17.0",
43
+ "@atlaskit/top-layer": "^0.18.0",
44
44
  "@babel/runtime": "^7.0.0",
45
45
  "@compiled/react": "^0.20.0",
46
46
  "bind-event-listener": "^3.0.0"
@@ -6,12 +6,5 @@
6
6
  "sideEffects": [
7
7
  "**/*.compiled.css"
8
8
  ],
9
- "types": "../dist/types/entry-points/types.d.ts",
10
- "typesVersions": {
11
- ">=4.5 <5.9": {
12
- "*": [
13
- "../dist/types-ts4.5/entry-points/types.d.ts"
14
- ]
15
- }
16
- }
9
+ "types": "../dist/types/entry-points/types.d.ts"
17
10
  }
@@ -1,25 +0,0 @@
1
- import React, { type ElementType } from 'react';
2
- import Avatar from '@atlaskit/avatar';
3
- import { type getOverrides } from './get-overrides';
4
- import { type AvatarProps, type onAvatarClickHandler } from './types';
5
- export interface AvatarGroupItemProps {
6
- avatar: AvatarProps;
7
- /**
8
- * Custom component used to render the avatar inside the dropdown menu item.
9
- * When not provided, defaults to the standard Avatar component.
10
- */
11
- avatarComponent?: typeof Avatar | ElementType<AvatarProps>;
12
- isActive?: boolean;
13
- isHover?: boolean;
14
- avatarOverrides?: ReturnType<typeof getOverrides>['Avatar'];
15
- index: number;
16
- onAvatarClick?: onAvatarClickHandler;
17
- testId?: string;
18
- /**
19
- * Use this to override the accessibility role for the element.
20
- * When used inside a dropdown menu, this should be set to "menuitem".
21
- */
22
- role?: string;
23
- }
24
- declare const AvatarGroupItem: React.ForwardRefExoticComponent<React.PropsWithoutRef<AvatarGroupItemProps> & React.RefAttributes<HTMLElement>>;
25
- export default AvatarGroupItem;
@@ -1,44 +0,0 @@
1
- import React, { type MouseEventHandler } from 'react';
2
- import { type AvatarGroupOverrides, type AvatarProps, type onAvatarClickHandler } from './types';
3
- type TMoreDropdownTopLayerProps = {
4
- isOpen: boolean;
5
- onClose: () => void;
6
- isTriggeredUsingKeyboard: boolean;
7
- data: Array<AvatarProps>;
8
- max: number;
9
- overrides?: AvatarGroupOverrides;
10
- onAvatarClick?: onAvatarClickHandler;
11
- testId?: string;
12
- labelId: string;
13
- renderMoreButton: (props: {
14
- 'aria-controls'?: string;
15
- 'aria-expanded'?: boolean;
16
- 'aria-haspopup'?: boolean | 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid';
17
- onClick: MouseEventHandler;
18
- ref?: React.Ref<HTMLElement>;
19
- }) => React.ReactNode;
20
- handleTriggerClicked: (event: React.MouseEvent | KeyboardEvent) => void;
21
- bindFocus: {
22
- onFocus: (event: React.FocusEvent) => void;
23
- onBlur: (event: React.FocusEvent) => void;
24
- };
25
- };
26
- /**
27
- * Top-layer implementation of the avatar group overflow dropdown.
28
- *
29
- * Replaces the legacy `@atlaskit/popup` rendering pipeline
30
- * (Popper.js + Portal + focus-trap + @atlaskit/layering)
31
- * with the native Popover API + CSS Anchor Positioning via `@atlaskit/top-layer`.
32
- *
33
- * Uses `role="menu"` with arrow key navigation for correct menu semantics.
34
- *
35
- * Gated behind the `platform-dst-top-layer` feature flag.
36
- *
37
- * Legacy props that are no-ops in the top-layer path (not accepted here):
38
- * - zIndex: stacking managed by browser top layer
39
- * - shouldRenderToParent: always renders in top layer
40
- * - boundary / rootBoundary: viewport is the natural boundary
41
- * - shouldFlip: CSS Anchor Positioning handles flipping
42
- */
43
- export declare function MoreDropdownTopLayer({ isOpen, onClose, isTriggeredUsingKeyboard: _isTriggeredUsingKeyboard, data, max, overrides, onAvatarClick, testId, labelId, renderMoreButton, handleTriggerClicked, bindFocus: _bindFocus, }: TMoreDropdownTopLayerProps): React.JSX.Element;
44
- export {};
@@ -1,127 +0,0 @@
1
- import React, { type ElementType, type MouseEventHandler } from 'react';
2
- import Avatar, { type AppearanceType } from '@atlaskit/avatar';
3
- import { type PositionType } from '@atlaskit/tooltip';
4
- import { type AvatarGroupOverrides, type AvatarGroupSize, type AvatarProps, type onAvatarClickHandler } from './types';
5
- export interface AvatarGroupProps {
6
- /**
7
- * Indicates the layout of the avatar group.
8
- * Avatars will either be overlapped in a stack, or
9
- * laid out in an even grid formation.
10
- * Defaults to "stack".
11
- */
12
- appearance?: 'grid' | 'stack';
13
- /**
14
- * Indicates the shape of the more indicator. Most more indicators are circular, but square more indicators
15
- * can be used for 'container' objects.
16
- */
17
- moreIndicatorAppearance?: AppearanceType;
18
- /**
19
- * Component used to render each avatar.
20
- */
21
- avatar?: typeof Avatar | ElementType<AvatarProps>;
22
- /**
23
- * The maximum number of avatars allowed in the list.
24
- * Defaults to 5 when displayed as a stack,
25
- * and 11 when displayed as a grid.
26
- */
27
- maxCount?: number;
28
- /**
29
- * Defines the size of the avatar.
30
- * Defaults to "medium".
31
- *
32
- * Note: The "xsmall" size that exists on Avatar is not supported here because elements such as the more indicator cannot be displayed in an accessible manner at that size.
33
- */
34
- size?: AvatarGroupSize;
35
- /**
36
- * Typically the background color that the avatar is presented on.
37
- * Accepts any color argument that the CSS border-color property accepts.
38
- */
39
- borderColor?: string;
40
- /**
41
- * An array of avatar prop data, that are spread onto each `avatar` component.
42
- *
43
- * For further usage information on AvatarPropTypes, the supported props for `avatar`, refer to [Avatar's prop documentation](https://atlassian.design/components/avatar/code).
44
- */
45
- data: Array<AvatarProps>;
46
- /**
47
- * Handle the click event on the avatar item.
48
- * Note that if an onClick prop is provided as part of avatar data, it will take precedence over onAvatarClick.
49
- */
50
- onAvatarClick?: onAvatarClickHandler;
51
- /**
52
- * Take control of the click event on the more indicator.
53
- * This will cancel the default dropdown behavior.
54
- */
55
- onMoreClick?: MouseEventHandler;
56
- /**
57
- * Provide additional props to the MoreButton.
58
- * Example use cases: altering tab order by providing tabIndex;
59
- * adding onClick behaviour without losing the default dropdown
60
- */
61
- showMoreButtonProps?: Partial<React.HTMLAttributes<HTMLElement>>;
62
- /**
63
- * Element the overflow popup should be attached to.
64
- * Defaults to "viewport".
65
- */
66
- boundariesElement?: 'viewport' | 'window' | 'scrollParent';
67
- /**
68
- * A `testId` prop is provided for specified elements,
69
- * which is a unique string that appears as a data attribute `data-testid` in the rendered code,
70
- * serving as a hook for automated tests.
71
- */
72
- /**
73
- * Will set these elements when defined:
74
- * - Container element - `{testId}--avatar-group`
75
- * - Avatar items - `{testId}--avatar-{index}`
76
- * - Overflow menu button - `{testId}--overflow-menu--trigger`
77
- * - Overflow menu content - `{testId}--overflow-menu--content`
78
- */
79
- testId?: string;
80
- /**
81
- * Custom overrides for the composed components.
82
- */
83
- overrides?: AvatarGroupOverrides;
84
- /**
85
- *
86
- * Where the tooltip should appear relative to its target.
87
- * Defaults to tooltip position "bottom".
88
- */
89
- tooltipPosition?: Extract<PositionType, 'bottom' | 'top'>;
90
- /**
91
- * Disables tooltips.
92
- */
93
- isTooltipDisabled?: boolean;
94
- /**
95
- * Text to be used as aria-label for the list of avatars.
96
- * Screen reader announcement with default label, which is `avatar group`, is `list, avatar group, X items`.
97
- *
98
- * The label should describe the `AvatarGroup`'s entities, for instance:
99
- * - `label="team members"`, screen reader announcement would be `list team members, X items`
100
- * - `label="reviewers"` screen reader announcement would be `list reviewers, X items`
101
- *
102
- * When there are several AvatarGroups on the page you should use a unique label to let users distinguish different lists.
103
- */
104
- label?: string;
105
- /**
106
- * Determines whether the 'show more' popup has `shouldRenderToParent` applied.
107
- */
108
- shouldPopupRenderToParent?: boolean;
109
- /**
110
- * Text to be used as aria-label for the more indicator.
111
- * If provided, this will be used exactly as-is for the aria-label.
112
- * If not provided, but an `aria-label` is provided via `showMoreButtonProps`, that will be used instead.
113
- * If neither is provided, the aria-label will default to "N more people" where N is the number of people that are not visible (e.g. "5 more people").
114
- */
115
- moreIndicatorLabel?: string;
116
- }
117
- /**
118
- * __Avatar group__
119
- *
120
- * An avatar group displays a number of avatars grouped together in a stack or grid.
121
- *
122
- * - [Examples](https://atlassian.design/components/avatar-group/examples)
123
- * - [Code](https://atlassian.design/components/avatar-group/code)
124
- * - [Usage](https://atlassian.design/components/avatar-group/usage)
125
- */
126
- declare const AvatarGroup: ({ appearance, moreIndicatorAppearance, avatar, borderColor, boundariesElement, data, isTooltipDisabled, maxCount, onAvatarClick, onMoreClick, overrides, showMoreButtonProps, size, testId, label, moreIndicatorLabel, tooltipPosition, shouldPopupRenderToParent, }: AvatarGroupProps) => React.JSX.Element;
127
- export default AvatarGroup;
@@ -1,2 +0,0 @@
1
- import type { AvatarGroupOverrides, DeepRequired } from './types';
2
- export declare function getOverrides(overrides?: AvatarGroupOverrides): DeepRequired<AvatarGroupOverrides>;
@@ -1,12 +0,0 @@
1
- /**
2
- * @jsxRuntime classic
3
- * @jsx jsx
4
- */
5
- import { type FC, type ReactNode } from 'react';
6
- declare const Grid: FC<{
7
- children: ReactNode;
8
- testId?: string;
9
- 'aria-label': string;
10
- id?: string;
11
- }>;
12
- export default Grid;
@@ -1,12 +0,0 @@
1
- import React from 'react';
2
- import { type FocusableElement } from '../../types';
3
- /**
4
- * Context provider which maintains the list of focusable elements and a method to
5
- * register new menu items.
6
- * This list drives the keyboard navgation of the menu.
7
- *
8
- */
9
- export declare const FocusManagerContext: React.Context<{
10
- menuItemRefs: FocusableElement[];
11
- registerRef: (ref: FocusableElement) => void;
12
- }>;
@@ -1,14 +0,0 @@
1
- import { type FC, type ReactNode } from 'react';
2
- /**
3
- * __Focus manager__
4
- *
5
- * A focus manager {description}.
6
- *
7
- * - [Examples](https://atlassian.design/components/{packageName}/examples)
8
- * - [Code](https://atlassian.design/components/{packageName}/code)
9
- * - [Usage](https://atlassian.design/components/{packageName}/usage)
10
- */
11
- declare const FocusManager: FC<{
12
- children: ReactNode;
13
- }>;
14
- export default FocusManager;
@@ -1,7 +0,0 @@
1
- import React from 'react';
2
- import { type PopupAvatarGroupProps } from '../../types';
3
- /**
4
- * It sets focus to the first avatar when popup is open.
5
- */
6
- declare const PopupAvatarGroup: ({ children, isLoading, maxHeight, maxWidth, minHeight, minWidth, onClick, role, setInitialFocusRef, spacing, testId, ...rest }: PopupAvatarGroupProps) => React.JSX.Element;
7
- export default PopupAvatarGroup;
@@ -1,4 +0,0 @@
1
- import { type RefObject } from 'react';
2
- import { type FocusableElement } from '../../types';
3
- declare function useRegisterItemWithFocusManager(): RefObject<FocusableElement>;
4
- export default useRegisterItemWithFocusManager;
@@ -1,2 +0,0 @@
1
- import { type FocusableElement } from '../../types';
2
- export default function handleFocus(refs: Array<FocusableElement>): (e: KeyboardEvent) => void;
@@ -1,18 +0,0 @@
1
- import { type AppearanceType, type AvatarClickEventHandler } from '@atlaskit/avatar';
2
- import { type AvatarGroupSize } from './types';
3
- export interface MoreIndicatorProps {
4
- count: number;
5
- 'aria-controls'?: string;
6
- 'aria-expanded'?: boolean;
7
- 'aria-haspopup'?: boolean | 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid';
8
- moreIndicatorLabel?: string;
9
- buttonProps: Partial<React.HTMLAttributes<HTMLElement>>;
10
- onClick: AvatarClickEventHandler;
11
- isActive: boolean;
12
- size: AvatarGroupSize;
13
- appearance?: AppearanceType;
14
- borderColor?: string;
15
- testId?: string;
16
- }
17
- declare const MoreIndicator: React.ForwardRefExoticComponent<React.PropsWithoutRef<MoreIndicatorProps> & React.RefAttributes<HTMLButtonElement>>;
18
- export default MoreIndicator;
@@ -1,14 +0,0 @@
1
- /**
2
- * @jsxRuntime classic
3
- * @jsx jsx
4
- */
5
- import { type FC, type ReactNode } from 'react';
6
- import { type AvatarGroupSize } from './types';
7
- declare const Stack: FC<{
8
- children: ReactNode;
9
- testId?: string;
10
- 'aria-label': string;
11
- size: AvatarGroupSize;
12
- id?: string;
13
- }>;
14
- export default Stack;
@@ -1,32 +0,0 @@
1
- import type { ElementType, ForwardRefExoticComponent, ReactNode, RefAttributes } from 'react';
2
- import type { AnalyticsEvent } from '@atlaskit/analytics-next';
3
- import { type default as Avatar, type AvatarPropTypes, type SizeType } from '@atlaskit/avatar';
4
- import { type MenuGroupProps } from '@atlaskit/menu';
5
- import { type ContentProps } from '@atlaskit/popup';
6
- import type { AvatarGroupItemProps } from './avatar-group-item';
7
- import { type MoreIndicatorProps } from './more-indicator';
8
- export type DeepRequired<T> = {
9
- [P in keyof T]-?: Required<T[P]>;
10
- };
11
- export type AvatarProps = AvatarPropTypes & {
12
- name: string;
13
- key?: string | number;
14
- };
15
- export interface AvatarGroupOverrides {
16
- AvatarGroupItem?: {
17
- render?: (Component: ForwardRefExoticComponent<AvatarGroupItemProps & RefAttributes<HTMLElement>>, props: AvatarGroupItemProps, index: number) => ReactNode;
18
- };
19
- Avatar?: {
20
- render?: (Component: typeof Avatar | ElementType<AvatarProps>, props: AvatarProps, index: number) => ReactNode;
21
- };
22
- MoreIndicator?: {
23
- render?: (Component: ForwardRefExoticComponent<MoreIndicatorProps & RefAttributes<HTMLButtonElement>>, props: MoreIndicatorProps) => ReactNode;
24
- };
25
- }
26
- export type onAvatarClickHandler = (event: React.MouseEvent, analyticsEvent: AnalyticsEvent | undefined, index: number) => void;
27
- export type FocusableElement = HTMLAnchorElement | HTMLButtonElement;
28
- export type Action = 'next' | 'prev' | 'first' | 'last';
29
- export interface PopupAvatarGroupProps extends MenuGroupProps {
30
- setInitialFocusRef?: ContentProps['setInitialFocusRef'];
31
- }
32
- export type AvatarGroupSize = Exclude<SizeType, 'xsmall'>;
@@ -1,2 +0,0 @@
1
- import type { AvatarProps } from './types';
2
- export declare const composeUniqueKey: (props: AvatarProps, index: number) => string | number;
@@ -1,2 +0,0 @@
1
- export { default } from '../components/avatar-group';
2
- export type { AvatarGroupProps } from '../components/avatar-group';
@@ -1 +0,0 @@
1
- export type { AvatarProps, AvatarGroupOverrides } from '../components/types';
@@ -1,3 +0,0 @@
1
- export { default } from './components/avatar-group';
2
- export type { AvatarGroupProps } from './components/avatar-group';
3
- export type { AvatarProps, AvatarGroupOverrides } from './components/types';