diff --git a/core/components/atoms/avatarGroup/AvatarGroup.tsx b/core/components/atoms/avatarGroup/AvatarGroup.tsx index 865c1fe80f..836c55cd02 100644 --- a/core/components/atoms/avatarGroup/AvatarGroup.tsx +++ b/core/components/atoms/avatarGroup/AvatarGroup.tsx @@ -8,7 +8,7 @@ import AvatarCount from './AvatarCount'; import Avatars from './Avatars'; import AvatarPopperBody from './AvatarPopperBody'; -interface AvatarData extends Record { +export interface AvatarData extends Record { firstName?: string; lastName?: string; appearance?: AvatarProps['appearance']; @@ -23,9 +23,11 @@ interface AvatarPopoverProps { appendToBody?: PopoverProps['appendToBody']; dark?: PopoverProps['dark']; position?: PopoverProps['position']; - on?: PopoverProps['on']; - maxHeight?: number; popperClassName?: string; + on?: PopoverProps['on']; + maxHeight?: number | string; + minHeight?: number | string; + width?: number | string; } export interface AvatarGroupProps extends BaseProps { @@ -65,10 +67,11 @@ export interface AvatarGroupProps extends BaseProps { * AvatarPopoverProps: { * popperRenderer?: (names: AvatarData[]) => JSX.Element; * appendToBody?: boolean; - * dark?: boolean; * position?: Position; * on?: ActionType; * maxHeight?: number; + * minHeight?: number | string; + * width?: number | string; * popperClassName?: string; * } * @@ -77,10 +80,11 @@ export interface AvatarGroupProps extends BaseProps { * | --- | --- | --- | * | popperRenderer | Callback function to create custom popover content | | * | appendToBody | Appends `Popover` wrapper inside body | true | - * | dark | Changes background of `Popover` | true | * | position | Position to place `Popover` | bottom | * | on | Event triggering the `Popover` | hover | - * | maxHeight | Max height of `Popover Text Wrapper` (does not work in case of custom popperRenderer) | 150 | + * | maxHeight | Max height of `Popover Text Wrapper` (does not work in case of custom popperRenderer) | 256 | + * | minHeight | Min height of `Popover Text Wrapper` (does not work in case of custom popperRenderer) | | + * | width | width of `Popover Text Wrapper` (does not work in case of custom popperRenderer) | 176 | * | popperClassName | Custom className added to `Popover` | | * */ @@ -96,10 +100,11 @@ export const AvatarGroup = (props: AvatarGroupProps) => { const { popperRenderer, - maxHeight = 150, + maxHeight = 256, + width = 176, + minHeight, position = 'bottom', on = 'hover', - dark = true, appendToBody = true, popperClassName = '', } = popoverOptions; @@ -128,31 +133,24 @@ export const AvatarGroup = (props: AvatarGroupProps) => { className ); - const popperClass = classNames( - { - ['AvatarGroup-Popper']: true, - }, - popperClassName - ); - return (
{list.length - max > 0 && list.length !== 3 && ( } position={position} appendToBody={appendToBody} - className={popperClass} offset="medium" > )} diff --git a/core/components/atoms/avatarGroup/AvatarPopperBody.tsx b/core/components/atoms/avatarGroup/AvatarPopperBody.tsx index 16f2c9d948..5c9e57ef8c 100644 --- a/core/components/atoms/avatarGroup/AvatarPopperBody.tsx +++ b/core/components/atoms/avatarGroup/AvatarPopperBody.tsx @@ -1,35 +1,61 @@ import * as React from 'react'; -import { Text } from '@/index'; +import { Text, Listbox, Tooltip } from '@/index'; import classNames from 'classnames'; +import { AvatarData } from './AvatarGroup'; -const AvatarPopperBody = (props: any) => { - const { hiddenAvatarList, popperRenderer, maxHeight, dark } = props; +interface AvatarPopperProps { + popperRenderer?: (names: AvatarData[]) => JSX.Element; + maxHeight?: number | string; + minHeight?: number | string; + width?: number | string; + popperClassName?: string; + hiddenAvatarList: AvatarData[]; +} + +const AvatarPopperBody = (props: AvatarPopperProps) => { + const { hiddenAvatarList, popperRenderer, maxHeight, minHeight, width, popperClassName } = props; if (popperRenderer) { return popperRenderer(hiddenAvatarList); } + const popperClass = classNames( + { + ['AvatarGroup-Popper py-3']: true, + }, + popperClassName + ); + return ( -
-
- {hiddenAvatarList.map((item: any, ind: any) => { - const { firstName = '', lastName = '', tooltipSuffix = '' } = item; +
+ + {hiddenAvatarList.map((item: AvatarData, index: number) => { + const { firstName = '', lastName = '', tooltipSuffix = '', disabled } = item; const name = `${firstName} ${lastName} ${tooltipSuffix}`; - const AvatarTextClass = classNames({ - [`mb-4`]: ind < hiddenAvatarList.length - 1, - }); + const elementRef = React.useRef(null); + return ( - - {name} - + + + + {name} + + + ); })} -
+
); }; diff --git a/core/components/atoms/avatarGroup/__stories__/OverflowBehavior.story.jsx b/core/components/atoms/avatarGroup/__stories__/OverflowBehavior.story.jsx new file mode 100644 index 0000000000..9bc14dc45f --- /dev/null +++ b/core/components/atoms/avatarGroup/__stories__/OverflowBehavior.story.jsx @@ -0,0 +1,84 @@ +import * as React from 'react'; +import { AvatarGroup, Text } from '@/index'; +import { list } from './AvatarList'; + +export const OverflowBehavior = () => { + return ( +
+
+ Dynamic Width +
+ +
+
+
+ Truncate +
+ +
+
+
+ ); +}; + +const customCode = `() => { + const list = [ + { + firstName: 'John', + lastName: 'Doe', + }, + { + firstName: 'Steven', + lastName: 'Packton', + }, + { + firstName: 'Nancy', + lastName: 'Wheeler' + }, + { + firstName: 'Monica', + lastName: 'Geller' + }, + { + firstName: 'Arya', + lastName: 'Stark', + }, + { + firstName: 'Rachel', + lastName: 'Green', + }, + { + firstName: 'Walter Paxton', + lastName: 'Wheeler' + }, + ]; + + return ( +
+
+ Dynamic Width +
+ +
+
+
+ Truncate +
+ +
+
+
+ ); +}`; + +export default { + title: 'Components/Avatar/AvatarGroup/Overflow Behavior', + component: AvatarGroup, + parameters: { + docs: { + docPage: { + customCode, + }, + }, + }, +}; diff --git a/core/components/atoms/avatarGroup/__stories__/index.story.jsx b/core/components/atoms/avatarGroup/__stories__/index.story.jsx index ee2f14ea8f..425c1a83a4 100644 --- a/core/components/atoms/avatarGroup/__stories__/index.story.jsx +++ b/core/components/atoms/avatarGroup/__stories__/index.story.jsx @@ -3,16 +3,14 @@ import { AvatarGroup } from '@/index'; import { list } from './AvatarList'; export const all = () => { - const position = 'bottom-end'; + const position = 'bottom'; const on = 'hover'; - const dark = true; const max = 2; const options = { max, popoverOptions: { on, position, - dark, }, list: list.slice(0, 4), }; @@ -51,7 +49,7 @@ const customCode = `() => { lastName: 'Wheeler' }, ]; - return ; + return ; }`; export default { diff --git a/core/components/atoms/avatarGroup/__stories__/variants/CustomPopper.story.jsx b/core/components/atoms/avatarGroup/__stories__/variants/CustomPopover.story.jsx similarity index 91% rename from core/components/atoms/avatarGroup/__stories__/variants/CustomPopper.story.jsx rename to core/components/atoms/avatarGroup/__stories__/variants/CustomPopover.story.jsx index 5c1241fda4..2adbdcfb7a 100644 --- a/core/components/atoms/avatarGroup/__stories__/variants/CustomPopper.story.jsx +++ b/core/components/atoms/avatarGroup/__stories__/variants/CustomPopover.story.jsx @@ -3,7 +3,7 @@ import { AvatarGroup, Avatar, Text } from '@/index'; import { list } from '../AvatarList'; import './style.css'; -export const customPopper = () => { +export const customPopover = () => { const popperRenderer = (names) => { const AvatarList = names.map((avatar, index) => { const { firstName, lastName, appearance } = avatar; @@ -25,7 +25,7 @@ export const customPopper = () => { return
{AvatarList}
; }; - return ; + return ; }; const customCode = `/* @@ -95,13 +95,13 @@ const customCode = `/* return ( ); }`; export default { - title: 'Components/Avatar/AvatarGroup/Variants/Custom Popper', + title: 'Components/Avatar/AvatarGroup/Variants/Custom Popover', component: AvatarGroup, parameters: { docs: { diff --git a/core/components/atoms/avatarGroup/__stories__/variants/Trigger.story.jsx b/core/components/atoms/avatarGroup/__stories__/variants/Trigger.story.jsx new file mode 100644 index 0000000000..8e7c9efa0b --- /dev/null +++ b/core/components/atoms/avatarGroup/__stories__/variants/Trigger.story.jsx @@ -0,0 +1,72 @@ +import * as React from 'react'; +import { AvatarGroup, Text } from '@/index'; +import { list } from '../AvatarList'; + +export const Trigger = () => { + return ( +
+
+ Hover +
+ +
+
+
+ Click +
+ +
+
+
+ ); +}; + +const customCode = `() => { + const list = [ + { + firstName: 'John', + lastName: 'Doe', + }, + { + firstName: 'Steven', + lastName: 'Packton', + }, + { + firstName: 'Nancy', + lastName: 'Wheeler' + }, + { + firstName: 'Monica', + lastName: 'Geller' + }, + ]; + + return ( +
+
+ Hover +
+ +
+
+
+ Click +
+ +
+
+
+ ); +}`; + +export default { + title: 'Components/Avatar/AvatarGroup/Variants/Trigger', + component: AvatarGroup, + parameters: { + docs: { + docPage: { + customCode, + }, + }, + }, +}; diff --git a/core/components/atoms/avatarGroup/__tests__/AvatarGroup.test.tsx b/core/components/atoms/avatarGroup/__tests__/AvatarGroup.test.tsx index d810e5cc1a..6b50312eb8 100644 --- a/core/components/atoms/avatarGroup/__tests__/AvatarGroup.test.tsx +++ b/core/components/atoms/avatarGroup/__tests__/AvatarGroup.test.tsx @@ -127,6 +127,49 @@ describe('AvatarGroup component', () => { expect(avatar.textContent).toMatch(avatarsInitials[index]); }); }); + + it('renders popover list item with disabled state', () => { + const list = [ + { + firstName: 'John', + lastName: 'Doe', + }, + { + firstName: 'Steven', + lastName: 'Packton', + }, + { + firstName: 'Nancy', + lastName: 'Wheeler', + disabled: true, + }, + { + firstName: 'Monica', + lastName: 'Geller', + }, + { + firstName: 'Arya', + lastName: 'Stark', + }, + { + firstName: 'Rachel', + lastName: 'Green', + }, + ]; + + const { getByTestId, getAllByTestId } = render( + + ); + + expect(getByTestId('DesignSystem-AvatarGroup--TriggerAvatarVariants')).toHaveClass('cursor-pointer'); + + const extraAvatar = getByTestId('DesignSystem-AvatarGroup--TriggerAvatar'); + fireEvent.click(extraAvatar); + const listItem = getAllByTestId('DesignSystem-AvatarGroup--Item'); + + expect(listItem[0]).toHaveAttribute('disabled'); + expect(listItem[1]).not.toHaveAttribute('disabled'); + }); }); describe('AvatarGroup Component with overwrite class', () => { diff --git a/css/src/components/avatarGroup.css b/css/src/components/avatarGroup.css index 6fe068faf5..e34fdb4f12 100644 --- a/css/src/components/avatarGroup.css +++ b/css/src/components/avatarGroup.css @@ -14,11 +14,8 @@ } .AvatarGroup-Popper { - max-width: var(--spacing-9); - overflow: hidden; + overflow-y: auto; box-sizing: border-box; - word-break: break-word; - hyphens: auto; } .AvatarGroup-TextWrapper { diff --git a/docs/src/pages/components/avatarGroup/images/count-more-than-three.png b/docs/src/pages/components/avatarGroup/images/count-more-than-three.png index 210d96e619..a990466a32 100644 Binary files a/docs/src/pages/components/avatarGroup/images/count-more-than-three.png and b/docs/src/pages/components/avatarGroup/images/count-more-than-three.png differ diff --git a/docs/src/pages/components/avatarGroup/images/overflow-behavior.png b/docs/src/pages/components/avatarGroup/images/overflow-behavior.png index 41afea782b..10a96d117d 100644 Binary files a/docs/src/pages/components/avatarGroup/images/overflow-behavior.png and b/docs/src/pages/components/avatarGroup/images/overflow-behavior.png differ diff --git a/docs/src/pages/components/avatarGroup/images/sizes.png b/docs/src/pages/components/avatarGroup/images/sizes.png index 8e9c094606..63ecb2fe26 100644 Binary files a/docs/src/pages/components/avatarGroup/images/sizes.png and b/docs/src/pages/components/avatarGroup/images/sizes.png differ