Skip to content

Commit

Permalink
Merge pull request #4 from Principes-Artis-Mechanicae/hotfix/Radio
Browse files Browse the repository at this point in the history
Feature: DropDown 컴포넌트 구현
  • Loading branch information
toothlessdev authored Aug 25, 2024
2 parents b60a8d9 + 25e6945 commit e86dbf8
Show file tree
Hide file tree
Showing 19 changed files with 228 additions and 26 deletions.
6 changes: 3 additions & 3 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import path from "path";

const config = {
stories: [
"../stories/**/*.mdx",
"../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)",
"../stories/**/*.story.@(js|jsx|mjs|ts|tsx)",
"../packages/stories/**/*.mdx",
"../packages/stories/**/*.stories.@(js|jsx|mjs|ts|tsx)",
"../packages/stories/**/*.story.@(js|jsx|mjs|ts|tsx)",
],

addons: [
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "principes-getp",
"version": "1.1.1",
"version": "1.1.2",
"description": "GET-P Design System",
"type": "module",
"types": "dist/index.d.ts",
Expand Down
3 changes: 3 additions & 0 deletions packages/assets/chevron_down.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
89 changes: 89 additions & 0 deletions packages/components/form/DropDown.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import styled from "@emotion/styled";
import { DropDownProps } from "./DropDown";

export const DropDownWrapper = styled.div<Pick<DropDownProps, "width">>`
position: relative;
width: ${(props) => props.width};
`;

export const DropDownContainer = styled.div<{ height: string; isOpened: boolean }>`
box-sizing: border-box;
display: flex;
align-items: center;
width: 100%;
height: ${(props) => props.height};
padding: 0px 20px;
border: 1px solid;
border-radius: 12px;
border-color: ${(props) => {
if (props.isOpened) return "#476FF1";
else return "#EBEDEF";
}};
img {
margin-left: auto;
transform: ${(props) => {
if (props.isOpened) return "rotate(180deg)";
else return "rotate(0deg)";
}};
transition: transform 0.3s ease-in-out;
}
&:hover {
cursor: pointer;
}
`;

export const DropDownItemsContainer = styled.div<{ isOpened: boolean; maxHeight: string }>`
position: absolute;
top: calc(100% + 10px);
width: 100%;
overflow: scroll;
border-radius: 12px;
border: ${(props) => {
if (props.isOpened) return "1px solid #ebedef";
else return "none";
}};
max-height: ${(props) => {
if (props.isOpened) return props.maxHeight;
else return "0px";
}};
transition: max-height 0.3s ease-in-out;
`;

export const DropDownItemWrapper = styled.div<{ active: boolean }>`
box-sizing: border-box;
display: flex;
align-items: center;
width: 100%;
height: 54px;
padding: 0px 20px;
&:hover {
background-color: #fafafa;
cursor: pointer;
}
font-weight: ${(props) => {
if (props.active) return "bold";
else return "normal";
}};
color: ${(props) => {
if (props.active) return "#476FF1";
else return "#021026";
}};
`;
58 changes: 58 additions & 0 deletions packages/components/form/DropDown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { useEffect, useState } from "react";
import { DropDownContainer, DropDownItemsContainer, DropDownItemWrapper, DropDownWrapper } from "./DropDown.style";
import { SelectedItem, useDropDown } from "../../context/DropDownContext";
import { Text } from "../../components/typography/Text";
import chevronDown from "../../assets/chevron_down.svg";

export interface DropDownProps {
width: string;
height: string;
itemContainerHeight: string;

children?: React.ReactNode;

placeholder: string;
onValueChange?: (value: SelectedItem) => void;
}

export interface DropDownItemProps extends SelectedItem {}

export const DropDown = ({
width,
height,
children,
placeholder,
itemContainerHeight,
onValueChange,
}: DropDownProps) => {
const [isOpened, setIsOpened] = useState<boolean>(false);
const { selected } = useDropDown();

useEffect(() => {
onValueChange && onValueChange(selected);
}, [selected]);

return (
<DropDownWrapper width={width}>
<DropDownContainer height={height} isOpened={isOpened} onClick={() => setIsOpened((isOpened) => !isOpened)}>
<Text size="l">{selected.index === -1 ? placeholder : selected.value}</Text>
<img src={chevronDown} />
</DropDownContainer>
<DropDownItemsContainer isOpened={isOpened} maxHeight={itemContainerHeight}>
{children}
</DropDownItemsContainer>
</DropDownWrapper>
);
};

export const DropDownItem = ({ index, value }: DropDownItemProps) => {
const { selected, setSelected } = useDropDown();
return (
<DropDownItemWrapper
active={selected.index === index}
onClick={() => setSelected({ ...selected, index, value })}
>
{value}
</DropDownItemWrapper>
);
};
22 changes: 22 additions & 0 deletions packages/context/DropDownContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { createContext, useContext, useState } from "react";

export interface SelectedItem {
index: number;
value: string;
}

export const DropDownContext = createContext<{
selected: SelectedItem;
setSelected: React.Dispatch<React.SetStateAction<SelectedItem>>;
} | null>(null);

export const useDropDown = () => {
const context = useContext(DropDownContext);
if (!context) throw new Error("useDropDown 은 DropDownContext 내부에서 사용되어야 합니다");
return context;
};

export const DropDownContextProvider = ({ children }: { children: React.ReactNode }) => {
const [selected, setSelected] = useState<SelectedItem>({ index: -1, value: "" });
return <DropDownContext.Provider value={{ selected, setSelected }}>{children}</DropDownContext.Provider>;
};
3 changes: 1 addition & 2 deletions packages/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
export { Test } from "./utils/test";

// components/form
export { Button } from "./components/form/Button";
export { CheckBox } from "./components/form/CheckBox";
Expand All @@ -8,6 +6,7 @@ export { Label } from "./components/form/Label";
export { SearchBar } from "./components/form/SearchBar";
export { TextArea } from "./components/form/TextArea";
export { RadioGroup, RadioItem } from "./components/form/Radio";
export { DropDown, DropDownItem } from "./components/form/DropDown";

// components/helper
export { withProviders } from "./components/helper/withProviders";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Button } from "../packages/components/form/Button";
import { Button } from "../components/form/Button";
import type { Meta, StoryObj } from "@storybook/react";

const meta = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CheckBox } from "../packages/components/form/CheckBox";
import { CheckBox } from "../components/form/CheckBox";
import type { Meta, StoryObj } from "@storybook/react";

