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

[FE][FEAT] #145 - 플로팅 버튼 구현 #150

Merged
merged 16 commits into from
Nov 13, 2024
Merged
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

<p>
<a href="https://www.notion.so/127b1b2b649180e88f70d6a4648924a0?pvs=4">팀 노션</a> |
<a href="https://github.com/boostcampwm-2024/web28-DDara/wiki">팀 위키</a> |
<a href="https://ddara-docs.vercel.app/">팀 위키</a> |
<a href="https://www.figma.com/design/r9nl4Jcz9VXIMbrpf50wY6/PickMeUp?node-id=90-1897">기획서</a> |
<a href="https://www.figma.com/design/r9nl4Jcz9VXIMbrpf50wY6/PickMeUp?node-id=87-929">디자인</a>
<!-- <br />
Expand Down
2 changes: 1 addition & 1 deletion docs/docusaurus/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

<p>
<a href="https://www.notion.so/127b1b2b649180e88f70d6a4648924a0?pvs=4">팀 노션</a> |
<a href="https://github.com/boostcampwm-2024/web28-DDara/wiki">팀 위키</a> |
<a href="https://ddara-docs.vercel.app/">팀 위키</a> |
<a href="https://www.figma.com/design/r9nl4Jcz9VXIMbrpf50wY6/PickMeUp?node-id=90-1897">기획서</a> |
<a href="https://www.figma.com/design/r9nl4Jcz9VXIMbrpf50wY6/PickMeUp?node-id=87-929">디자인</a>
<!-- <br />
Expand Down
3 changes: 2 additions & 1 deletion docs/docusaurus/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
"react-dom": "^18.0.0",
"react-player": "^2.16.0"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.6.1",
Expand Down
8 changes: 7 additions & 1 deletion docs/docusaurus/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
// This file is not used in compilation. It is here just for a nice editor experience.
"extends": "@docusaurus/tsconfig",
"compilerOptions": {
"baseUrl": "."
"baseUrl": ".",
"paths": {
"@site/*": ["src/*"],
"@theme/*": ["src/theme/*"],
"@component/*": ["src/components/*"],
"@markdown/*": ["src/components/markdown/*"],
}
}
}
2 changes: 1 addition & 1 deletion frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ export const App = () => (
<Route path="/add-channel/:user/draw" element={<DrawRoute />} />
<Route path="/channel/:channelId/*" element={<ChannelRoutes />} />
</Routes>
);
);
118 changes: 118 additions & 0 deletions frontend/src/component/common/FloatingButton/FloatingButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import classNames from 'classnames';
import React, { useState } from 'react';
import { ButtonState } from '../enums';
import { IconType, ToolCategory } from '../types';

