Skip to content

Commit

Permalink
fix(input): enhance storybook input examples with additional props an…
Browse files Browse the repository at this point in the history
…d ref handling
  • Loading branch information
froggy1014 committed Nov 20, 2024
2 parents b0ba26b + 2ae6bd3 commit f59d871
Show file tree
Hide file tree
Showing 14 changed files with 376 additions and 0 deletions.
16 changes: 16 additions & 0 deletions packages/skeleton/.storybook/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { StorybookConfig } from '@storybook/react-vite';

export default {
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
addons: [
'@storybook/addon-onboarding',
'@storybook/addon-links',
'@storybook/addon-essentials',
'@chromatic-com/storybook',
'@storybook/addon-interactions',
],
framework: {
name: '@storybook/react-vite',
options: {},
},
} satisfies StorybookConfig;
5 changes: 5 additions & 0 deletions packages/skeleton/.storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { Preview } from '@storybook/react';

export default {
tags: ['autodocs'],
} satisfies Preview;
66 changes: 66 additions & 0 deletions packages/skeleton/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{
"name": "@sipe-team/skeleton",
"description": "Skeleton component for Sipe Design System",
"version": "0.0.0",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/sipe-team/3-1_sds"
},
"type": "module",
"exports": "./src/index.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsup",
"build:storybook": "storybook build",
"dev:storybook": "storybook dev -p 6006",
"lint": "biome lint .",
"test": "vitest",
"typecheck": "tsc",
"prepack": "pnpm run build"
},
"devDependencies": {
"@biomejs/biome": "catalog:",
"@faker-js/faker": "^9.2.0",
"@storybook/addon-essentials": "catalog:",
"@storybook/addon-interactions": "catalog:",
"@storybook/addon-links": "catalog:",
"@storybook/blocks": "catalog:",
"@storybook/react": "catalog:",
"@storybook/react-vite": "catalog:",
"@storybook/test": "catalog:",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.0.1",
"@types/react": "^18.3.12",
"happy-dom": "catalog:",
"react": "^18.3.1",
"storybook": "catalog:",
"tsup": "catalog:",
"typescript": "catalog:",
"vitest": "catalog:"
},
"peerDependencies": {
"react": ">= 18"
},
"publishConfig": {
"access": "public",
"exports": {
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
}
}
},
"sideEffects": false,
"dependencies": {
"@radix-ui/react-slot": "^1.1.0"
}
}
30 changes: 30 additions & 0 deletions packages/skeleton/src/Skeleton.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
@keyframes fadeInOut {
0% {
opacity: 1;
}
50% {
opacity: 0.8;
}
100% {
opacity: 1;
}
}


.skeleton{
animation: fadeInOut 1.5s infinite !important;
width: var(--width);
height: var(--height);
background-color: rgb(155, 155, 155);

background-image: none !important;
background-clip: border-box !important;
border: none !important;
box-shadow: none !important;
box-decoration-break: clone !important;
color: transparent !important;
outline: none !important;
pointer-events: none !important;
user-select: none !important;
cursor: default !important;
}
78 changes: 78 additions & 0 deletions packages/skeleton/src/Skeleton.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { faker } from '@faker-js/faker';
// Skeleton.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Skeleton } from './Skeleton';

const meta = {
component: Skeleton,
parameters: {
layout: 'centered',
},
argTypes: {
variant: {
control: 'select',
options: ['circle', 'rectangular'],
},
width: {
control: { type: 'number', min: 20, max: 200, step: 10 },
},
height: {
control: { type: 'number', min: 20, max: 200, step: 10 },
},
loading: {
control: 'boolean',
},
asChild: {
control: 'boolean',
},
},
} satisfies Meta<typeof Skeleton>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Basic: Story = {
args: {
loading: true,
variant: 'rectangular',
width: 100,
height: 100,
},
};

export const CircleSkeleton: Story = {
args: {
loading: true,
variant: 'circle',
width: 80,
height: 80,
},
};

export const RectangularSkeleton: Story = {
args: {
loading: true,
variant: 'rectangular',
width: 80,
height: 30,
},
};

export const SkeletonWithChildren: Story = {
args: {
loading: true,
asChild: true,
children: <button type="button">Loading...</button>,
variant: 'rectangular',
},
};

