diff --git a/src/components/Editor/EditorBlockIcon/AlignIcon/AlignIcon.tsx b/src/components/Editor/EditorBlockIcon/AlignIcon/AlignIcon.tsx index f788533..80a44c9 100644 --- a/src/components/Editor/EditorBlockIcon/AlignIcon/AlignIcon.tsx +++ b/src/components/Editor/EditorBlockIcon/AlignIcon/AlignIcon.tsx @@ -6,7 +6,9 @@ import useEditorStore from "store/useEditorStore"; * 클릭 시 왼쪽 정렬과 가운데 정렬을 토글 */ export default function AlignIcon() { - const { editor, align, toggleAlign } = useEditorStore(); + const editor = useEditorStore((state) => state.editor); + const align = useEditorStore((state) => state.align); + const toggleAlign = useEditorStore((state) => state.toggleAlign); /** * 텍스트 정렬 상태를 토글하고 에디터의 블록들을 업데이트하는 함수 diff --git a/src/components/Editor/EditorBlockIcon/EmojiIcon/EmojiIcon.tsx b/src/components/Editor/EditorBlockIcon/EmojiIcon/EmojiIcon.tsx index c143331..e22140f 100644 --- a/src/components/Editor/EditorBlockIcon/EmojiIcon/EmojiIcon.tsx +++ b/src/components/Editor/EditorBlockIcon/EmojiIcon/EmojiIcon.tsx @@ -10,7 +10,7 @@ interface EmojiIconProps { * 클릭 시 이모지 선택 모달을 열고 블록 인덱스를 업데이트 */ export default function EmojiIcon({ handleBlockIndex }: EmojiIconProps) { - const { toggleModal } = useEditorStore(); + const toggleModal = useEditorStore((state) => state.toggleModal); const handleIconClick = () => { handleBlockIndex(); diff --git a/src/components/Editor/EditorBlockIcon/LineIcon/LineIcon.tsx b/src/components/Editor/EditorBlockIcon/LineIcon/LineIcon.tsx index 58040f2..5e451a5 100644 --- a/src/components/Editor/EditorBlockIcon/LineIcon/LineIcon.tsx +++ b/src/components/Editor/EditorBlockIcon/LineIcon/LineIcon.tsx @@ -10,7 +10,7 @@ interface LineIconProps { * 클릭 시 선 그리기 모달을 열고 블록 인덱스를 업데이트 */ export default function LineIcon({ handleBlockIndex }: LineIconProps) { - const { toggleModal } = useEditorStore(); + const toggleModal = useEditorStore((state) => state.toggleModal); const handleIconClick = () => { handleBlockIndex(); diff --git a/src/components/Editor/EditorBlockIcon/PlaceIcon/PlaceIcon.tsx b/src/components/Editor/EditorBlockIcon/PlaceIcon/PlaceIcon.tsx index 9a657cb..824af94 100644 --- a/src/components/Editor/EditorBlockIcon/PlaceIcon/PlaceIcon.tsx +++ b/src/components/Editor/EditorBlockIcon/PlaceIcon/PlaceIcon.tsx @@ -10,7 +10,7 @@ interface PlaceIconProps { * 클릭 시 장소 선택 모달을 열고 블록 인덱스를 업데이트 */ export default function PlaceIcon({ handleBlockIndex }: PlaceIconProps) { - const { toggleModal } = useEditorStore(); + const toggleModal = useEditorStore((state) => state.toggleModal); const handleIconClick = () => { handleBlockIndex(); diff --git a/src/components/Editor/EditorContent/EditorContent.tsx b/src/components/Editor/EditorContent/EditorContent.tsx index afeb8c7..682bb09 100644 --- a/src/components/Editor/EditorContent/EditorContent.tsx +++ b/src/components/Editor/EditorContent/EditorContent.tsx @@ -11,7 +11,7 @@ import useEditorStore from "@/store/useEditorStore"; * 드래그&드롭, 실행취소 기능을 포함한 에디터 인스턴스를 생성 */ const EditorContent = memo(() => { - const { setEditor } = useEditorStore(); + const setEditor = useEditorStore((state) => state.setEditor); const editorInstanceRef = useRef(null); useEffect(() => { diff --git a/src/components/Editor/EditorSection/EditorSection.tsx b/src/components/Editor/EditorSection/EditorSection.tsx index 53f6422..c3881c9 100644 --- a/src/components/Editor/EditorSection/EditorSection.tsx +++ b/src/components/Editor/EditorSection/EditorSection.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from "react"; +import { useRef } from "react"; import * as S from "./EditorSection.style"; import EditorToolbar from "@/components/Editor/EditorToolbar/EditorToolbar"; import EditorContent from "@/components/Editor/EditorContent/EditorContent"; @@ -9,38 +9,11 @@ import EditorContent from "@/components/Editor/EditorContent/EditorContent"; */ export default function EditorSection() { const editorSectionRef = useRef(null); - const [toolbarTop, setToolbarTop] = useState(487); - - useEffect(() => { - /** - * 스크롤 이벤트 핸들러 - * 에디터 섹션의 위치에 따라 툴바의 위치를 동적으로 조정 - */ - const handleScroll = () => { - if (editorSectionRef.current) { - const rect = editorSectionRef.current.getBoundingClientRect(); - - if (rect.top > 0) { - setToolbarTop(rect.top + 40); - } - - if (rect.top <= 0) { - setToolbarTop(40); - } - } - }; - - window.addEventListener("scroll", handleScroll); - - return () => { - window.removeEventListener("scroll", handleScroll); - }; - }, []); return ( - + ); } diff --git a/src/components/Editor/EditorToolModal/EditorToolModal.tsx b/src/components/Editor/EditorToolModal/EditorToolModal.tsx index d40fdaa..5dd7b41 100644 --- a/src/components/Editor/EditorToolModal/EditorToolModal.tsx +++ b/src/components/Editor/EditorToolModal/EditorToolModal.tsx @@ -13,7 +13,8 @@ interface Props { * 이모지, 구분선, 장소 등의 추가 옵션을 제공하는 모달 창을 관리 */ export default function EditorToolModal({ top, children }: Props) { - const { activeModal, closeModal } = useEditorStore(); + const activeModal = useEditorStore((state) => state.activeModal); + const closeModal = useEditorStore((state) => state.closeModal); /** * 모달 외부 클릭 감지 훅 사용 @@ -29,6 +30,8 @@ export default function EditorToolModal({ top, children }: Props) { } ); + if (!activeModal) return null; + return ( {children} diff --git a/src/components/Editor/EditorToolModal/EmojiModal/EmojiModal.tsx b/src/components/Editor/EditorToolModal/EmojiModal/EmojiModal.tsx index 3d63c53..f9a4216 100644 --- a/src/components/Editor/EditorToolModal/EmojiModal/EmojiModal.tsx +++ b/src/components/Editor/EditorToolModal/EmojiModal/EmojiModal.tsx @@ -18,7 +18,8 @@ export default function EmojiModal({ addBlock }: EmojiIconProps) { const [page, setPage] = useState(0); const ITEMS_PER_PAGE = 150; - const { closeModal } = useEditorStore(); + const activeModal = useEditorStore((state) => state.activeModal); + const closeModal = useEditorStore((state) => state.closeModal); const handleEmojiClick = (emojiData: Emoji) => { addBlock("emoji", { @@ -36,6 +37,8 @@ export default function EmojiModal({ addBlock }: EmojiIconProps) { (page + 1) * ITEMS_PER_PAGE ); + if (activeModal !== "emoji") return null; + return ( diff --git a/src/components/Editor/EditorToolModal/LineModal/LineModal.tsx b/src/components/Editor/EditorToolModal/LineModal/LineModal.tsx index d1a2a67..78b271a 100644 --- a/src/components/Editor/EditorToolModal/LineModal/LineModal.tsx +++ b/src/components/Editor/EditorToolModal/LineModal/LineModal.tsx @@ -12,7 +12,8 @@ interface LineIconProps { * 다양한 스타일의 구분선을 제공하고 선택한 구분선을 에디터에 추가 */ export default function LineModal({ addBlock }: LineIconProps) { - const { closeModal } = useEditorStore(); + const activeModal = useEditorStore((state) => state.activeModal); + const closeModal = useEditorStore((state) => state.closeModal); const handleLineClick = (line: Line) => { const lineData = { @@ -23,6 +24,8 @@ export default function LineModal({ addBlock }: LineIconProps) { closeModal(); }; + if (activeModal !== "line") return null; + return ( {LineData.map((line, index) => ( diff --git a/src/components/Editor/EditorToolModal/PlaceModal/PlaceModal.tsx b/src/components/Editor/EditorToolModal/PlaceModal/PlaceModal.tsx index 8dacbaa..b79f983 100644 --- a/src/components/Editor/EditorToolModal/PlaceModal/PlaceModal.tsx +++ b/src/components/Editor/EditorToolModal/PlaceModal/PlaceModal.tsx @@ -18,7 +18,8 @@ export default function PlaceModal({ addBlock }: PlaceIconProps) { { name: string; id: string; address: string; url: string }[] >([]); - const { closeModal } = useEditorStore(); + const activeModal = useEditorStore((state) => state.activeModal); + const closeModal = useEditorStore((state) => state.closeModal); /** * 장소 검색 처리 함수 @@ -63,6 +64,8 @@ export default function PlaceModal({ addBlock }: PlaceIconProps) { handleSearch(searchTerm); }, [searchTerm]); + if (activeModal !== "place") return null; + return ( diff --git a/src/components/Editor/EditorToolbar/EditorToolbar.tsx b/src/components/Editor/EditorToolbar/EditorToolbar.tsx index fb15617..c20c471 100644 --- a/src/components/Editor/EditorToolbar/EditorToolbar.tsx +++ b/src/components/Editor/EditorToolbar/EditorToolbar.tsx @@ -18,18 +18,24 @@ import { import FixedToolbar from "@/components/Common/FixedToolbar/FixedToolbar"; import useEditorStore from "@/store/useEditorStore"; +import { RefObject, useEffect, useState } from "react"; interface Props { - toolbarTop: number; + editorSectionRef: RefObject; } /** * 에디터의 툴바 컴포넌트 * 블록을 추가할 수 있는 도구들을 제공 */ -export default function EditorToolbar({ toolbarTop }: Props) { - const { editor, activeModal, currentBlockIndex, setCurrentBlockIndex } = - useEditorStore(); +export default function EditorToolbar({ editorSectionRef }: Props) { + const [toolbarTop, setToolbarTop] = useState(487); + + const editor = useEditorStore((state) => state.editor); + const currentBlockIndex = useEditorStore((state) => state.currentBlockIndex); + const setCurrentBlockIndex = useEditorStore( + (state) => state.setCurrentBlockIndex + ); /** * 현재 블록의 인덱스를 처리하는 함수 @@ -53,6 +59,7 @@ export default function EditorToolbar({ toolbarTop }: Props) { const shouldUseFirstBlock = firstBlock?.name === "paragraph" && firstBlock.isEmpty; setCurrentBlockIndex(shouldUseFirstBlock ? 0 : 1); + return; } @@ -80,15 +87,39 @@ export default function EditorToolbar({ toolbarTop }: Props) { } }; + useEffect(() => { + /** + * 스크롤 이벤트 핸들러 + * 에디터 섹션의 위치에 따라 툴바의 위치를 동적으로 조정 + */ + const handleScroll = () => { + if (editorSectionRef.current) { + const rect = editorSectionRef.current.getBoundingClientRect(); + + if (rect.top > 0) { + setToolbarTop(rect.top + 40); + } + + if (rect.top <= 0) { + setToolbarTop(40); + } + } + }; + + window.addEventListener("scroll", handleScroll); + + return () => { + window.removeEventListener("scroll", handleScroll); + }; + }, []); + return ( <> - {activeModal && ( - - {activeModal === "place" && } - {activeModal === "emoji" && } - {activeModal === "line" && } - - )} + + + + + state.setSubtitleText); - const titleImage = useTitleStore((state) => state.titleCoverImage); - const titleCoverColor = useTitleStore((state) => state.titleCoverColor); + const hasTitleBackground = useTitleStore((state) => state.hasTitleBackground); return ( ` + display: flex; + flex-direction: column; + gap: 16px; + position: absolute; + left: 0; + width: 100%; + z-index: 100; + transition: all ease-in-out 0.2s; + + ${({ $align, $hasBackground }) => + $align === "bottom" && + !$hasBackground && + ` + bottom: 50px; + + + `} + + ${({ $align, $hasBackground }) => + $align === "bottom" && + $hasBackground && + ` + bottom: 70px; + + + `} + + ${({ $align }) => + $align === "center" && + ` + bottom: 50%; + text-align: center; + + `} +`; diff --git a/src/components/Title/TitleInput/TitleInputWrapper/TitleInputContainer/TitleInputContainer.tsx b/src/components/Title/TitleInput/TitleInputWrapper/TitleInputContainer/TitleInputContainer.tsx new file mode 100644 index 0000000..e0d8bda --- /dev/null +++ b/src/components/Title/TitleInput/TitleInputWrapper/TitleInputContainer/TitleInputContainer.tsx @@ -0,0 +1,20 @@ +import { ReactNode } from "react"; +import * as S from "./TitleInputContainer.style"; +import useTitleStore from "@/store/useTitleStore"; + +function TitleInputContainer({ children }: { children: ReactNode }) { + const hasTitleBackground = useTitleStore((state) => state.hasTitleBackground); + + const titleAlign = useTitleStore((state) => state.alignment); + + return ( + + {children} + + ); +} + +export default TitleInputContainer; diff --git a/src/components/Title/TitleInput/TitleInputWrapper/TitleInputWrapper.tsx b/src/components/Title/TitleInput/TitleInputWrapper/TitleInputWrapper.tsx index 546aae7..cea260c 100644 --- a/src/components/Title/TitleInput/TitleInputWrapper/TitleInputWrapper.tsx +++ b/src/components/Title/TitleInput/TitleInputWrapper/TitleInputWrapper.tsx @@ -1,25 +1,16 @@ -import * as S from "./TitleInputWrapper.style"; import TitleTextInput from "@/components/Title/TitleInput/TitleTextInput/TitleTextInput"; import SubtitleTextInput from "@/components/Title/TitleInput/SubtitleTextInput/SubtitleTextInput"; - -import useTitleStore from "@/store/useTitleStore"; +import TitleInputContainer from "@/components/Title/TitleInput/TitleInputWrapper/TitleInputContainer/TitleInputContainer"; /** * 제목과 부제목 입력 필드를 감싸는 컨테이너 컴포넌트 * 배경 유무와 정렬 상태에 따라 스타일이 변경됨 */ export default function TitleInputWrapper() { - const titleImage = useTitleStore((state) => state.titleCoverImage); - const titleCoverColor = useTitleStore((state) => state.titleCoverColor); - const titleAlign = useTitleStore((state) => state.alignment); - return ( - + - + ); } diff --git a/src/components/Title/TitleInput/TitleTextInput/TitleTextInput.tsx b/src/components/Title/TitleInput/TitleTextInput/TitleTextInput.tsx index 1b523df..0063fcc 100644 --- a/src/components/Title/TitleInput/TitleTextInput/TitleTextInput.tsx +++ b/src/components/Title/TitleInput/TitleTextInput/TitleTextInput.tsx @@ -17,8 +17,7 @@ import useTitleStore from "@/store/useTitleStore"; */ export default function TitleTextInput() { const setTitleText = useTitleStore((state) => state.setTitleText); - const titleImage = useTitleStore((state) => state.titleCoverImage); - const titleCoverColor = useTitleStore((state) => state.titleCoverColor); + const hasTitleBackground = useTitleStore((state) => state.hasTitleBackground); const titleColor = useTitleStore((state) => state.titleColor); const [isTooltipVisible, setTooltipVisible] = useState(false); @@ -110,17 +109,17 @@ export default function TitleTextInput() { fontColor={ titleColor ? titleColor - : titleImage || titleCoverColor + : hasTitleBackground ? COMMON_THEME.white_primary : COMMON_THEME.black_primary } placeholderColor={ - titleCoverColor + hasTitleBackground ? COMMON_THEME.white_primary : COMMON_THEME.gray_primary } cursorColor={ - titleImage || titleCoverColor + hasTitleBackground ? COMMON_THEME.white_primary : COMMON_THEME.black_primary } @@ -136,7 +135,7 @@ export default function TitleTextInput() { isOpen={isFontFamilyOpen} onToggle={toggleFontFamilyTooltip} /> - {!titleImage && !titleCoverColor && ( + {!hasTitleBackground && ( ` + width: 100%; + height: ${({ $expanded }) => ($expanded ? "100vh" : "450px")}; + border-bottom: 1px solid ${COMMON_THEME.light_gray}; + background-color: ${({ $bgColor }) => $bgColor || "trasnparent"}; + background-image: ${({ $bgImage }) => + $bgImage ? `url(${$bgImage})` : "none"}; + background-size: cover; + background-position: center; + position: relative; + transition: all ease-in-out 0.2s; + ${({ $bgImage }) => + $bgImage && + ` + &::before { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.3); + z-index: 1; + } + `}; +`; diff --git a/src/components/Title/TitleSection/TitleBackground/TitleBackground.tsx b/src/components/Title/TitleSection/TitleBackground/TitleBackground.tsx new file mode 100644 index 0000000..bb2db51 --- /dev/null +++ b/src/components/Title/TitleSection/TitleBackground/TitleBackground.tsx @@ -0,0 +1,20 @@ +import * as S from "./TitleBackground.style"; +import useTitleStore from "@/store/useTitleStore"; + +function TitleBackground({ children }: { children: React.ReactNode }) { + const titleCoverImage = useTitleStore((state) => state.titleCoverImage); + const isExpanded = useTitleStore((state) => state.isExpanded); + const titleCoverColor = useTitleStore((state) => state.titleCoverColor); + + return ( + + {children} + + ); +} + +export default TitleBackground; diff --git a/src/components/Title/TitleSection/TitleSection.tsx b/src/components/Title/TitleSection/TitleSection.tsx index 89d07d8..8637f50 100644 --- a/src/components/Title/TitleSection/TitleSection.tsx +++ b/src/components/Title/TitleSection/TitleSection.tsx @@ -5,39 +5,30 @@ import TitleCoverColorSwiper from "@/components/Title/TitleTools/TitleCoverColor import useTitleStore from "@/store/useTitleStore"; import useEditorStore from "@/store/useEditorStore"; +import TitleBackground from "@/components/Title/TitleSection/TitleBackground/TitleBackground"; /** * 글의 제목 섹션을 담당하는 컴포넌트 * 제목, 부제목, 커버 이미지/컬러 등을 관리 */ -export default function TitleSection() { - // 제목 관련 상태값들을 전역 상태에서 가져옴 - const { - titleText, - subtitleText, - titleCoverImage, - titleCoverColor, - isExpanded, - alignment, - titleFont, - titleColor, - } = useTitleStore(); - const { editor } = useEditorStore(); - +function TitleSection() { /** * 저장 버튼 클릭 핸들러 * Editor.js의 데이터와 제목 섹션의 데이터를 통합하여 저장 */ const onClickSave = () => { + const titleState = useTitleStore.getState(); + const editor = useEditorStore.getState().editor; + const titleData = { - titleText: titleText, - subtitleText: subtitleText, - titleCoverImage: titleCoverImage, - imageExpanded: isExpanded, - titleCoverColor: titleCoverColor, - titleAlignment: alignment, - titleFont: titleFont, - titleColor: titleColor, + titleText: titleState.titleText, + subtitleText: titleState.subtitleText, + titleCoverImage: titleState.titleCoverImage, + imageExpanded: titleState.isExpanded, + titleCoverColor: titleState.titleCoverColor, + titleAlignment: titleState.alignment, + titleFont: titleState.titleFont, + titleColor: titleState.titleColor, }; // Editor.js의 save 메서드를 호출하여 에디터 데이터와 제목 데이터를 통합 @@ -50,11 +41,7 @@ export default function TitleSection() { }; return ( - + {/* 상단 메뉴바 및 저장 버튼 */} @@ -69,8 +56,10 @@ export default function TitleSection() { {/* 제목 입력 및 커버 이미지/컬러 선택 영역 */} - {titleCoverColor && } + - + ); } + +export default TitleSection; diff --git a/src/components/Title/TitleToolbar/TitleToolbar.tsx b/src/components/Title/TitleToolbar/TitleToolbar.tsx index ab83b33..df27827 100644 --- a/src/components/Title/TitleToolbar/TitleToolbar.tsx +++ b/src/components/Title/TitleToolbar/TitleToolbar.tsx @@ -4,28 +4,24 @@ import TitleCoverImageActiveTool from "@/components/Title/TitleTools/TitleCoverI import TitleCoverColorIcon from "components/Title/TitleTools/TitleCoverColor/TitleCoverColorIcon/TitleCoverColorIcon"; import TitleAlignTool from "components/Title/TitleTools/TitleAlignTool/TitleAlignTool"; -import useTitleStore from "@/store/useTitleStore"; - /** * 제목 섹션의 도구 모음 컴포넌트 * 커버 이미지, 커버 컬러, 정렬 등의 도구들을 포함 */ export default function TitleToolbar() { - const titleImage = useTitleStore((state) => state.titleCoverImage); - return ( {/* 커버 이미지 업로드 도구 */} {/* 커버 이미지가 없을 때만 커버 컬러 선택 도구 표시 */} - {!titleImage && } + {/* 제목 텍스트 정렬 도구 */} {/* 커버 이미지가 있을 때만 이미지 관련 추가 도구 표시 */} - {titleImage && } + ); } diff --git a/src/components/Title/TitleTools/TitleAlignTool/TitleAlignTool.tsx b/src/components/Title/TitleTools/TitleAlignTool/TitleAlignTool.tsx index f616464..9540577 100644 --- a/src/components/Title/TitleTools/TitleAlignTool/TitleAlignTool.tsx +++ b/src/components/Title/TitleTools/TitleAlignTool/TitleAlignTool.tsx @@ -7,8 +7,7 @@ import useTitleStore from "@/store/useTitleStore"; * 제목 텍스트의 수직 정렬(하단/중앙)을 토글하는 기능 제공 */ export default function TitleAlignTool() { - const titleCoverImage = useTitleStore((state) => state.titleCoverImage); - const titleCoverColor = useTitleStore((state) => state.titleCoverColor); + const hasTitleBackground = useTitleStore((state) => state.hasTitleBackground); const titleAlign = useTitleStore((state) => state.alignment); const setTitleAlign = useTitleStore((state) => state.setAlignment); @@ -21,13 +20,13 @@ export default function TitleAlignTool() { {titleAlign === "bottom" && ( handleTitleAlign("center")} - $hasCoverBg={!!titleCoverImage || !!titleCoverColor} + $hasCoverBg={hasTitleBackground} /> )} {titleAlign === "center" && ( handleTitleAlign("bottom")} - $hasCoverBg={!!titleCoverImage || !!titleCoverColor} + $hasCoverBg={hasTitleBackground} /> )} diff --git a/src/components/Title/TitleTools/TitleCoverColor/TitleCoverColorIcon/TitleCoverColorIcon.tsx b/src/components/Title/TitleTools/TitleCoverColor/TitleCoverColorIcon/TitleCoverColorIcon.tsx index 40ecb83..7435cde 100644 --- a/src/components/Title/TitleTools/TitleCoverColor/TitleCoverColorIcon/TitleCoverColorIcon.tsx +++ b/src/components/Title/TitleTools/TitleCoverColor/TitleCoverColorIcon/TitleCoverColorIcon.tsx @@ -7,7 +7,9 @@ import { TITLE_COVER_COLORS } from "@/styles/Theme"; * 커버 컬러의 활성화/비활성화를 담당 */ export default function TitleCoverColorIcon() { - const titleCoverColor = useTitleStore((state) => state.titleCoverColor); + const titleImage = useTitleStore((state) => state.titleCoverImage); + const hasTitleBackground = useTitleStore((state) => state.hasTitleBackground); + const setTitleCoverColor = useTitleStore((state) => state.setTitleCoverColor); const setTitleColor = useTitleStore((state) => state.setTitleColor); @@ -18,15 +20,18 @@ export default function TitleCoverColorIcon() { * - 커버 컬러 변경 시 제목 텍스트 컬러는 초기화 */ const toggleTitleCoverColor = () => { - if (titleCoverColor) setTitleCoverColor(null); - if (!titleCoverColor) setTitleCoverColor(TITLE_COVER_COLORS.red); + if (hasTitleBackground) setTitleCoverColor(null); + if (!hasTitleBackground) setTitleCoverColor(TITLE_COVER_COLORS.red); setTitleColor(null); }; + + if (titleImage) return null; + return ( ); } diff --git a/src/components/Title/TitleTools/TitleCoverColor/TitleCoverColorSwiper/TitleCoverColorSwiper.tsx b/src/components/Title/TitleTools/TitleCoverColor/TitleCoverColorSwiper/TitleCoverColorSwiper.tsx index 242cf45..1503a5d 100644 --- a/src/components/Title/TitleTools/TitleCoverColor/TitleCoverColorSwiper/TitleCoverColorSwiper.tsx +++ b/src/components/Title/TitleTools/TitleCoverColor/TitleCoverColorSwiper/TitleCoverColorSwiper.tsx @@ -7,13 +7,13 @@ import { TITLE_COVER_COLORS } from "@/styles/Theme"; * 색상 원형 버튼들을 나열하고 좌우 버튼으로 색상 변경 가능 */ const TitleCoverColorSwiper = () => { - const currentColor = useTitleStore((state) => state.titleCoverColor); + const titleCoverColor = useTitleStore((state) => state.titleCoverColor); const setTitleCoverColor = useTitleStore((state) => state.setTitleCoverColor); const colorKeys = Object.keys(TITLE_COVER_COLORS); const currentIndex = colorKeys.indexOf( Object.keys(TITLE_COVER_COLORS).find( - (key) => TITLE_COVER_COLORS[key] === currentColor + (key) => TITLE_COVER_COLORS[key] === titleCoverColor ) || "" ); @@ -27,6 +27,8 @@ const TitleCoverColorSwiper = () => { setTitleCoverColor(TITLE_COVER_COLORS[colorKeys[prevIndex]]); }; + if (!titleCoverColor) return null; + return ( @@ -37,7 +39,7 @@ const TitleCoverColorSwiper = () => { onClick={() => setTitleCoverColor(TITLE_COVER_COLORS[colorKey])} > diff --git a/src/components/Title/TitleTools/TitleCoverImageActiveTool/TitleCoverImageActiveTool.tsx b/src/components/Title/TitleTools/TitleCoverImageActiveTool/TitleCoverImageActiveTool.tsx index 0b86836..bd53d34 100644 --- a/src/components/Title/TitleTools/TitleCoverImageActiveTool/TitleCoverImageActiveTool.tsx +++ b/src/components/Title/TitleTools/TitleCoverImageActiveTool/TitleCoverImageActiveTool.tsx @@ -6,6 +6,7 @@ import useTitleStore from "@/store/useTitleStore"; * 이미지 확장/축소 및 삭제 기능 제공 */ export default function TitleCoverImageActiveTool() { + const titleImage = useTitleStore((state) => state.titleCoverImage); const setTitleImage = useTitleStore((state) => state.setTitleCoverImage); const setImageExpanded = useTitleStore((state) => state.setIsExpanded); const isTitleImageExpanded = useTitleStore((state) => state.isExpanded); @@ -19,6 +20,8 @@ export default function TitleCoverImageActiveTool() { setImageExpanded(!isTitleImageExpanded); }; + if (!titleImage) return null; + return ( diff --git a/src/components/Title/TitleTools/TitleCoverImageTool/TitleCoverImageTool.tsx b/src/components/Title/TitleTools/TitleCoverImageTool/TitleCoverImageTool.tsx index 740bd9c..68b9a1b 100644 --- a/src/components/Title/TitleTools/TitleCoverImageTool/TitleCoverImageTool.tsx +++ b/src/components/Title/TitleTools/TitleCoverImageTool/TitleCoverImageTool.tsx @@ -8,8 +8,8 @@ import useTitleStore from "@/store/useTitleStore"; */ export default function TitleCoverImageTool() { const fileInputRef = useRef(null); - const titleCoverImage = useTitleStore((state) => state.titleCoverImage); - const titleCoverColor = useTitleStore((state) => state.titleCoverColor); + const hasTitleBackground = useTitleStore((state) => state.hasTitleBackground); + const setTitleImage = useTitleStore((state) => state.setTitleCoverImage); const setTitleColor = useTitleStore((state) => state.setTitleColor); @@ -44,7 +44,7 @@ export default function TitleCoverImageTool() { /> ); diff --git a/src/store/useTitleStore.ts b/src/store/useTitleStore.ts index 4310561..57d02bb 100644 --- a/src/store/useTitleStore.ts +++ b/src/store/useTitleStore.ts @@ -10,6 +10,7 @@ const useTitleStore = create((set) => ({ subtitleText: "", titleCoverImage: null, titleCoverColor: null, + hasTitleBackground: false, isExpanded: false, alignment: "bottom", titleFont: "Noto Sans", @@ -26,11 +27,13 @@ const useTitleStore = create((set) => ({ set({ titleCoverImage: image, titleCoverColor: null, + hasTitleBackground: !!image, }), setTitleCoverColor: (color) => set({ titleCoverColor: color, titleCoverImage: null, + hasTitleBackground: !!color, }), setIsExpanded: (expanded) => set({ isExpanded: expanded }), setAlignment: (alignment) => set({ alignment }), diff --git a/src/types/store/title.types.ts b/src/types/store/title.types.ts index 55241d2..fad2a11 100644 --- a/src/types/store/title.types.ts +++ b/src/types/store/title.types.ts @@ -13,6 +13,7 @@ export interface TitleStore { subtitleText: string; titleCoverImage: string | null; titleCoverColor: string | null; + hasTitleBackground: boolean; isExpanded: boolean; alignment: TitleAlignment; titleFont: TitleFont;