diff --git a/frontend/src/components/common/TooltipToggleButton.tsx b/frontend/src/components/common/TooltipToggleButton.tsx index 85247ce8..26d8a1aa 100644 --- a/frontend/src/components/common/TooltipToggleButton.tsx +++ b/frontend/src/components/common/TooltipToggleButton.tsx @@ -4,9 +4,6 @@ const style = { toggleButton: { width: "25px", height: "25px", - minWidth: "25px", - padding: "0", - margin: "2px", border: "none", fontWeight: "bold", }, diff --git a/frontend/src/components/editor/Editor.tsx b/frontend/src/components/editor/Editor.tsx index 12b6e92c..d7010279 100644 --- a/frontend/src/components/editor/Editor.tsx +++ b/frontend/src/components/editor/Editor.tsx @@ -14,9 +14,9 @@ import { useCreateUploadUrlMutation, useUploadFileMutation } from "../../hooks/a import { selectWorkspace } from "../../store/workspaceSlice"; import { ScrollSyncPane } from "react-scroll-sync"; import { selectSetting } from "../../store/settingSlice"; -import { FormatBarState, useFormatUtils, FormatType } from "../../hooks/useFormatUtils"; +import { ToolBarState, useFormatUtils, FormatType } from "../../hooks/useFormatUtils"; -import FormatBar from "./FormatBar"; +import ToolBar from "./ToolBar"; function Editor() { const dispatch = useDispatch(); @@ -28,7 +28,7 @@ function Editor() { const { mutateAsync: createUploadUrl } = useCreateUploadUrlMutation(); const { mutateAsync: uploadFile } = useUploadFileMutation(); - const [formatBarState, setFormatBarState] = useState({ + const [toolBarState, setToolBarState] = useState({ show: false, position: { top: 0, left: 0 }, selectedFormats: new Set(), @@ -73,18 +73,19 @@ function Editor() { checkAndAddFormat("`", FormatType.CODE); checkAndAddFormat("~~", FormatType.STRIKETHROUGH); - setFormatBarState((prev) => ({ + // TODO: Modify the rendering method so that it is not affected by the size of the Toolbar + setToolBarState((prev) => ({ ...prev, show: true, position: { - top: coords.top - 8, - left: coords.left + 190, + top: coords.top - 5, + left: coords.left, }, selectedFormats: formats, })); } } else { - setFormatBarState((prev) => ({ + setToolBarState((prev) => ({ ...prev, show: false, selectedFormats: new Set(), @@ -185,11 +186,8 @@ function Editor() { minHeight: "100%", }} /> - {Boolean(formatBarState.show && editorStore.cmView) && ( - + {Boolean(toolBarState.show) && ( + )} diff --git a/frontend/src/components/editor/FormatBar.tsx b/frontend/src/components/editor/FormatBar.tsx deleted file mode 100644 index e58516f2..00000000 --- a/frontend/src/components/editor/FormatBar.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { Popover, ToggleButtonGroup } from "@mui/material"; -import TooltipToggleButton from "../common/TooltipToggleButton"; -import { FormatBarState, useFormatUtils, FormatType } from "../../hooks/useFormatUtils"; - -interface FormatBarProps { - formatBarState: FormatBarState; - onChangeFormatBarState: React.Dispatch>; -} - -function FormatBar({ - formatBarState: { show: showFormatBar, position: formatBarPosition, selectedFormats }, - onChangeFormatBarState, -}: FormatBarProps) { - const { toggleButtonChangeHandler } = useFormatUtils(); - - return ( - onChangeFormatBarState((prev) => ({ ...prev, show: false }))} - anchorOrigin={{ - vertical: "top", - horizontal: "left", - }} - transformOrigin={{ - vertical: "bottom", - horizontal: "left", - }} - disableAutoFocus - > - - - i - - - B - - - ~ - - - {""} - - - - ); -} - -export default FormatBar; diff --git a/frontend/src/components/editor/ToolBar.tsx b/frontend/src/components/editor/ToolBar.tsx new file mode 100644 index 00000000..d5f57e0e --- /dev/null +++ b/frontend/src/components/editor/ToolBar.tsx @@ -0,0 +1,104 @@ +import { Popover, ToggleButtonGroup, Divider, Stack, Fade } from "@mui/material"; +import TooltipToggleButton from "../common/TooltipToggleButton"; +import { ToolBarState, useFormatUtils, FormatType } from "../../hooks/useFormatUtils"; +import YorkieIntelligence from "./YorkieIntelligence"; +import { useDebounce } from "react-use"; +import { useState } from "react"; + +interface ToolBarProps { + toolBarState: ToolBarState; + onChangeToolBarState: React.Dispatch>; +} + +function ToolBar({ + toolBarState: { show: showToolBar, position: formatBarPosition, selectedFormats }, + onChangeToolBarState, +}: ToolBarProps) { + const { toggleButtonChangeHandler } = useFormatUtils(); + const [debouncedShowToolBar, setDebouncedShowToolBar] = useState(null); + + useDebounce( + () => { + setDebouncedShowToolBar(showToolBar); + }, + 500, + [showToolBar] + ); + + if (!debouncedShowToolBar) return; + + return ( + onChangeToolBarState((prev) => ({ ...prev, show: false }))} + anchorOrigin={{ + vertical: "top", + horizontal: "left", + }} + transformOrigin={{ + vertical: "bottom", + horizontal: "left", + }} + disableAutoFocus + TransitionComponent={Fade} + TransitionProps={{ timeout: 300 }} + > + + + + + + + i + + + B + + + ~ + + + {""} + + + + + + ); +} + +export default ToolBar; diff --git a/frontend/src/components/editor/YorkieIntelligence.tsx b/frontend/src/components/editor/YorkieIntelligence.tsx index 1fcac643..26b7c335 100644 --- a/frontend/src/components/editor/YorkieIntelligence.tsx +++ b/frontend/src/components/editor/YorkieIntelligence.tsx @@ -1,36 +1,26 @@ -import { Card, CardActionArea, Fade, Popper, Stack, Typography, useTheme } from "@mui/material"; +import { Button, Typography } from "@mui/material"; import { useEffect, useState } from "react"; import { createPortal } from "react-dom"; -import { useDebounce } from "react-use"; -import { INTELLIGENCE_FOOTER_ID, INTELLIGENCE_HEADER_ID } from "../../constants/intelligence"; +import { INTELLIGENCE_FOOTER_ID } from "../../constants/intelligence"; import YorkieIntelligenceFooter from "./YorkieIntelligenceFooter"; +import { useSelector } from "react-redux"; +import { selectSetting } from "../../store/settingSlice"; function YorkieIntelligence() { - const theme = useTheme(); const [footerOpen, setFooterOpen] = useState(false); - const [intelligenceHeaderPivot, setIntelligenceHeaderPivot] = useState(null); const [intelligenceFooterPivot, setIntelligenceFooterPivot] = useState(null); - const [debouncedPivot, setDebouncedPivot] = useState(null); - useDebounce( - () => { - setDebouncedPivot(intelligenceHeaderPivot); - }, - 500, - [intelligenceHeaderPivot] - ); + const { yorkieIntelligence } = useSelector(selectSetting); useEffect(() => { + // initialize intelligence footer pivot + const intelligenceFooterPivot = document.getElementById(INTELLIGENCE_FOOTER_ID); + setIntelligenceFooterPivot(intelligenceFooterPivot); + document.addEventListener("selectionchange", function () { - const intelligenceHeaderPivot = document.getElementById(INTELLIGENCE_HEADER_ID); + // If changed selection (ex : text formatting), update the intelligence footer pivot const intelligenceFooterPivot = document.getElementById(INTELLIGENCE_FOOTER_ID); - setIntelligenceHeaderPivot(intelligenceHeaderPivot); setIntelligenceFooterPivot(intelligenceFooterPivot); - - if (!intelligenceHeaderPivot) { - setFooterOpen(false); - setDebouncedPivot(null); - } }); }, []); @@ -38,41 +28,32 @@ function YorkieIntelligence() { setFooterOpen((prev) => !prev); }; - if (!debouncedPivot || !intelligenceFooterPivot) return; + if (!intelligenceFooterPivot) return; return ( <> - - {({ TransitionProps }) => ( - - - - - - Yorkie Intelligence - - - - - )} - + yorkie_img + + Yorkie Intelligence + + + {footerOpen && createPortal( , diff --git a/frontend/src/hooks/useFormatUtils.ts b/frontend/src/hooks/useFormatUtils.ts index 9443350d..deedf1e0 100644 --- a/frontend/src/hooks/useFormatUtils.ts +++ b/frontend/src/hooks/useFormatUtils.ts @@ -6,7 +6,7 @@ import { Dispatch, SetStateAction } from "react"; import { useSelector } from "react-redux"; import { selectEditor } from "../store/editorSlice"; -export interface FormatBarState { +export interface ToolBarState { show: boolean; position: { top: number; left: number }; selectedFormats: Set; @@ -122,7 +122,7 @@ export const useFormatUtils = () => { const toggleButtonChangeHandler = useCallback( ( selectedFormats: Set, - onChangeFormatBarState: Dispatch> + onChangeToolBarState: Dispatch> ) => { return (_event: MouseEvent, format: FormatType) => { if (!cmView) return; @@ -133,7 +133,7 @@ export const useFormatUtils = () => { } else { newSelectedFormats.add(format); } - onChangeFormatBarState((prev) => ({ + onChangeToolBarState((prev) => ({ ...prev, selectedFormats: newSelectedFormats, })); diff --git a/frontend/src/pages/workspace/document/Index.tsx b/frontend/src/pages/workspace/document/Index.tsx index 2a3fa823..8ae61c30 100644 --- a/frontend/src/pages/workspace/document/Index.tsx +++ b/frontend/src/pages/workspace/document/Index.tsx @@ -8,15 +8,12 @@ import { useGetDocumentQuery } from "../../../hooks/api/workspaceDocument"; import { useGetWorkspaceQuery } from "../../../hooks/api/workspace"; import DocumentView from "../../../components/editor/DocumentView"; import { useYorkieDocument } from "../../../hooks/useYorkieDocument"; -import YorkieIntelligence from "../../../components/editor/YorkieIntelligence"; -import { selectSetting } from "../../../store/settingSlice"; function DocumentIndex() { const dispatch = useDispatch(); const params = useParams(); const userStore = useSelector(selectUser); - const settingStore = useSelector(selectSetting); const { data: workspace, isLoading: isWorkspaceLoading } = useGetWorkspaceQuery( params.workspaceSlug ); @@ -49,7 +46,6 @@ function DocumentIndex() { return ( - {settingStore.yorkieIntelligence?.enable && } ); }