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

chore: 일부 컴포넌트 스토리 추가 #594

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"dev": "vite",
"build": "vite build",
"serve": "vite preview",
"story": "ladle serve",
"lint": "eslint src"
},
"eslintConfig": {
Expand Down
85 changes: 85 additions & 0 deletions src/component/utils/Accordion.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { useState } from "react";
import { Story } from "@ladle/react";
import Accordion, { Props } from "./Accordion";

type AccordionStory = Story<Props>;

const argTypes: AccordionStory["argTypes"] = {
summaryIconType: {
options: ["plus", "arrow"],
control: { type: "inline-radio" },
defaultValue: "arrow",
},
summaryIconPosition: {
options: ["start", "end"],
control: { type: "inline-radio" },
defaultValue: "start",
},
};

export const 활용법: AccordionStory = ({ ...args }) => {
const [isOpened, setIsOpened] = useState(false);

return (
<div>
<h1>Accordion</h1>
<h2>토글방식의 UI를 위한 컴포넌트</h2>
<h3>클릭하면 접혀있던/펼쳐져 있던 내용을 확인할 수 있습니다.</h3>
<Accordion summaryUI="클릭해주세요" detailUI="까꿍" />
<Accordion
{...args}
initialOpened={true}
summaryUI={<p> 처음부터 열려있도록 설정할 수도 있습니다</p>}
detailUI={<p>펼쳐있을 때만 보이는 부분</p>}
/>
<h3>활용방법</h3>
<Accordion
{...args}
summaryUI="ReactNode로 설정되어 있기 때문에 컴포넌트/문자열 등 다양하게 활용할 수 있어요"
detailUI={
<p style={{ backgroundColor: "lightgrey", marginTop: "-15px" }}>
<p>
느끼셨다시피 기본 스타일링은 없다시피 합니다. 필요에 따라
className등으로 설정해주세요
</p>
<p>
대표적으로 <a href="https://42library.kr/information">이용안내</a>
페이지에서 활용하는 컴포넌트입니다
</p>
</p>
}
/>
<Accordion
summaryUI="기본적으로 쓰이는 아이콘이 지정되어 있어요"
detailUI="자세한건 왼쪽 하단 컨트롤로 조정해보세요"
initialOpened={true}
summaryIconType="plus"
summaryIconPosition="end"
/>
<h3>
기타 활용 : <b>일괄접기</b>
</h3>
<Accordion
{...args}
initialOpened={isOpened}
summaryUI="이 컴포넌트의 접힘 상태에 따라 아래 컴포넌트가 함께 접히거나 펼쳐집니다"
detailUI="아래 컴포넌트들의 dependencyOpened 설정 때문이예요"
onChange={() => setIsOpened(!isOpened)}
/>
<Accordion
{...args}
dependencyOpened={isOpened}
summaryUI="!!"
detailUI="!!"
/>
<Accordion
{...args}
dependencyOpened={isOpened}
summaryUI="개별적으로 여닫을 수도 있어요"
detailUI="!!!"
/>
</div>
);
};

활용법.argTypes = argTypes;
5 changes: 3 additions & 2 deletions src/component/utils/Accordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Minus from "../../asset/img/plus_icon_on.svg";
import Arrow from "../../asset/img/arrow_right_black.svg";
import "../../asset/css/Accordion.css";

type AccordionProp = {
export type Props = {
initialOpened?: boolean;
summaryButtonClassName?: string;
summaryIconClassName?: string;
Expand All @@ -17,6 +17,7 @@ type AccordionProp = {
onChange?: (isOpened: boolean) => void;
fixed?: boolean;
};

const Accordion = ({
initialOpened = false,
summaryIconType,
Expand All @@ -28,7 +29,7 @@ const Accordion = ({
dependencyOpened,
onChange,
fixed = false,
}: AccordionProp) => {
}: Props) => {
const [isOpened, setIsOpened] = useState(initialOpened);

useEffect(() => {
Expand Down
130 changes: 130 additions & 0 deletions src/component/utils/Carousel.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { Story } from "@ladle/react";
import Carousel from "./Carousel";
import { Props } from "./CarouselRoot";

type CarouselStory = Story<Props>;

const exampleArray = Array.from({ length: 10 }, (_, i) => ({ id: i + 1 }));
const exampleItemSize = 100;
// 리스트 내부에 들어갈 UI 컴포넌트 예시
const ExampleItemUi = ({ item }: { item: { id: number } }) => (
<div
style={{
width: "100px",
height: "100px",
border: "solid 2px red",
flexBasis: exampleItemSize,
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
{item.id}
</div>
);

export const 기본활용법: CarouselStory = () => (
<>
<h1>Carousel</h1>
<h2>무한 회전하는 UI 컴포넌트</h2>
<h3>기본으로 애니메이션이 적용된 리스트</h3>
<p>- 무한회전을 위한 설정 자동으로 적용됨 (마지막요소 다음에 첫요소 등)</p>
<p>- 마우스 hover시 일시 정지 및 재시작 기능 포함</p>
<p>- 메인페이지 인기도서, 인기검색어 등에 활용되고 있음</p>
<Carousel.Root length={exampleArray.length} itemSize={exampleItemSize}>
<Carousel.List items={exampleArray} renderItem={ExampleItemUi} />
</Carousel.Root>
</>
);

export const 조합활용: CarouselStory = () => (
<>
<h1>Carousel</h1>
<h2>다양한 컴포넌트를 조합하여 활용</h2>
<h3>컴포넌트를 조합하여 다양한 UI를 구성할 수 있음</h3>
<p>필수 컴포넌트인 Root와 List외의 컴포넌트는 필요에 따라 추가할 수 있음</p>
<p>Root로 감싸있기만 하면 컴포넌트의 위치 및 순서, 조합은 자유롭게 선택 </p>
<p>
cf.
<a href="https://www.google.com/search?q=Compound+Pattern">
Compound Pattern
</a>
</p>

<Carousel.Root length={exampleArray.length} itemSize={exampleItemSize}>
<Carousel.Container>
<Carousel.Prev>
<button>이전</button>
</Carousel.Prev>
<Carousel.List items={exampleArray} renderItem={ExampleItemUi} />
<Carousel.Prev>
<button>이전</button>
</Carousel.Prev>
</Carousel.Container>
<Carousel.Next>
<button>다음</button>
</Carousel.Next>
</Carousel.Root>
</>
);
export const 컴포넌트상세: CarouselStory = () => (
<>
<h1>Carousel.Root</h1>
<p>필수 컴포넌트, 전체를 감싸는 context 제공</p>

<h1>Carousel.List</h1>
<p>필수 컴포넌트, 리스트와 각 요소 UI 표현</p>

<h1>Carousel.Container</h1>
<p>리스트를 감싸는 컴포넌트 (생략가능)</p>
<p>특정 영역만 보이도록 설정하기 위함</p>
<Carousel.Root length={exampleArray.length} itemSize={exampleItemSize}>
<Carousel.Container style={{ width: "250px" }}>
<Carousel.List items={exampleArray} renderItem={ExampleItemUi} />
</Carousel.Container>
</Carousel.Root>

<h1>Carousel.Prev & Carousel.Next</h1>
<p>리스트 이전/다음 요소로 넘기기 위한 버튼 컴포넌트 (생략가능)</p>
<Carousel.Root length={exampleArray.length} itemSize={exampleItemSize}>
<Carousel.Next>다음</Carousel.Next>
<Carousel.List items={exampleArray} renderItem={ExampleItemUi} />
<Carousel.Prev>
<p>이전</p>
<span style={{ backgroundColor: "lightgreen" }}>
이 안에 다양한 UI를 넣어 꾸밀 수 있어요
</span>
</Carousel.Prev>
</Carousel.Root>

<h1>Carousel.Pagination</h1>
<p>리스트 페이지네이션 용 컴포넌트 (생략가능)</p>
<p>
리스트의 현재 위치를 나타내거나 특정 위치로 이동하도록 설정가능 (생략가능)
</p>
<p>Root에 저장된 page, setPage, lastPage를 Props로 받아 UI를 구성</p>
<p>- page : 현재 리스트의 위치</p>
<p>- setPage : 특정 위치로 이동시키는 함수</p>
<Carousel.Root length={exampleArray.length} itemSize={exampleItemSize}>
<Carousel.List items={exampleArray} renderItem={ExampleItemUi} />
<Carousel.Pagination
render={({ page, setPage }) => (
<>
{exampleArray.map(item => {
const isCurrentPage = item.id === page;
return (
<button
key={item.id}
onClick={() => setPage(item.id)}
style={{ color: isCurrentPage ? "red" : "black" }}
>
{item.id}
</button>
);
})}
</>
)}
/>
</Carousel.Root>
</>
);
2 changes: 1 addition & 1 deletion src/component/utils/CarouselRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useInterval } from "~/hook/useInterval";
import { CarouselContext } from "~/component/utils/Carousel";
import "~/asset/css/Carousel.css";

type Props = {
export type Props = {
length: number;
itemSize?: number;
itemCount?: number;
Expand Down
27 changes: 27 additions & 0 deletions src/component/utils/Tooltip.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Story } from "@ladle/react";
import Tooltip, { Props } from "./Tooltip";

type TooltipStory = Story<Props>;

export const 활용법: TooltipStory = () => (
<>
{/* 툴팁 컴포넌트 활용에 필요, App.tsx에 내장되어 있음 */}
<div id="portal" />
<h1>Tooltip</h1>
<h2>UI의 간단한 설명을 추가하기 위한 컴포넌트</h2>
<h3>마우스 hover시 설명을 확인할 수 있습니다.</h3>
<Tooltip description="툴팁의 설명입니다">
<span>툴팁이 나올 요소입니다</span>
</Tooltip>
<div
style={{
display: "flex",
justifyContent: "end",
}}
>
<Tooltip description="↑ 툴팁 시작위치">
하위요소 위치에 바로 아래에 툴팁이 나옵니다
</Tooltip>
</div>
</>
);
4 changes: 2 additions & 2 deletions src/component/utils/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { ReactNode, useState } from "react";
import { createPortal } from "react-dom";
import { useBound } from "~/hook/useBound";

type TooltipProps = {
export type Props = {
className?: string;
children: ReactNode;
description: string;
};

const Tooltip = ({ children, description, className }: TooltipProps) => {
const Tooltip = ({ children, description, className }: Props) => {
const [isDisplayed, setDisplayed] = useState(false);
const { boundInfo, targetRef } = useBound<HTMLDivElement>({
hasResizeEvent: true,
Expand Down
Loading