Skip to content

Commit

Permalink
[Feat/Avatar] add Avatar demo component (#27)
Browse files Browse the repository at this point in the history
* add dependendy
@radix-ui/react-avatar

* add default avatar component

* add avatar demo component
  • Loading branch information
leezer94 authored Jul 26, 2023
1 parent 0e0cecb commit b1802cb
Show file tree
Hide file tree
Showing 11 changed files with 234 additions and 6 deletions.
98 changes: 98 additions & 0 deletions apps/web/components/examples/avatar/demo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui';
import { TypographyH4 } from '@/components/ui/typography';
import { cn } from '@/lib';
import { useCallback, useState } from 'react';

const SAMPLE_AVATAR = [
{
src: 'https://images.unsplash.com/photo-1511485977113-f34c92461ad9?ixlib=rb-1.2.1&w=128&h=128&dpr=2&q=80',
alt: 'sample-avatar1',
fallback: 'sample',
size: 'default',
description: 'Default',
},
{
src: 'https://images.unsplash.com/photo-1634926878768-2a5b3c42f139?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1356&q=80',
alt: 'sample-avatar2',
fallback: 'sample',
size: 'lg',
description: 'Large',
},
];

const FALLBACK_AVATAR = [
{
src: '',
alt: 'sample-avatar1/fallback',
fallback: 'FB',
size: 'default',
description: 'Default',
},
{
src: '',
alt: 'sample-avatar2/fallback',
fallback: 'FB',
size: 'lg',
description: 'Large',
},
];

export default function AvatarDemo() {
const [isHovered, setIsHovered] = useState(false);

const handleIsHovered = useCallback(
(hover: boolean) => setIsHovered(hover),
[]
);
// 호버 상태면 fallback
// 호버가 아닐땐 avatar

return (
<div className='flex items-center justify-center gap-10'>
{!isHovered &&
SAMPLE_AVATAR.map(({ src, alt, fallback, size, description }, idx) => (
<div
key={`${alt}/${idx}`}
className='flex h-[180px] w-[90px] flex-col items-center justify-start gap-y-2 font-bold'
>
<TypographyH4 className='flex-1 font-light text-foreground/60'>
{description}
</TypographyH4>
<div className={cn('flex flex-1 items-center')}>
<Avatar
onMouseEnter={() => handleIsHovered(true)}
onMouseLeave={() => handleIsHovered(false)}
size={size as 'default' | 'lg'}
>
<AvatarImage src={src} alt={alt} />
<AvatarFallback>{fallback}</AvatarFallback>
</Avatar>
</div>
</div>
))}
{isHovered &&
FALLBACK_AVATAR.map(
({ src, alt, fallback, size, description }, idx) => (
<div
key={`${alt}/${idx}`}
className='flex h-[180px] w-[90px] flex-col items-center justify-start gap-y-2 font-bold'
>
<TypographyH4 className='flex-1 font-light text-foreground/60'>
{description}
</TypographyH4>
<div className={cn('flex flex-1 items-center')}>
<Avatar
onMouseEnter={() => handleIsHovered(true)}
onMouseLeave={() => handleIsHovered(false)}
size={size as 'default' | 'lg'}
>
<AvatarImage src={src} alt={alt} />
<AvatarFallback>{fallback}</AvatarFallback>
</Avatar>
</div>
</div>
)
)}
</div>
);
}
6 changes: 3 additions & 3 deletions apps/web/components/examples/carousel/demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ export default function CarouselDemo() {
orientation='horizontal'
autoplay={autoplay}
>
<CarouselItem>
<IssueTemplateCard />
</CarouselItem>
{/* <CarouselItem> */}
<IssueTemplateCard />
{/* </CarouselItem> */}
<AppleTemplateCard />
{CAROUSEL_IMAGES.map((url, idx) => (
<div
Expand Down
2 changes: 2 additions & 0 deletions apps/web/components/examples/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import AvatarDemo from '@/components/examples/avatar/demo';
import AccordionDemo from './accordion/demo';
import ButtonDemo from './button/demo';
import CardDemo from './card/demo';
Expand All @@ -8,4 +9,5 @@ export const examples = {
ButtonDemo,
CardDemo,
CarouselDemo,
AvatarDemo,
};
67 changes: 67 additions & 0 deletions apps/web/components/ui/avatar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use client';

import React from 'react';
import * as AvatarPrimitive from '@radix-ui/react-avatar';
import { cn } from '@/lib/utils';

interface AvatarSize {
size: 'default' | 'lg';
}

const Avatar = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root> & AvatarSize
>(({ className, children, size, ...props }, ref) => {
return (
<AvatarPrimitive.Root
ref={ref}
className={cn(
'rounded-full border-orange-500 border-2 flex justify-center items-center select-none align-middle overflow-hidden bg-blackA3',
`h-[${size === 'default' ? 45 : 90}px] w-[${
size === 'default' ? 45 : 90
}px]`,
className
)}
{...props}
>
{children}
</AvatarPrimitive.Root>
);
});

Avatar.displayName = AvatarPrimitive.Root.displayName;

const AvatarImage = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Image>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
>(({ className, onLoadingStatusChange, ...props }, ref) => (
<AvatarPrimitive.Image
ref={ref}
onLoadingStatusChange={onLoadingStatusChange}
className={cn('h-full w-full rounded-[inherit] object-cover', className)}
{...props}
/>
));

AvatarImage.displayName = AvatarPrimitive.Image.displayName;

const AvatarFallback = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Fallback>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
>(({ className, delayMs, children, ...props }, ref) => (
<AvatarPrimitive.Fallback
ref={ref}
className={cn(
'flex items-center justify-center w-full h-full font-medium text-lg text-foreground/80 border-2 rounded-[inherit] bg-white',
className
)}
delayMs={delayMs}
{...props}
>
{children}
</AvatarPrimitive.Fallback>
));

AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;

export { Avatar, AvatarImage, AvatarFallback };
4 changes: 3 additions & 1 deletion apps/web/components/ui/carousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ const Carousel = React.forwardRef<
aria-label='prev-button'
/>
)}
{elements[currentIndex]}
{/* children elements */}
<div className='h-full '>{elements[currentIndex]}</div>
{/* */}
<div className='top-4 flex justify-center py-2'>
{elements.map((_, idx) => (
<div
Expand Down
1 change: 1 addition & 0 deletions apps/web/components/ui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from './scroll-area';
export * from './select';
export * from './separator';
export * from './carousel';
export * from './avatar';
15 changes: 13 additions & 2 deletions apps/web/components/ui/typography.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,20 @@ export function TypographyH3({
);
}

export function TypographyH4({ children }: { children: Typography }) {
export function TypographyH4({
className,
children,
}: {
className: string;
children: Typography;
}) {
return (
<h4 className='scroll-m-20 text-xl font-semibold tracking-tight'>
<h4
className={cn(
'scroll-m-20 text-xl font-semibold tracking-tight',
className
)}
>
{children}
</h4>
);
Expand Down
5 changes: 5 additions & 0 deletions apps/web/config/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ export const DOCS_CONFIG: DocsConfig = {
href: '/docs/components/carousel',
items: [],
},
{
title: '아바타',
href: '/docs/components/avatar',
items: [],
},
],
},
{
Expand Down
14 changes: 14 additions & 0 deletions apps/web/content/docs/components/avatar.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title: Avatar
description: 이미지 fallback 을 포함하는 유저를 나타낼 수 있는 아바타 컴포넌트
component: true
radix:
link: https://www.radix-ui.com/docs/primitives/components/avatar
api: https://www.radix-ui.com/docs/primitives/components/avatar#api-reference
---

<ComponentExample src='/components/examples/avatar/demo.tsx'>
<div className='max-w-[70%] w-full'>
<AvatarDemo />
</div>
</ComponentExample>
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"dependencies": {
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-aspect-ratio": "^1.0.3",
"@radix-ui/react-avatar": "^1.0.3",
"@radix-ui/react-collapsible": "^1.0.3",
"@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-dropdown-menu": "^2.0.5",
Expand Down
27 changes: 27 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit b1802cb

Please sign in to comment.