Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(avatarGroup): introduce #5916

Merged
merged 33 commits into from
Oct 14, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
b715483
feat(avatarGroup): introduce
AugustinMauroy Sep 29, 2023
49c6a31
update
AugustinMauroy Sep 29, 2023
19b888c
feat(avatarGroup): update base on feedback
AugustinMauroy Sep 30, 2023
7673f18
update
AugustinMauroy Oct 1, 2023
37f7a5e
Merge remote-tracking branch 'upstream/main' into feat(authors)
AugustinMauroy Oct 2, 2023
2d581af
re-add package
AugustinMauroy Oct 2, 2023
55457f8
update
AugustinMauroy Oct 3, 2023
0f3e306
update
AugustinMauroy Oct 4, 2023
b3bf1ed
update
AugustinMauroy Oct 8, 2023
de3ee52
feat(avatarGroupe): update with feedBack
AugustinMauroy Oct 11, 2023
340147c
fix: indentation
AugustinMauroy Oct 11, 2023
c61cbf9
remove `'use client';`
AugustinMauroy Oct 11, 2023
0e2e396
feat(utils): separate "avatar"
AugustinMauroy Oct 11, 2023
c764b26
feat(avatarGroup): introduce
AugustinMauroy Sep 29, 2023
4200176
update
AugustinMauroy Sep 29, 2023
b91d26a
feat(avatarGroup): update base on feedback
AugustinMauroy Sep 30, 2023
081cf42
update
AugustinMauroy Oct 1, 2023
fd75eee
re-add package
AugustinMauroy Oct 2, 2023
bf33b6b
update
AugustinMauroy Oct 3, 2023
477c0c3
update
AugustinMauroy Oct 4, 2023
423b208
update
AugustinMauroy Oct 8, 2023
86578f1
feat(avatarGroupe): update with feedBack
AugustinMauroy Oct 11, 2023
ceac69a
fix: indentation
AugustinMauroy Oct 11, 2023
4918f85
remove `'use client';`
AugustinMauroy Oct 11, 2023
af292d1
feat(utils): separate "avatar"
AugustinMauroy Oct 11, 2023
279ba4b
review: expedited code-review changes
ovflowd Oct 11, 2023
38144d0
test(avatarGroup): add
AugustinMauroy Oct 14, 2023
e8295b7
Merge branch 'feat(authors)' of https://github.com/AugustinMauroy/nod…
AugustinMauroy Oct 14, 2023
d71f145
review: expedited code-review changes
ovflowd Oct 11, 2023
4c98b35
remove: removed files with wrong casing
ovflowd Oct 14, 2023
db86f0e
chore: renamed utils
ovflowd Oct 14, 2023
a2edfec
chore: fix linting order
ovflowd Oct 14, 2023
d8233d9
chore: fix tests
ovflowd Oct 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions components/Common/AvatarGroup/avatar/index.module.css
AugustinMauroy marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.avatar {
@apply -ml-2 rounded-full border-2 border-white bg-neutral-100 first:ml-0 dark:border-neutral-950 dark:bg-neutral-800;
AugustinMauroy marked this conversation as resolved.
Show resolved Hide resolved
}
19 changes: 19 additions & 0 deletions components/Common/AvatarGroup/avatar/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { userNameToAvatarUrl } from '@/util/github';
import Avatar from './';
import type { Meta as MetaObj, StoryObj } from '@storybook/react';
AugustinMauroy marked this conversation as resolved.
Show resolved Hide resolved

type Story = StoryObj<typeof Avatar>;
type Meta = MetaObj<typeof Avatar>;
export const Default: Story = {
AugustinMauroy marked this conversation as resolved.
Show resolved Hide resolved
args: {
src: userNameToAvatarUrl('AugustinMauroy'),
},
};

export const Failed: Story = {
AugustinMauroy marked this conversation as resolved.
Show resolved Hide resolved
args: {
src: 'https://avatars.githubusercontent.com/u/fake-user-id',
},
};

export default { component: Avatar } as Meta;
25 changes: 25 additions & 0 deletions components/Common/AvatarGroup/avatar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useState } from 'react';
import Image from 'next/image';
import styles from './index.module.css';
import type { FC } from 'react';

type AvatarProps = {
src: string;
};

const Avatar: FC<AvatarProps> = ({ src }) => {
const [url, setUrl] = useState(src);

return (
<Image
AugustinMauroy marked this conversation as resolved.
Show resolved Hide resolved
className={styles.avatar}
src={url}
width={32}
height={32}
alt="avatar"
onError={() => setUrl('/static/images/avatar-placeholder.svg')}
/>
);
};

