From 3e6594739da1edddea7a0354311f84c93b6fb3c8 Mon Sep 17 00:00:00 2001 From: Edward Kim <65283190+bepyan@users.noreply.github.com> Date: Wed, 21 Aug 2024 03:11:41 +0900 Subject: [PATCH] feat: accordion element (#82) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: placeholder style * feat: add accordion style * feat: accordion element * feat: accordion setting * cleanup * feat: OG 이미지 설정 (#79) * feat: update thumbnail * feat: apply og image * feat: add layout thumbnail * feat: 템플릿의 썸네일이 초기 적용되도록 * feat: 로딩 (#80) * chore: InView with framer-motion * feat: add loading layout * feat: text-effect * feat: global loading * feat: delay create invitation * feat: 저장 중 로딩 * feat: 삭제 토스트 추가 * feat: 저장 버튼 평소 활성화 * feat: OG 이미지 설정 (#79) * feat: update thumbnail * feat: apply og image * feat: add layout thumbnail * feat: 템플릿의 썸네일이 초기 적용되도록 --- .../editor/elements/accordion-element.tsx | 55 ++++++++++ src/components/editor/elements/container.tsx | 30 ++++++ src/components/editor/elements/recursive.tsx | 3 + src/components/editor/placeholders.tsx | 21 ++-- .../accordion-setting.tsx | 102 ++++++++++++++++++ .../sidebar-element-settings-tab/index.tsx | 7 ++ .../editor/sidebar/sidebar-elements-tab.tsx | 7 ++ src/components/editor/type.ts | 7 ++ 8 files changed, 226 insertions(+), 6 deletions(-) create mode 100644 src/components/editor/elements/accordion-element.tsx create mode 100644 src/components/editor/sidebar/sidebar-element-settings-tab/accordion-setting.tsx diff --git a/src/components/editor/elements/accordion-element.tsx b/src/components/editor/elements/accordion-element.tsx new file mode 100644 index 0000000..948ab6f --- /dev/null +++ b/src/components/editor/elements/accordion-element.tsx @@ -0,0 +1,55 @@ +"use client"; + +import { AnimatePresence, motion } from "framer-motion"; +import { ChevronDownIcon } from "lucide-react"; +import { useState } from "react"; +import ElementWrapper from "~/components/editor/elements/element-wrapper"; +import Text from "~/components/editor/elements/text"; +import { useEditor } from "~/components/editor/provider"; +import type { InferEditorElement } from "~/components/editor/type"; + +export default function AccordionElement({ + element, +}: { + element: InferEditorElement<"accordion">; +}) { + const { editor } = useEditor(); + const [isOpen, setIsOpen] = useState( + editor.state.isPreviewMode ? false : true, + ); + + return ( + +
+ + + {isOpen && ( + +
+ +
+
+ )} +
+
+
+ ); +} diff --git a/src/components/editor/elements/container.tsx b/src/components/editor/elements/container.tsx index 55d4478..a392189 100644 --- a/src/components/editor/elements/container.tsx +++ b/src/components/editor/elements/container.tsx @@ -199,6 +199,36 @@ export default function Container({ element }: Props) { }, }); break; + case "accordion": + dispatch({ + type: "ADD_ELEMENT", + payload: { + containerId: id, + elementDetails: { + type: "accordion", + id: nanoid(), + name: "Accordion", + styles: {}, + content: { + triggerText: "제목", + triggerStyle: { + color: "#09090B", + }, + containerStyle: { + backgroundColor: "#F4F4F5", + }, + text: { + type: "text", + id: nanoid(), + name: "Text", + styles: textDefaultStyles, + content: { innerText: "여기에 내용을 입력하세요." }, + }, + }, + }, + }, + }); + break; } }; diff --git a/src/components/editor/elements/recursive.tsx b/src/components/editor/elements/recursive.tsx index ab72b08..983634e 100644 --- a/src/components/editor/elements/recursive.tsx +++ b/src/components/editor/elements/recursive.tsx @@ -1,3 +1,4 @@ +import AccordionElement from "~/components/editor/elements/accordion-element"; import BlankElement from "~/components/editor/elements/blank-element"; import Container from "~/components/editor/elements/container"; import ImageElement from "~/components/editor/elements/image-element"; @@ -25,6 +26,8 @@ export default function Recursive({ element }: { element: EditorElement }) { return ; case "logoBanner": return ; + case "accordion": + return ; default: return null; } diff --git a/src/components/editor/placeholders.tsx b/src/components/editor/placeholders.tsx index 99ab71d..74df29c 100644 --- a/src/components/editor/placeholders.tsx +++ b/src/components/editor/placeholders.tsx @@ -1,5 +1,6 @@ import { BoxSelectIcon, + ChevronsDownUpIcon, ImageIcon, MapIcon, NavigationIcon, @@ -26,7 +27,7 @@ function Placeholder({ type, children, className }: PlaceholderProps) { draggable onDragStart={handleDragStart} className={cn( - "flex h-14 w-14 cursor-grab items-center justify-center gap-1 rounded-lg bg-muted/70 p-2 active:cursor-grabbing", + "flex h-14 w-14 cursor-grab items-center justify-center gap-1 rounded-lg bg-muted/70 p-2 text-muted-foreground active:cursor-grabbing", className, )} > @@ -63,7 +64,7 @@ export function ContainerPlaceholder() { export function ImagePlaceholder() { return ( - {" "} + ); } @@ -71,7 +72,7 @@ export function ImagePlaceholder() { export function NavigationPlaceholder() { return ( - + ); } @@ -79,7 +80,7 @@ export function NavigationPlaceholder() { export function KakaoMapPlaceholder() { return ( - + ); } @@ -87,7 +88,7 @@ export function KakaoMapPlaceholder() { export function BlankPlaceholder() { return ( - + ); } @@ -95,7 +96,15 @@ export function BlankPlaceholder() { export function LogoBannerPlaceholder() { return ( - + + + ); +} + +export function AccordionPlaceholder() { + return ( + + ); } diff --git a/src/components/editor/sidebar/sidebar-element-settings-tab/accordion-setting.tsx b/src/components/editor/sidebar/sidebar-element-settings-tab/accordion-setting.tsx new file mode 100644 index 0000000..33c53ba --- /dev/null +++ b/src/components/editor/sidebar/sidebar-element-settings-tab/accordion-setting.tsx @@ -0,0 +1,102 @@ +"use client"; + +import { useEditor } from "~/components/editor/provider"; +import type { InferEditorElement } from "~/components/editor/type"; +import { EditorInput } from "~/components/editor/ui/input"; + +export default function AccordionSetting() { + const { editor, dispatch } = useEditor(); + const element = editor.state + .selectedElement as InferEditorElement<"accordion">; + + const update = ( + content: Partial["content"]>, + ) => { + dispatch({ + type: "UPDATE_ELEMENT", + payload: { + elementDetails: { + ...element, + content: { + ...element.content, + ...content, + }, + }, + }, + }); + }; + + return ( +
+
+ { + if (!e.target.value) { + return; + } + + update({ + triggerText: e.target.value, + }); + }} + componentPrefix={제목} + /> +
+
+ { + update({ + triggerStyle: { + ...element.content.triggerStyle, + color: e.target.value, + }, + }); + }} + componentPrefix={ +
+ 제목 색상 +
+
+ } + /> +
+
+ { + update({ + containerStyle: { + ...element.content.containerStyle, + backgroundColor: e.target.value, + }, + }); + }} + componentPrefix={ +
+ 배경 색상 +
+
+ } + /> +
+
+ ); +} diff --git a/src/components/editor/sidebar/sidebar-element-settings-tab/index.tsx b/src/components/editor/sidebar/sidebar-element-settings-tab/index.tsx index ab6e0dd..4ced45b 100644 --- a/src/components/editor/sidebar/sidebar-element-settings-tab/index.tsx +++ b/src/components/editor/sidebar/sidebar-element-settings-tab/index.tsx @@ -1,6 +1,7 @@ "use client"; import { useEditor } from "~/components/editor/provider"; +import AccordionSetting from "~/components/editor/sidebar/sidebar-element-settings-tab/accordion-setting"; import BackgroundSetting from "~/components/editor/sidebar/sidebar-element-settings-tab/background-setting"; import BorderSetting from "~/components/editor/sidebar/sidebar-element-settings-tab/border-setting"; import ImageSetting from "~/components/editor/sidebar/sidebar-element-settings-tab/image-setting"; @@ -71,6 +72,12 @@ export default function SidebarElementSettingsTab(props: Props) { )} + + {selectedElement.type === "accordion" && ( + <> + + + )}
); diff --git a/src/components/editor/sidebar/sidebar-elements-tab.tsx b/src/components/editor/sidebar/sidebar-elements-tab.tsx index 2187c73..bb589f8 100644 --- a/src/components/editor/sidebar/sidebar-elements-tab.tsx +++ b/src/components/editor/sidebar/sidebar-elements-tab.tsx @@ -1,5 +1,6 @@ import React from "react"; import { + AccordionPlaceholder, BlankPlaceholder, ContainerPlaceholder, ImagePlaceholder, @@ -79,6 +80,12 @@ export default function SidebarElementsTab(props: Props) { Component: , group: "elements", }, + { + id: "accordion", + label: "Accordion", + Component: , + group: "elements", + }, ]; return ( diff --git a/src/components/editor/type.ts b/src/components/editor/type.ts index 6573121..dc8a83f 100644 --- a/src/components/editor/type.ts +++ b/src/components/editor/type.ts @@ -24,6 +24,13 @@ type EditorElementContentMap = { blank: {}; empty: {}; logoBanner: {}; + accordion: { + triggerText?: string; + triggerStyle?: React.CSSProperties; + containerStyle?: React.CSSProperties; + contentStyle?: React.CSSProperties; + text: InferEditorElement<"text">; + }; }; export type EditorElementType = keyof EditorElementContentMap;