Skip to content

Commit

Permalink
feat: 스켈레톤 컴포넌트 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
gxxrxn committed Jan 18, 2024
1 parent dfc0ec0 commit 42fdffb
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 0 deletions.
60 changes: 60 additions & 0 deletions src/stories/base/skeleton/Skeleton.Circle.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Meta, StoryObj } from '@storybook/react';
import Skeleton from '@/v1/base/Skeleton';

const meta: Meta<typeof Skeleton> = {
title: 'Base/Skeleton',
component: Skeleton,
};

export default meta;

type CircleStory = StoryObj<typeof Skeleton.Circle>;
type TextStory = StoryObj<typeof Skeleton.Text>;
type RectStory = StoryObj<typeof Skeleton.Rect>;

const basicSizes = ['small', 'medium', 'large'];

export const Circle: CircleStory = {
args: { size: 'small' },
argTypes: {
size: {
options: [...basicSizes],
control: { type: 'radio' },
},
},
render: args => (
<Skeleton>
<Skeleton.Circle {...args} />
</Skeleton>
),
};

export const Text: TextStory = {
args: { fontSize: 'small', width: '50%' },
argTypes: {
fontSize: {
options: ['2xsmall', 'xsmall', ...basicSizes, 'xlarge', '2xlarge'],
control: { type: 'radio' },
},
},
render: args => (
<Skeleton>
<Skeleton.Text {...args} />
</Skeleton>
),
};

export const Rectangle: RectStory = {
args: { width: '10rem', height: '12.3rem' },
argTypes: {
rounded: {
options: [...basicSizes, 'full'],
control: { type: 'radio' },
},
},
render: args => (
<Skeleton>
<Skeleton.Rect {...args} />
</Skeleton>
),
};
104 changes: 104 additions & 0 deletions src/v1/base/Skeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { ReactNode } from 'react';

const Skeleton = ({ children }: { children?: ReactNode }) => {
return <div className="animate-pulse">{children}</div>;
};

type Size = 'small' | 'medium' | 'large';
type XSize = 'xsmall' | 'xlarge';
type XXSize = '2xsmall' | '2xlarge';
type FullSize = 'full';

/** Circle Skeleton */
type CircleSize = Size;

const getCircleSize = (size: CircleSize) => {
switch (size) {
case 'large':
return 'w-[7rem] h-[7rem]';
case 'medium':
return 'w-[3.2rem] h-[3.2rem]';
case 'small':
default:
return 'w-[2rem] h-[2rem]';
}
};

const Circle = ({ size = 'small' }: { size?: CircleSize }) => {
const sizeClasses = getCircleSize(size);
return <div className={`rounded-full bg-black-400 ${sizeClasses}`} />;
};

/** Text Skeleton */
type FontSize = Size | XSize | XXSize;

const getTextHeight = (size?: FontSize) => {
switch (size) {
case '2xsmall':
return 'h-[1rem]';
case 'xsmall':
return 'h-[1.2rem]';
case 'small':
return 'h-[1.4rem]';
case 'medium':
return 'h-[1.6rem]';
case 'large':
return 'h-[1.8rem]';
case 'xlarge':
return 'h-[2rem]';
case '2xlarge':
return 'h-[2.2rem]';
default:
return 'h-[1.2rem]'; // small
}
};

const Text = ({
width,
fontSize = 'small',
}: {
width?: string;
fontSize?: FontSize;
}) => {
const heightClasses = getTextHeight(fontSize);
return <div className={`bg-black-400 ${heightClasses}`} style={{ width }} />;
};

/** Rectangle Skelton */
type RoundedSize = Size | FullSize;

const getRoundedSize = (size?: RoundedSize) => {
switch (size) {
case 'small':
return 'rounded-[0.2rem]';
case 'medium':
return 'rounded-[0.5rem]';
case 'large':
return 'rounded-[2rem]';
case 'full':
return 'rounded-full';
default:
return 'rounded-none';
}
};

const Rect = ({
width,
height,
rounded,
}: {
width?: string;
height?: string;
rounded?: RoundedSize;
}) => {
const roundedClass = getRoundedSize(rounded);
return (
<div className={`bg-black-400 ${roundedClass}`} style={{ width, height }} />
);
};

Skeleton.Circle = Circle;
Skeleton.Text = Text;
Skeleton.Rect = Rect;

export default Skeleton;

0 comments on commit 42fdffb

Please sign in to comment.