Skip to content

Commit

Permalink
feature(component): Rewrite Avatar to use themes, resolves themesbe…
Browse files Browse the repository at this point in the history
  • Loading branch information
tulup-conner committed May 24, 2022
1 parent 0b897b5 commit 5055c82
Showing 1 changed file with 35 additions and 60 deletions.
95 changes: 35 additions & 60 deletions src/lib/components/Avatar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,97 +1,72 @@
import classNames from 'classnames';
import { FC, PropsWithChildren } from 'react';
import { ComponentProps, FC, PropsWithChildren } from 'react';
import { FlowbiteSizes } from '../Flowbite/FlowbiteTheme';
import { useTheme } from '../Flowbite/ThemeContext';
import AvatarGroup from './AvatarGroup';
import AvatarGroupCounter from './AvatarGroupCounter';

export type AvatarProps = PropsWithChildren<{
export interface AvatarProps extends PropsWithChildren<ComponentProps<'div'>> {
alt?: string;
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
rounded?: boolean;
bordered?: boolean;
img?: string;
status?: 'offline' | 'online' | 'away' | 'busy';
statusPosition?: 'top-left' | 'top-right' | 'bottom-right' | 'bottom-left';
rounded?: boolean;
size?: keyof FlowbiteSizes;
stacked?: boolean;
}>;

const sizeClasses: Record<AvatarProps['size'] & string, string> = {
xs: 'w-6 h-6',
sm: 'w-8 h-8',
md: 'w-10 h-10',
lg: 'w-20 h-20',
xl: 'w-36 h-36',
};

const statusClasses: Record<AvatarProps['status'] & string, string> = {
offline: 'bg-gray-400',
online: 'bg-green-400',
away: 'bg-yellow-400',
busy: 'bg-red-400',
};

const statusPositionClasses: Record<AvatarProps['statusPosition'] & string, string> = {
'top-right': '-top-1 -right-1',
'top-left': '-top-1 -left-1',
'bottom-left': '-bottom-1 -left-1',
'bottom-right': '-bottom-1 -right-1',
};
status?: 'away' | 'busy' | 'offline' | 'online';
statusPosition?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';
}

const AvatarComponent: FC<AvatarProps> = ({
alt = '',
img,
status,
bordered = false,
children,
statusPosition = 'top-left',
size = 'md',
img,
rounded = false,
bordered = false,
size = 'md',
stacked = false,
status,
statusPosition = 'top-left',
...props
}) => {
const theme = useTheme().theme.avatar;

return (
<div data-testid="avatar-element" className="flex items-center space-x-4">
<div className={theme.base} data-testid="avatar-element" {...props}>
<div className="relative">
{img ? (
<img
className={classNames(sizeClasses[size], {
rounded: !rounded,
'rounded-full': rounded,
'ring-2 ring-gray-300 dark:ring-gray-500': bordered || stacked,
'p-1': bordered,
})}
src={img}
alt={alt}
className={classNames(
bordered && theme.bordered,
rounded && theme.rounded,
stacked && theme.stacked,
theme.img.enabled,
theme.size[size],
)}
src={img}
/>
) : (
<div
className={classNames(`relative overflow-hidden bg-gray-100 dark:bg-gray-600`, sizeClasses[size], {
rounded: !rounded,
'rounded-full': rounded,
'ring-2 ring-gray-300 dark:ring-gray-500': bordered || stacked,
'p-1': bordered,
})}
className={classNames(
bordered && theme.bordered,
rounded && theme.rounded,
stacked && theme.stacked,
theme.img.disabled,
theme.size[size],
)}
>
<svg
className="absolute -bottom-1 h-auto w-auto text-gray-400"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z"
clipRule="evenodd"
></path>
<path fillRule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z" clipRule="evenodd" />
</svg>
</div>
)}
{status && (
<span
className={classNames(
'absolute h-3.5 w-3.5 rounded-full border-2 border-white dark:border-gray-800',
statusClasses[status],
statusPositionClasses[statusPosition],
)}
></span>
<span className={classNames(theme.status.base, theme.status[status], theme.statusPosition[statusPosition])} />
)}
</div>
{children && <div>{children}</div>}
Expand Down

0 comments on commit 5055c82

Please sign in to comment.