Skip to content

Commit

Permalink
feat(fuselage): Avatar Emoji (#930)
Browse files Browse the repository at this point in the history
Co-authored-by: gabriellsh <gabriel.henriques@rocket.chat>
  • Loading branch information
yash-rajpal and gabriellsh authored Mar 13, 2023
1 parent 057b036 commit 8f9fae1
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 15 deletions.
8 changes: 7 additions & 1 deletion packages/fuselage/src/components/Avatar/Avatar.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { composeStories } from '@storybook/testing-react';
import { render } from '@testing-library/react';
import { render, screen } from '@testing-library/react';
import React from 'react';

import * as stories from './Avatar.stories';
Expand All @@ -10,4 +10,10 @@ describe('[Avatar Component]', () => {
it('renders without crashing', () => {
render(<Default />);
});

it('should render emoji avatar', () => {
render(<Default children='😄' />);

expect(screen.getAllByText('😄').length).toBeGreaterThanOrEqual(1);
});
});
44 changes: 40 additions & 4 deletions packages/fuselage/src/components/Avatar/Avatar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,19 @@ const sizes: (
| 'x332'
)[] = ['x16', 'x18', 'x28', 'x32', 'x36', 'x48', 'x124', 'x200', 'x332'];

const wrapChildren = (children: React.ReactNode, size: number) =>
children ? <div style={{ fontSize: `${size}px` }}>{children}</div> : null;

const Template: ComponentStory<typeof Avatar> = (args) => (
<Margins all='x16'>
{sizes.map((size, i) => (
<Box display='inline-flex' verticalAlign='middle' key={i}>
<Avatar url={args.url} size={size} rounded={args.rounded} />
<Avatar
url={args.url}
size={size}
rounded={args.rounded}
children={wrapChildren(args.children, Number(size.substring(1)))}
/>
</Box>
))}
</Margins>
Expand All @@ -47,14 +55,35 @@ Rounded.args = {
rounded: true,
};

export const Emoji = Template.bind({});
Emoji.args = {
children: '😀',
rounded: true,
};

const StackTemplate: ComponentStory<typeof Avatar> = (args) => (
<Margins all='x16'>
{sizes.map((size, i) => (
<Box key={i}>
<Avatar.Stack className={args.className}>
<Avatar url={args.url} size={size} rounded={args.rounded} />
<Avatar url={args.url} size={size} rounded={args.rounded} />
<Avatar url={args.url} size={size} rounded={args.rounded} />
<Avatar
url={args.url}
size={size}
rounded={args.rounded}
children={wrapChildren(args.children, Number(size.substring(1)))}
/>
<Avatar
url={args.url}
size={size}
rounded={args.rounded}
children={wrapChildren(args.children, Number(size.substring(1)))}
/>
<Avatar
url={args.url}
size={size}
rounded={args.rounded}
children={wrapChildren(args.children, Number(size.substring(1)))}
/>
</Avatar.Stack>
</Box>
))}
Expand All @@ -71,3 +100,10 @@ StackRounded.args = {
url: imgUrl,
rounded: true,
};

export const StackWithEmoji = StackTemplate.bind({});
StackWithEmoji.args = {
children: '😀',

rounded: true,
};
38 changes: 28 additions & 10 deletions packages/fuselage/src/components/Avatar/Avatar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { DetailedHTMLProps, HTMLAttributes } from 'react';
import type { DetailedHTMLProps, HTMLAttributes, ReactNode } from 'react';
import React from 'react';
import flattenChildren from 'react-keyed-flatten-children';

Expand All @@ -21,6 +21,9 @@ export type AvatarProps = {
rounded?: boolean;
objectFit?: boolean;
url: string;
children?: ReactNode;
image?: string;
emojiClassname?: string;
} & HTMLAttributes<HTMLElement>;

export const Avatar = ({
Expand All @@ -29,6 +32,9 @@ export const Avatar = ({
rounded = false,
objectFit = false,
url,
children,
image,
emojiClassname,
...props
}: AvatarProps) => {
props.className = prependClassName(
Expand All @@ -37,18 +43,30 @@ export const Avatar = ({
.filter(Boolean)
.join(' ')
);
const innerClass = [
'rcx-avatar__element',
objectFit && 'rcx-avatar__element--object-fit',
size && `rcx-avatar__element--${size}`,
rounded && 'rcx-avatar__element--rounded',
]
.filter(Boolean)
.join(' ');
const innerClass = prependClassName(
emojiClassname,
[
'rcx-avatar__element',
objectFit && 'rcx-avatar__element--object-fit',
size && `rcx-avatar__element--${size}`,
rounded && 'rcx-avatar__element--rounded',
]
.filter(Boolean)
.join(' ')
);

return (
<figure aria-label={title} {...props}>
<img src={`${url}`} className={`${innerClass}`} />
{children || image ? (
<span
className={`${innerClass}`}
style={image && image.length ? { backgroundImage: image } : undefined}
>
{children}
</span>
) : (
<img src={`${url}`} className={`${innerClass}`} />
)}
</figure>
);
};
Expand Down

0 comments on commit 8f9fae1

Please sign in to comment.