React, TypeScript 및 Storybook을 사용하여 구성 요소 디자인 시스템 만들기
26063 단어 webdevjavascriptbeginnersreact
Tailwindcss 또는 Bootstrap과 같은 CSS 프레임워크를 사용해 본 사람들에게는 이러한 프레임워크가 자체 디자인 시스템을 고수하기 때문에 디자인 시스템으로 작업한다는 아이디어가 새로운 것이 아닙니다. Storybook은 기본적으로 개발자가 프런트엔드에서 자신만의 구성 요소 디자인 시스템을 만들 수 있는 방법을 제공합니다. 구성 요소를 개별적으로 볼 수 있고 모든 구성 요소에 대한 문서 및 테스트를 생성할 수 있기 때문에 이것은 매우 좋습니다.
예를 들어 고객에게 Storybook의 디자인 시스템을 보여주면 모든 구성 요소가 어떻게 보이는지 볼 수 있습니다. 다른 버전을 볼 수 있도록 배경색 및 글꼴 크기와 같은 일부 값을 변경할 수도 있습니다. 디자이너의 경우 코드에서 자신의 디자인이 어떻게 보이는지 볼 수 있고 애니메이션이 있으면 그것도 볼 수 있습니다.
프로젝트 설정
Storybook으로 보일러플레이트 React 프로젝트를 설정하는 것으로 시작하겠습니다. 디렉터리로 이동하여 명령줄 도구를 엽니다. 아래 코드를 복사하여 명령줄에 붙여넣어 프로젝트를 설정합니다.
npx create-react-app my-app --template typescript
cd my-app
npx sb init
이제 두 개의 실행 스크립트가 있어야 합니다. 아래 두 스크립트를 모두 실행하여 서버를 시작하십시오.
# Starts the React Application
npm run start
# Starts the Storybook component design system
npm run storybook
Storybook 구성 요소 만들기
웹 브라우저에서 열린 Storybook 개발 페이지로 이동하면 작동 방식에 대한 느낌을 얻을 수 있도록 몇 가지 예제 구성 요소가 제공되어야 합니다. 이제 Storybook을 사용하여 구성 요소를 만드는 것이 어떤 것인지 확인할 수 있도록 UI 구성 요소를 만들어 보겠습니다.
먼저 Hero라는 폴더를 만들고 src 안에 있는 stories 폴더 안에 넣습니다. 이제 3개의 파일을 만들어 Hero 폴더 안에 넣습니다.
Hero.css
, Hero.stories.tsx
및 Hero.tsx
파일을 생성합니다.아래 코드를 복사하여 해당 파일에 붙여넣습니다.
src/stories/Hero/Hero.css
@import url('https://fonts.googleapis.com/css2?family=Quicksand:wght@400;500;700&display=swap');
.hero {
background: rgb(236, 236, 236);
border: 1rem solid rgb(220, 220, 220);
max-width: 50rem;
width: 100%;
border-radius: 1rem;
}
.hero-content {
width: 100%;
display: flex;
flex-flow: column nowrap;
}
.hero-content h1 {
font-family: 'Quicksand', sans-serif;
color: #000000;
text-transform: uppercase;
text-align: center;
}
.hero-content img {
max-width: 50rem;
width: 100%;
}
.hero-content p {
font-family: 'Quicksand', sans-serif;
color: #000000;
padding: 0.5rem;
}
#preloader {
width: 50rem;
height: 50rem;
}
#loader {
display: block;
position: relative;
left: 50%;
top: 50%;
width: 150px;
height: 150px;
margin: -75px 0 0 -75px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #9370db;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
#loader:before {
content: '';
position: absolute;
top: 5px;
left: 5px;
right: 5px;
bottom: 5px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #ba55d3;
-webkit-animation: spin 3s linear infinite;
animation: spin 3s linear infinite;
}
#loader:after {
content: '';
position: absolute;
top: 15px;
left: 15px;
right: 15px;
bottom: 15px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #ff00ff;
-webkit-animation: spin 1.5s linear infinite;
animation: spin 1.5s linear infinite;
}
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes spin {
0% {
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
src/stories/Hero/Hero.stories.tsx
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Hero } from './Hero';
export default {
title: 'Hero/Hero',
component: Hero,
} as ComponentMeta<typeof Hero>;
const Template: ComponentStory<typeof Hero> = (args) => <Hero {...args} />;
export const Primary = Template.bind({});
Primary.args = {
id: 1,
title: 'Mountain',
img: 'https://images.unsplash.com/photo-1464278533981-50106e6176b1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2274&q=80',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis mollis tellus et libero feugiat, vitae dignissim augue pulvinar.',
};
src/stories/Hero/Hero.tsx
import './Hero.css';
interface Heroprops {
id: number;
title: string;
img: string;
content: string;
loading: boolean;
}
export const Hero = ({ id, title, img, content, loading, ...props }: Heroprops) => {
return (
<>
<div className="hero">
{loading ? (
<div id="preloader">
<div id="loader"></div>
</div>
) : (
<div className="hero-content">
<h1>{title}</h1>
<img src={img} alt={title} />
<p>{content}</p>
</div>
)}
</div>
</>
);
};
export default Hero;
App.css
파일 내부의 모든 코드를 아래 코드로 바꿉니다.
*,
*::before,
*::after {
padding: 0;
margin: 0;
box-sizing: border-box;
}
html {
font-size: 16px;
}
body {
font-size: 1rem;
font-family: 'Quicksand', sans-serif;
color: #000000;
background-color: #222;
}
.container {
margin: 0 auto;
width: 100%;
max-width: 50rem;
}
App.tsx
파일 내부의 모든 코드를 아래 코드로 바꿉니다.
import Hero from '../src/stories/Hero/Hero';
import './App.css';
const App = () => {
return (
<>
<div className="container">
<Hero
id={1}
title={'Mountain'}
img={
'https://images.unsplash.com/photo-1464278533981-50106e6176b1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2274&q=80'
}
content={
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis mollis tellus et libero feugiat, vitae dignissim augue pulvinar.'
}
// Change this value to true to see the loading animation
loading={false}
/>
</div>
</>
);
};
export default App;
React 앱과 Storybook 서버용 서버를 다시 로드하면 이제 이미지가 있는 Hero 구성 요소가 표시됩니다. 어떤 이유로든 이미지가 깨지면 이미지 URL을 다른 것으로 변경할 수 있습니다.
App.tsx
및 Hero.stories.tsx
파일에서 이 작업을 수행합니다.Hero 구성 요소에는 Storybook에서 몇 가지 사용자 지정 가능한 옵션이 있습니다. ID, 제목, img, 콘텐츠 및 로딩 상태까지 변경할 수 있습니다.
마지막 생각들
Storybook 사용에 대한 간략한 소개입니다. 자세한 내용은 메인Storybook website을 참조하십시오.
Reference
이 문제에 관하여(React, TypeScript 및 Storybook을 사용하여 구성 요소 디자인 시스템 만들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/andrewbaisden/creating-a-component-design-system-using-react-typescript-and-storybook-381g텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)