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/Avatar] add Avatar demo component #27

Merged
merged 3 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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.