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;