const meta = {
Expand Down
40 changes: 40 additions & 0 deletions packages/stories/DropDown.story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { DropDownContextProvider } from "../context/DropDownContext";
import { DropDown, DropDownItem } from "../components/form/DropDown";
import type { Meta, StoryObj } from "@storybook/react";

const meta = {
title: "Form/DropDown",
component: DropDown,
} satisfies Meta<typeof DropDown>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
args: {
width: "440px",
height: "54px",
itemContainerHeight: "150px",
placeholder: "카테고리를 선택해주세요",
},
render: (args) => {
return (
<DropDownContextProvider>
<DropDown
width={args.width}
height={args.height}
itemContainerHeight={args.itemContainerHeight}
placeholder={args.placeholder}
onValueChange={(value) => {
console.log(value);
}}
>
<DropDownItem index={1} value="프론트엔드 개발" />
<DropDownItem index={2} value="백엔드 개발" />
<DropDownItem index={3} value="앱 개발" />
<DropDownItem index={4} value="프로그램 개발" />
</DropDown>
</DropDownContextProvider>
);
},
};
5 changes: 2 additions & 3 deletions stories/Input.story.tsx → packages/stories/Input.story.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from "react";
import { Button } from "../packages/components/form/Button";
import { Input } from "../packages/components/form/Input";
import { Button } from "../components/form/Button";
import { Input } from "../components/form/Input";
import { css } from "@emotion/react";
import type { Meta, StoryObj } from "@storybook/react";

Expand Down
2 changes: 1 addition & 1 deletion stories/Label.story.ts → packages/stories/Label.story.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Label } from "../packages/components/form/Label";
import { Label } from "../components/form/Label";
import type { Meta, StoryObj } from "@storybook/react";

const meta = {
Expand Down
2 changes: 1 addition & 1 deletion stories/Radio.story.ts → packages/stories/Radio.story.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Meta, StoryObj } from "@storybook/react";
import { RadioItem } from "../packages/components/form/Radio";
import { RadioItem } from "../components/form/Radio";

const meta = {
title: "Form/Radio",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from "react";
import type { Meta, StoryObj } from "@storybook/react";
import { RadioGroup, RadioItem } from "../packages/components/form/Radio";
import { RadioGroup, RadioItem } from "../components/form/Radio";

const meta = {
title: "Form/Radio",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SearchBar } from "../packages/components/form/SearchBar";
import { SearchBar } from "../components/form/SearchBar";
import type { Meta, StoryObj } from "@storybook/react";

const meta = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TextArea } from "../packages/components/form/TextArea";
import { TextArea } from "../components/form/TextArea";
import type { Meta, StoryObj } from "@storybook/react";

const meta = {
Expand Down
3 changes: 0 additions & 3 deletions packages/utils/test.ts

This file was deleted.

4 changes: 0 additions & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,

// "baseUrl": "packages",
// "paths": {
// "@/*": ["*"]
// },
"typeRoots": ["./node_modules/@types", "@types"]
},
"include": ["packages", "./packages/index.d.ts"]
Expand Down

0 comments on commit e86dbf8

Please sign in to comment.