-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
AlphaAvatarGroup
component (#2177)
<!-- How to write a good PR title: - Follow [the Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/). - Give as much context as necessary and as little as possible - Prefix it with [WIP] while it’s a work in progress --> ## Self Checklist - [x] I wrote a PR title in **English** and added an appropriate **label** to the PR. - [x] I wrote the commit message in **English** and to follow [**the Conventional Commits specification**](https://www.conventionalcommits.org/en/v1.0.0/). - [x] I [added the **changeset**](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md) about the changes that needed to be released. (or didn't have to) - [x] I wrote or updated **documentation** related to the changes. (or didn't have to) - [x] I wrote or updated **tests** related to the changes. (or didn't have to) - [x] I tested the changes in various browsers. (or didn't have to) - Windows: Chrome, Edge, (Optional) Firefox - macOS: Chrome, Edge, Safari, (Optional) Firefox ## Related Issue <!-- Please link to issue if one exists --> <!-- Fixes #0000 --> - Fixes #2163 ## Summary <!-- Please brief explanation of the changes made --> - `AlphaAvatarGroup` 컴포넌트를 구현합니다. ## Details <!-- Please elaborate description of the changes --> - AvatarGroup 에서 새로운 디자인 토큰을 사용하고 있지 않아서 토큰을 갈아끼울 필요는 없었습니다. - 아바타 사이즈에 따라서 border 두께를 다르게 주도록 디자인이 변경된 부분이 있어서 AvatarGroup에서 사이즈를 컨텍스트를 내려주도록 했습니다. - 불필요하게 열어주는 속성을 제거했습니다. `ellipsisStyle`, `ellipsisClassName`, `onMouseEnterEllipsis`, `onMouseLeaveEllipsis`속성이 없어졌습니다. ### Breaking change? (Yes/No) <!-- If Yes, please describe the impact and migration path for users --> - No ## References <!-- Please list any other resources or points the reviewer should be aware of --> - [컴포넌트 스펙(internal)](https://www.notion.so/channelio/Avatar-Group-5fa6501554514acb816f3ff8ad0f7c91) - [피그마(internal)](https://www.figma.com/file/aJJF4bU82uR0jAsmWp5wlE/Navigation?type=design&node-id=1-19452&mode=dev)
- Loading branch information
1 parent
e82bc25
commit 61752bf
Showing
11 changed files
with
768 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@channel.io/bezier-react": patch | ||
--- | ||
|
||
Add `AlphaAvatarGroup` component |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 55 additions & 0 deletions
55
packages/bezier-react/src/components/AlphaAvatarGroup/AlphaAvatarGroup.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import React from 'react' | ||
|
||
import { type Meta, type StoryFn, type StoryObj } from '@storybook/react' | ||
|
||
import { AlphaAvatar } from '~/src/components/AlphaAvatar' | ||
|
||
import { AvatarGroup } from './AvatarGroup' | ||
import { type AvatarGroupProps } from './AvatarGroup.types' | ||
import MOCK_AVATAR_LIST from './__mocks__/avatarList' | ||
|
||
const meta: Meta<typeof AvatarGroup> = { | ||
component: AvatarGroup, | ||
argTypes: { | ||
max: { | ||
control: { | ||
type: 'range', | ||
min: 1, | ||
max: MOCK_AVATAR_LIST.length, | ||
step: 1, | ||
}, | ||
}, | ||
spacing: { | ||
control: { | ||
type: 'range', | ||
min: -50, | ||
max: 50, | ||
step: 1, | ||
}, | ||
}, | ||
}, | ||
} | ||
export default meta | ||
|
||
const Template: StoryFn<AvatarGroupProps> = (args) => ( | ||
<AvatarGroup {...args}> | ||
{MOCK_AVATAR_LIST.map(({ id, avatarUrl, name }) => ( | ||
<AlphaAvatar | ||
key={id} | ||
avatarUrl={avatarUrl} | ||
name={name} | ||
/> | ||
))} | ||
</AvatarGroup> | ||
) | ||
|
||
export const Primary: StoryObj<AvatarGroupProps> = { | ||
render: Template, | ||
|
||
args: { | ||
max: 5, | ||
ellipsisType: 'icon', | ||
size: '30', | ||
spacing: 4, | ||
}, | ||
} |
53 changes: 53 additions & 0 deletions
53
packages/bezier-react/src/components/AlphaAvatarGroup/AvatarGroup.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
@import '../AlphaAvatar/Avatar.module'; | ||
|
||
.AvatarGroup { | ||
--b-avatar-group-spacing: 0; | ||
--b-avatar-group-size: 0; | ||
|
||
position: relative; | ||
z-index: var(--z-index-base); | ||
display: flex; | ||
|
||
@each $size in $avatar-sizes { | ||
&:where(.size-#{$size}) { | ||
--b-avatar-group-size: #{$size}px; | ||
} | ||
} | ||
|
||
& > * + * { | ||
margin-left: var(--b-avatar-group-spacing); | ||
} | ||
} | ||
|
||
.AvatarEllipsisIconWrapper { | ||
position: relative; | ||
} | ||
|
||
.AvatarEllipsisIcon { | ||
position: absolute; | ||
z-index: var(--z-index-floating); | ||
top: 0; | ||
right: 0; | ||
|
||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
|
||
width: 100%; | ||
height: 100%; | ||
|
||
outline: none; | ||
} | ||
|
||
.AvatarEllipsisCountWrapper { | ||
--b-avatar-group-ellipsis-ml: 0; | ||
|
||
margin-left: var(--b-avatar-group-ellipsis-ml); | ||
} | ||
|
||
.AvatarEllipsisCount { | ||
position: relative; | ||
display: flex; | ||
align-items: center; | ||
height: var(--b-avatar-group-size); | ||
} |
93 changes: 93 additions & 0 deletions
93
packages/bezier-react/src/components/AlphaAvatarGroup/AvatarGroup.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import React from 'react' | ||
|
||
import { render } from '~/src/utils/test' | ||
|
||
import { Avatar } from '~/src/components/Avatar' | ||
|
||
import { AVATAR_GROUP_ELLIPSIS_ICON_TEST_ID, AvatarGroup } from './AvatarGroup' | ||
import { type AvatarGroupProps } from './AvatarGroup.types' | ||
import MOCK_AVATAR_LIST from './__mocks__/avatarList' | ||
|
||
describe('AvatarGroup', () => { | ||
let props: AvatarGroupProps | ||
const mockFallbackUrl = 'https://www.google.com' | ||
|
||
beforeEach(() => { | ||
props = { | ||
max: MOCK_AVATAR_LIST.length - 1, | ||
spacing: 4, | ||
ellipsisType: 'icon', | ||
} | ||
}) | ||
|
||
afterAll(() => { | ||
jest.restoreAllMocks() | ||
}) | ||
|
||
const renderComponent = (otherProps?: AvatarGroupProps) => | ||
render( | ||
<AvatarGroup | ||
{...props} | ||
{...otherProps} | ||
> | ||
{MOCK_AVATAR_LIST.map(({ id, avatarUrl, name }) => ( | ||
<Avatar | ||
key={id} | ||
avatarUrl={avatarUrl} | ||
fallbackUrl={mockFallbackUrl} | ||
name={name} | ||
/> | ||
))} | ||
</AvatarGroup> | ||
) | ||
|
||
describe('Ellipsis type - Icon', () => { | ||
beforeEach(() => { | ||
props.ellipsisType = 'icon' | ||
}) | ||
|
||
it('Snapshot', () => { | ||
const { getByRole } = renderComponent() | ||
const rendered = getByRole('group') | ||
expect(rendered).toMatchSnapshot() | ||
}) | ||
|
||
it('should render ellipsis icon when avatar count is more than max', () => { | ||
const { getByTestId } = renderComponent() | ||
const rendered = getByTestId(AVATAR_GROUP_ELLIPSIS_ICON_TEST_ID) | ||
expect(rendered).toBeInTheDocument() | ||
}) | ||
|
||
it('should not render ellipsis icon when avatar count is less than max', () => { | ||
props.max = MOCK_AVATAR_LIST.length | ||
const { queryByTestId } = renderComponent() | ||
const rendered = queryByTestId(AVATAR_GROUP_ELLIPSIS_ICON_TEST_ID) | ||
expect(rendered).not.toBeInTheDocument() | ||
}) | ||
}) | ||
|
||
describe('Ellipsis type - Count', () => { | ||
beforeEach(() => { | ||
props.ellipsisType = 'count' | ||
}) | ||
|
||
it('Snapshot', () => { | ||
const { getByRole } = renderComponent() | ||
const rendered = getByRole('group') | ||
expect(rendered).toMatchSnapshot() | ||
}) | ||
|
||
it('should render ellipsis count when avatar count is more than max', () => { | ||
const { getByText } = renderComponent() | ||
const rendered = getByText('+1') | ||
expect(rendered).toBeInTheDocument() | ||
}) | ||
|
||
it('should not render ellipsis count when avatar count is less than max', () => { | ||
props.max = MOCK_AVATAR_LIST.length | ||
const { queryByText } = renderComponent() | ||
const rendered = queryByText('+1') | ||
expect(rendered).not.toBeInTheDocument() | ||
}) | ||
}) | ||
}) |
Oops, something went wrong.