/**
* FloatingButton 컴포넌트는 도구 선택 및 메뉴 토글 기능을 제공하는 플로팅 버튼을 렌더링합니다.
leedongyull marked this conversation as resolved.
Show resolved Hide resolved
* @remarks
* 메뉴가 열리면 툴 선택과 설명 표시가 가능하며, 메뉴를 닫을 때 버튼 아이콘이 변경됩니다.
* @example
* return (
* <FloatingButton />
* )
*/
export const FloatingButton = () => {
const [toolType, setToolType] = useState<ButtonState>(ButtonState.CLOSE);
const [isMenuOpen, setIsMenuOpen] = useState<boolean>(false);

/**
* @remarks
* - 메뉴를 토글하는 함수입니다.
*/
const toggleMenu = () => {
setIsMenuOpen(prev => !prev);
if (!isMenuOpen) {
setToolType(ButtonState.OPEN);
} else {
setToolType(ButtonState.CLOSE);
}
};

/**
* @remarks
* 툴을 선택하고 메뉴를 닫는 함수입니다.
* @param {ButtonState} type - 선택된 툴 타입
*/
const handleMenuClick = (type: ButtonState) => {
setToolType(type);
setIsMenuOpen(!isMenuOpen);
};

return (
<div
className={classNames('absolute', 'bottom-5', 'right-10', 'flex', 'flex-col', 'items-center')}
leedongyull marked this conversation as resolved.
Show resolved Hide resolved
>
<button
type="button"
onClick={toggleMenu}
className={classNames(
'absolute',
'bottom-0',
'bg-blueGray-800',
'w-12',
'h-12',
'rounded-full',
'flex',
'justify-center',
'items-center',
'text-white',
'shadow-floatMenuButton',
'z-10',
)}
>
{React.createElement(IconType[toolType], { className: 'w-6 h-6' })}
</button>

{ToolCategory.map(({ type, description, icon }, index) => (
<button
type="button"
onClick={() => handleMenuClick(type)}
key={type}
className={classNames(
'w-10',
'h-10',
'bg-blueGray-200',
'text-white',
'rounded-full',
'flex',
'items-center',
'justify-center',
'absolute',
'transition-all',
'duration-300',
'shadow-floatButton',
{
'shadow-none': !isMenuOpen,
},
)}
style={{ bottom: toolType === ButtonState.OPEN ? `${48 * index + 64}px` : '0px' }}
>
<div className={classNames('flex', 'items-center')}>
{React.createElement(icon, { className: 'w-5 h-5' })}
{isMenuOpen && (
<div
className={classNames(
'w-20',
'h-8',
'bg-blueGray-200',
'absolute',
'right-12',
'text-white',
'text-xs',
'flex',
'items-center',
'justify-center',
'rounded-md',
'opacity-[0.5]',
)}
>
{description}
</div>
)}
</div>
</button>
))}
</div>
);
};
13 changes: 13 additions & 0 deletions frontend/src/component/common/enums.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* @remarks
* ButtonState Enum은 버튼이 가질 수 있는 모든 종류를 정의합니다.
* @example
* const buttonState = ButtonState.OPEN;
*/
export enum ButtonState {
CLOSE = 'CLOSE', // 메뉴 닫기 버튼
OPEN = 'OPEN', // 메뉴 열기 버튼
START_MARKER = 'START_MARKER', // 출발지 설정 버튼
DESTINATION_MARKER = 'DESTINATION_MARKER', // 도착지 설정 버튼
LINE_DRAWING = 'LINE_DRAWING', // 경로 그리기 버튼
}
42 changes: 42 additions & 0 deletions frontend/src/component/common/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { FaPaintBrush } from 'react-icons/fa';
import { HiLocationMarker, HiOutlineDotsHorizontal, HiOutlineLocationMarker } from 'react-icons/hi';
import { SlLayers } from 'react-icons/sl';
import { ButtonState } from './enums';

/**
* IconType 객체는 각 버튼 타입에 해당하는 아이콘 컴포넌트를 매핑합니다.
* @type {Record<ButtonState, React.ComponentType>}
*/
export const IconType = {
CLOSE: SlLayers, // 닫기 버튼 아이콘
OPEN: HiOutlineDotsHorizontal, // 열기 버튼 아이콘
START_MARKER: HiLocationMarker, // 출발지 설정 아이콘
DESTINATION_MARKER: HiOutlineLocationMarker, // 도착지 설정 아이콘
LINE_DRAWING: FaPaintBrush, // 경로 그리기 아이콘
};
/**
* @remarks
* ToolCategory 배열은 각 저작도구에 대한 정보를 담고 있습니다.
* 각 툴은 버튼 타입, 설명, 아이콘을 포함합니다.
* 이 배열은 버튼의 목록을 정의하고, 이후 툴을 확장할 때 유용합니다.
* 또한, OPEN과 CLOSE 등 저작 도구가 아닌 종류는 제외합니다.
* @example
* const tool = ToolCategory[0];
*/
export const ToolCategory = [
{
type: ButtonState.LINE_DRAWING, // 경로 그리기 툴
description: '경로 그리기', // 툴 설명
icon: IconType.LINE_DRAWING, // 툴 아이콘
},
{
type: ButtonState.START_MARKER, // 출발지 설정 툴
description: '출발지 설정', // 툴 설명
icon: IconType.START_MARKER, // 툴 아이콘
},
{
type: ButtonState.DESTINATION_MARKER, // 도착지 설정 툴
description: '도착지 설정', // 툴 설명
icon: IconType.DESTINATION_MARKER, // 툴 아이콘
},
];
2 changes: 2 additions & 0 deletions frontend/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ module.exports = {
'6xl': '4rem',
},
boxShadow: {
floatButton: '0 5px 10px rgba(0,0,0,0.3)',
floatMenuButton: '0 4px 4px rgba(0,0,0,0.25)',
float: '0 4px 20px rgba(0, 0, 0, 0.13)',
basic: 'inset 0 0 3px rgba(0, 0, 0, 0.11)',
},
Expand Down
27 changes: 27 additions & 0 deletions pnpm-lock.yaml

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

Loading