export const SkeletonWithText: Story = {
args: {
loading: true,
asChild: true,
children: <span>{faker.lorem.lines(2)}</span>,
variant: 'rectangular',
},
};
55 changes: 55 additions & 0 deletions packages/skeleton/src/Skeleton.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { render, screen } from '@testing-library/react';
import { expect, test } from 'vitest';
import { Skeleton } from './Skeleton';

test('loading이 true 일 때 스켈레톤이 렌더링 된다.', () => {
render(<Skeleton loading={true} aria-label="skeleton" />);

const skeleton = screen.getByLabelText('skeleton');
expect(skeleton).toBeInTheDocument();
});

test('loading이 false 일 때 children이 렌더링 된다.', () => {
render(<Skeleton loading={false}>Childrun</Skeleton>);

expect(screen.getByText('Childrun')).toBeInTheDocument();
});

test('variant가 circle일 때 borderRadius가 50%로 설정된다.', () => {
render(<Skeleton loading={true} variant="circle" aria-label="skeleton" />);

const skeleton = screen.getByLabelText('skeleton');
expect(skeleton).toHaveStyle({ borderRadius: '50%' });
});
test('variant가 rectangular일 때 borderRadius가 기본값 4px으로 설정된다.', () => {
render(
<Skeleton loading={true} variant="rectangular" aria-label="skeleton" />,
);

const skeleton = screen.getByLabelText('skeleton');
expect(skeleton).toHaveStyle({ borderRadius: '4px' });
});
test('width와 height가 props로 전달될 때 올바르게 스타일이 적용된다.', () => {
render(
<Skeleton loading={true} width={150} height={50} aria-label="skeleton" />,
);

const skeleton = screen.getByLabelText('skeleton');
expect(skeleton).toHaveStyle({ width: '150px', height: '50px' });
});

test('asChild가 true일 때, children으로 전달된 요소에 Skeleton 스타일을 적용한다.', () => {
render(
<Skeleton asChild loading={true} width={120} height={30}>
<span data-testid="child">Child Content</span>
</Skeleton>,
);

const child = screen.getByTestId('child');
expect(child).toBeInTheDocument();
expect(child).toHaveStyle({
'background-color': 'rgb(155, 155, 155)',
width: '120px',
height: '30px',
});
});
39 changes: 39 additions & 0 deletions packages/skeleton/src/Skeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Slot } from '@radix-ui/react-slot';
import {
type CSSProperties,
type ComponentProps,
type ForwardedRef,
forwardRef,
} from 'react';
import styles from './Skeleton.module.css';

type Variant = 'circle' | 'rectangular';

interface SkeletonProps extends ComponentProps<'div'> {
asChild?: boolean;
loading: boolean;
variant?: Variant;
width?: number;
height?: number;
}
export const Skeleton = forwardRef(function Skeleton(
{ asChild, loading, children, ...props }: SkeletonProps,
ref: ForwardedRef<any>,
) {
if (!loading) return children;

const Component = asChild ? Slot : 'div';

const style = {
'--width': props.width ? `${props.width}px` : 'auto',
'--height': props.height ? `${props.height}px` : 'auto',
borderRadius: props.variant === 'circle' ? '50%' : '4px',
} as CSSProperties;

return (
<Component ref={ref} {...props} style={style} className={styles.skeleton}>
{children}
</Component>
);
});
Skeleton.displayName = 'Skeleton';
1 change: 1 addition & 0 deletions packages/skeleton/src/env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare module '*.module.css';
1 change: 1 addition & 0 deletions packages/skeleton/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Skeleton';
3 changes: 3 additions & 0 deletions packages/skeleton/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "../../tsconfig.json"
}
8 changes: 8 additions & 0 deletions packages/skeleton/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { defineConfig } from 'tsup';

export default defineConfig({
entry: ['src/index.ts'],
clean: true,
dts: true,
format: ['esm', 'cjs'],
});
12 changes: 12 additions & 0 deletions packages/skeleton/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { defineConfig } from 'vitest/config';

export default defineConfig({
test: {
environment: 'happy-dom',
globals: true,
passWithNoTests: true,
setupFiles: './vitest.setup.ts',
watch: false,
css: true,
},
});
1 change: 1 addition & 0 deletions packages/skeleton/vitest.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import '@testing-library/jest-dom';
61 changes: 61 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 f59d871

Please sign in to comment.