export default Avatar;
7 changes: 7 additions & 0 deletions components/Common/AvatarGroup/index.module.css
AugustinMauroy marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.avatarGroup {
@apply flex items-center overflow-x-auto;
AugustinMauroy marked this conversation as resolved.
Show resolved Hide resolved

.showMore {
@apply flex h-8 w-8 items-center justify-center rounded-full border-2 border-white bg-neutral-100 text-sm dark:border-neutral-950 dark:bg-neutral-900;
}
}
61 changes: 61 additions & 0 deletions components/Common/AvatarGroup/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { userNameToAvatarUrl } from '@/util/github';
import AvatarGroup from './';
import type { Meta as MetaObj, StoryObj } from '@storybook/react';

type Story = StoryObj<typeof AvatarGroup>;
type Meta = MetaObj<typeof AvatarGroup>;

const AvatarList = {
AugustinMauroy marked this conversation as resolved.
Show resolved Hide resolved
avatars: [
userNameToAvatarUrl('ovflowd'),
userNameToAvatarUrl('bmuenzenmeyer'),
userNameToAvatarUrl('AugustinMauroy'),
userNameToAvatarUrl('HinataKah0'),
userNameToAvatarUrl('Harkunwar'),
userNameToAvatarUrl('rodion-arr'),
userNameToAvatarUrl('mikeesto'),
userNameToAvatarUrl('bnb'),
userNameToAvatarUrl('benhalverson'),
userNameToAvatarUrl('aymen94'),
userNameToAvatarUrl('shanpriyan'),
userNameToAvatarUrl('Wai-Dung'),
userNameToAvatarUrl('manishprivet'),
userNameToAvatarUrl('araujogui'),
],
};

export const Default: Story = {
args: {
AugustinMauroy marked this conversation as resolved.
Show resolved Hide resolved
...AvatarList,
},
};

export const WithCustomLimit: Story = {
args: {
...AvatarList,
limit: 5,
},
};

export const InSmallContainer: Story = {
decorators: [
Story => (
<div style={{ width: '150px' }}>
<Story />
</div>
),
],
args: {
...AvatarList,
limit: 5,
},
};

export const WithForceShow: Story = {
args: {
...AvatarList,
forceShow: true,
},
};

export default { component: AvatarGroup } as Meta;
41 changes: 41 additions & 0 deletions components/Common/AvatarGroup/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'use client';
AugustinMauroy marked this conversation as resolved.
Show resolved Hide resolved
import { useState } from 'react';
import styles from './index.module.css';
import type { FC } from 'react';
import Avatar from './avatar';

type AvatarGroupProps = {
avatars: string[];
limit?: number;
forceShow?: boolean;
};

const AvatarGroup: FC<AvatarGroupProps> = ({
limit = 10,
avatars,
forceShow,
}) => {
const [showMore, setShowMore] = useState(forceShow?.valueOf() || false);
AugustinMauroy marked this conversation as resolved.
Show resolved Hide resolved

const handleShowMoreClick = () => {
if (forceShow) return;
AugustinMauroy marked this conversation as resolved.
Show resolved Hide resolved
setShowMore(true);
};

return (
<div className={styles.avatarGroup}>
{showMore
? avatars.map((avatar, index) => <Avatar key={index} src={avatar} />)
AugustinMauroy marked this conversation as resolved.
Show resolved Hide resolved
: avatars
.slice(0, limit)
.map((avatar, index) => <Avatar key={index} src={avatar} />)}
{avatars.length > limit && !showMore && (
<span className={styles.showMore} onClick={() => handleShowMoreClick()}>
AugustinMauroy marked this conversation as resolved.
Show resolved Hide resolved
+{avatars.length - limit}
</span>
)}
</div>
);
};

export default AvatarGroup;
13 changes: 13 additions & 0 deletions public/static/images/avatar-placeholder.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions util/__tests__/github.test.ts
AugustinMauroy marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { userNameToAvatarUrl } from '@/util/github';

describe('userNameToAvatarUrl', () => {
it('returns the correct URL', () => {
expect(userNameToAvatarUrl('octocat')).toBe(
'https://avatars.githubusercontent.com/octocat'
);
});
});
3 changes: 3 additions & 0 deletions util/github.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const userNameToAvatarUrl = (userName: string): string => {
AugustinMauroy marked this conversation as resolved.
Show resolved Hide resolved
return `https://avatars.githubusercontent.com/${userName}`;
};
Loading