-
-
-
-
+ {isTemplatesOpen && (
+
+
+
히어로 · CTA
+
+
+
+
+ 페이지 상단 Hero 섹션 (큰 제목 + 서브텍스트 + 버튼)
+
+
+
+
+
+
+
+
+
+
+
신뢰/소개
+
+
+
+
고객 후기(Testimonials) 섹션
+
+
+
+
+
+
+
-
-
-
-
콘텐츠 섹션
-
-
-
-
-
-
-
3컬럼 기능 소개 섹션
-
-
-
-
-
-
-
-
-
-
-
-
신뢰/소개
-
-
-
-
-
-
-
고객 후기(Testimonials) 섹션
-
-
-
-
-
-
-
+ )}
);
diff --git a/src/app/editor/panels/PropertiesSidebar.tsx b/src/app/editor/panels/PropertiesSidebar.tsx
index f7b3d0e..2b514d9 100644
--- a/src/app/editor/panels/PropertiesSidebar.tsx
+++ b/src/app/editor/panels/PropertiesSidebar.tsx
@@ -1,5 +1,6 @@
"use client";
+import { useState } from "react";
import type { Block, ButtonBlockProps, FormBlockProps, ListBlockProps, SectionBlockProps, TextBlockProps, VideoBlockProps } from "@/features/editor/state/editorStore";
import { ButtonPropertiesPanel } from "./ButtonPropertiesPanel";
import { TextPropertiesPanel } from "./TextPropertiesPanel";
@@ -14,6 +15,18 @@ import { FormCheckboxPropertiesPanel } from "../forms/FormCheckboxPropertiesPane
import { FormRadioPropertiesPanel } from "../forms/FormRadioPropertiesPanel";
import { FormControllerPanel } from "../forms/FormControllerPanel";
import { ProjectPropertiesPanel } from "./ProjectPropertiesPanel";
+import { Trash2, Copy, SlidersHorizontal, HelpCircle } from "lucide-react";
+
+type BlockHelpProperty = {
+ label: string;
+ description: string;
+};
+
+type BlockHelpContent = {
+ title: string;
+ description: string;
+ properties?: BlockHelpProperty[];
+};
interface PropertiesSidebarProps {
blocks: Block[];
@@ -48,16 +61,621 @@ export function PropertiesSidebar(props: PropertiesSidebarProps) {
onOutdentSelectedItem,
} = props;
+ const [helpOpen, setHelpOpen] = useState(false);
+
+ const getHelpContentForSelectedBlock = (): BlockHelpContent | null => {
+ if (!selectedBlockId) return null;
+ const selectedBlock = blocks.find((b) => b.id === selectedBlockId);
+ if (!selectedBlock) return null;
+
+ switch (selectedBlock.type) {
+ case "text":
+ return {
+ title: "텍스트 블록 튜토리얼",
+ description:
+ "제목과 본문 텍스트를 입력할 때 사용하는 기본 블록입니다.\n\n좌측 패널에서 텍스트를 추가한 뒤, 캔버스에서 텍스트를 더블클릭하거나 속성 패널에서 내용을 수정해 보세요. 정렬, 크기, 색상 등을 조절해 다양한 스타일의 텍스트를 만들 수 있습니다.",
+ properties: [
+ {
+ label: "선택한 텍스트 블록 내용",
+ description:
+ "이 블록에 실제로 표시될 문장을 입력하는 영역입니다. 캔버스에서 텍스트를 더블클릭했을 때와 동일한 내용이며, 여러 줄을 입력하면 줄바꿈이 그대로 반영됩니다.",
+ },
+ {
+ label: "정렬",
+ description:
+ "텍스트를 왼쪽/가운데/오른쪽 중 어디에 맞출지 결정합니다. 일반 본문은 왼쪽, Hero 제목이나 짧은 강조 문구는 가운데 정렬을 추천합니다.",
+ },
+ {
+ label: "텍스트 스타일 (밑줄/가운데줄/이탤릭)",
+ description:
+ "밑줄은 링크처럼 보이게 하거나 특정 단어를 강조할 때, 가운데줄은 할인 전 가격처럼 취소선을 표현할 때, 이탤릭은 인용구나 제품명 등 살짝 톤을 바꾸고 싶을 때 사용합니다.",
+ },
+ {
+ label: "글자 크기",
+ description:
+ "텍스트의 폰트 크기를 px 단위로 조절합니다. 프리셋(XS~3XL)으로 대략적인 크기를 고른 뒤, 슬라이더/숫자 입력으로 세밀하게 조정할 수 있습니다.",
+ },
+ {
+ label: "글자 간격",
+ description:
+ "문자 사이의 간격(자간)을 조절합니다. 본문은 보통 또는 약간 넓게, 대문자 위주의 짧은 타이틀은 살짝 넓게 설정하면 가독성과 디자인이 좋아집니다.",
+ },
+ {
+ label: "줄 간격",
+ description:
+ "행과 행 사이의 간격(행간)을 정합니다. 본문은 1.5~1.7 정도가 읽기 좋고, 아주 짧은 제목은 1.25 정도로 줄이면 한 덩어리로 단단해 보입니다.",
+ },
+ {
+ label: "굵기",
+ description:
+ "폰트 두께를 100~900 범위에서 조절합니다. 본문은 보통(400), 섹션 제목은 세미볼드(600), 강한 CTA 문구는 볼드(700) 정도를 추천합니다.",
+ },
+ {
+ label: "텍스트 색상",
+ description:
+ "글자 색을 팔레트 또는 HEX 코드로 지정합니다. 본문은 대비가 높은 짙은 색을, 강조 문구는 브랜드 메인 색을 사용하는 것이 좋습니다.",
+ },
+ {
+ label: "블록 배경색",
+ description:
+ "텍스트가 들어 있는 카드/박스 전체 배경색을 지정합니다. 공지사항, 강조 박스, 경고 문구 등을 만들 때 연한 배경색과 함께 사용하면 좋습니다.",
+ },
+ {
+ label: "최대 너비",
+ description:
+ "한 줄 텍스트가 지나치게 길어지지 않도록 최대 줄 길이를 제한합니다. `본문 폭(60ch)`는 일반 문단에, `좁게(40ch)`는 카드/배너 같은 짧은 문구에 적합합니다.",
+ },
+ ],
+ };
+ case "button":
+ return {
+ title: "버튼 블록 튜토리얼",
+ description:
+ "폼 제출이나 링크 이동을 위한 CTA 버튼을 만들 때 사용하는 블록입니다. 라벨, 링크(URL), 정렬, 색상/크기를 조절해 원하는 액션 버튼을 구성해 보세요.",
+ properties: [
+ {
+ label: "버튼 텍스트",
+ description:
+ "버튼 위에 표시될 문구입니다. 예: '지금 시작하기', '문의 남기기'. 짧고 행동을 유도하는 문장을 사용하는 것이 좋습니다.",
+ },
+ {
+ label: "가로 패딩 (px)",
+ description:
+ "버튼 양 옆의 여백을 조절합니다. 값이 클수록 버튼이 가로로 넓어져 더 강조됩니다.",
+ },
+ {
+ label: "세로 패딩 (px)",
+ description:
+ "버튼 위·아래 여백을 조절합니다. 값이 클수록 버튼 높이가 높아져 더 눈에 띱니다.",
+ },
+ {
+ label: "버튼 링크",
+ description:
+ "버튼 클릭 시 이동할 URL 또는 앵커(#section)입니다. 외부 페이지, 페이지 내 섹션, 폼 제출 엔드포인트 등으로 연결할 수 있습니다.",
+ },
+ {
+ label: "정렬",
+ description:
+ "해당 버튼이 포함된 영역 안에서 왼쪽/가운데/오른쪽 중 어디에 위치할지 결정합니다. 주요 CTA 버튼은 가운데 정렬이 많이 쓰입니다.",
+ },
+ {
+ label: "텍스트 색상",
+ description:
+ "버튼 라벨 글자 색입니다. 채움 색상과 충분한 대비가 나도록 설정해야 가독성이 좋습니다.",
+ },
+ {
+ label: "스타일",
+ description:
+ "버튼 외형 스타일입니다. '채움'은 꽉 찬 스타일, '외곽선'은 테두리만 있는 스타일, '고스트'는 배경 없이 텍스트/테두리만 있는 스타일입니다.",
+ },
+ {
+ label: "채움 색상",
+ description:
+ "채움 스타일에서 버튼 내부를 채우는 색입니다. 브랜드 메인 색이나 강조 색을 사용하면 좋습니다.",
+ },
+ {
+ label: "외곽선 색상",
+ description:
+ "외곽선/고스트 스타일에서 버튼 테두리 색입니다. 배경색과의 대비를 고려해 설정합니다.",
+ },
+ {
+ label: "모서리 둥글기",
+ description:
+ "버튼 모서리를 얼마나 둥글게 처리할지 결정합니다. '없음'은 각진 버튼, '완전 둥글게'는 알약 모양 버튼입니다.",
+ },
+ {
+ label: "버튼 너비 모드 / 버튼 고정 너비",
+ description:
+ "버튼이 컨테이너 너비에 맞춰 늘어날지(전체 폭), 내용 길이에 맞출지(자동), 고정 px 너비를 가질지 결정합니다.",
+ },
+ {
+ label: "버튼 크기",
+ description:
+ "버튼 라벨 텍스트의 폰트 크기입니다. 중요한 CTA 버튼은 주변 텍스트보다 조금 더 크게 설정하면 좋습니다.",
+ },
+ {
+ label: "줄 간격 / 글자 간격",
+ description:
+ "버튼 라벨의 행간과 자간을 조절합니다. 글자가 너무 답답해 보이면 자간을 약간 넓히고, 여러 줄 버튼 문구는 줄 간격을 조금 넓혀 주세요.",
+ },
+ ],
+ };
+ case "image":
+ return {
+ title: "이미지 블록 튜토리얼",
+ description:
+ "배너, 썸네일, 설명 이미지를 배치할 때 사용하는 블록입니다. 외부 이미지 URL을 입력하거나 업로드 이미지를 선택하고, 너비/정렬/모서리 둥글기를 조절해 레이아웃에 맞게 배치해 보세요.",
+ properties: [
+ {
+ label: "이미지 소스",
+ description:
+ "이미지를 외부 URL에서 가져올지(URL), 빌더에 업로드한 에셋을 사용할지(파일 업로드) 선택합니다.",
+ },
+ {
+ label: "이미지 URL / 이미지 파일 업로드",
+ description:
+ "URL 모드에서는 외부 이미지 주소를 입력하고, 업로드 모드에서는 로컬 이미지를 업로드해 `/api/image/:id` 형식으로 관리합니다.",
+ },
+ {
+ label: "대체 텍스트",
+ description:
+ "이미지가 로드되지 않거나 스크린리더를 사용하는 사용자에게 보여질 설명 텍스트입니다. 이미지가 전달하는 의미를 한두 문장으로 작성해 주세요.",
+ },
+ {
+ label: "카드 배경색",
+ description:
+ "이미지를 감싸는 카드 영역의 배경색입니다. 투명한 PNG 아이콘이나 로고를 올릴 때 배경을 살짝 깔아주면 더 잘 보입니다.",
+ },
+ {
+ label: "정렬",
+ description:
+ "이미지가 포함된 영역 안에서 왼쪽/가운데/오른쪽 중 어디에 위치할지 결정합니다.",
+ },
+ {
+ label: "너비 모드 / 고정 너비 (px)",
+ description:
+ "이미지를 내용 크기에 맞출지(auto) 또는 px 단위로 고정된 너비를 사용할지 선택합니다. 썸네일 그리드에서는 고정 너비를 사용하는 편이 레이아웃이 안정적입니다.",
+ },
+ {
+ label: "모서리 둥글기",
+ description:
+ "이미지 카드 모서리 둥글기를 px 단위로 조절합니다. 아바타/아이콘은 완전 둥글게, 일반 사진은 살짝 둥글게 설정하면 자연스럽습니다.",
+ },
+ ],
+ };
+ case "list":
+ return {
+ title: "리스트 블록 튜토리얼",
+ description:
+ "불릿/번호 리스트를 만들 때 사용하는 블록입니다. 아이템 텍스트를 수정하고, 정렬/불릿 스타일을 바꿔 체크리스트나 단계별 안내 등을 표현할 수 있습니다.",
+ properties: [
+ {
+ label: "리스트 아이템 (줄바꿈으로 구분)",
+ description:
+ "각 줄이 하나의 리스트 항목이 됩니다. 들여쓰기를 이용한 중첩 리스트는 TDD 기준의 변환 로직에 따라 자동으로 트리 구조로 변환됩니다.",
+ },
+ {
+ label: "정렬",
+ description:
+ "리스트 전체를 왼쪽/가운데/오른쪽 중 어디에 정렬할지 결정합니다. 체크리스트는 왼쪽 정렬, 특징 요약은 가운데 정렬이 자주 사용됩니다.",
+ },
+ {
+ label: "글자 크기 (px)",
+ description:
+ "리스트 텍스트의 폰트 크기를 조절합니다. 본문보다 약간 작게 설정하면 보조 정보 느낌을 줄 수 있습니다.",
+ },
+ {
+ label: "줄 간격",
+ description:
+ "리스트 항목 내부의 행간을 조절합니다. 항목 내용이 길어질수록 1.5~1.8 정도의 넉넉한 값을 추천합니다.",
+ },
+ {
+ label: "텍스트 색상",
+ description:
+ "리스트 텍스트의 색상입니다. 배경색과의 대비를 고려해 본문과 동일하거나 약간 연한 색상을 사용할 수 있습니다.",
+ },
+ {
+ label: "블록 배경색",
+ description:
+ "리스트 전체 카드의 배경색입니다. 단계별 안내나 체크리스트 박스를 강조하는 용도로 사용할 수 있습니다.",
+ },
+ {
+ label: "불릿 스타일",
+ description:
+ "불릿(●/○/■) 또는 번호(1., a., i.) 형식을 선택합니다. 숫자/알파벳/로마 숫자 스타일을 선택하면 자동으로 순서형 리스트(ordered)가 됩니다.",
+ },
+ {
+ label: "아이템 간 여백 (px)",
+ description:
+ "각 리스트 항목 사이의 세로 간격입니다. 설명이 긴 항목이 많다면 여백을 넉넉히 두어 가독성을 확보하세요.",
+ },
+ ],
+ };
+ case "divider":
+ return {
+ title: "구분선 블록 튜토리얼",
+ description:
+ "섹션과 섹션 사이를 나누거나 콘텐츠를 시각적으로 구분할 때 사용하는 블록입니다. 정렬, 두께, 길이, 색상, 여백을 조절해 페이지 흐름을 정리해 보세요.",
+ properties: [
+ {
+ label: "정렬",
+ description:
+ "구분선을 컨테이너 안에서 왼쪽/가운데/오른쪽 중 어디에 위치시킬지 결정합니다.",
+ },
+ {
+ label: "두께",
+ description:
+ "선의 두께입니다. '얇게'는 가벼운 보조 구분선, '보통'은 섹션 경계를 확실히 나눌 때 사용합니다.",
+ },
+ {
+ label: "길이 모드 / 고정 길이 (px)",
+ description:
+ "구분선을 전체 폭으로 쓸지, 내용에 맞출지, 또는 px 단위의 고정 길이를 사용할지 선택합니다.",
+ },
+ {
+ label: "선 색상",
+ description:
+ "구분선 컬러입니다. 너무 진한 색보다는 섹션 배경보다 살짝 진한 정도의 중간 톤을 추천합니다.",
+ },
+ {
+ label: "위/아래 여백",
+ description:
+ "구분선 위·아래에 들어가는 공백입니다. 값이 클수록 섹션이 더 명확하게 나뉘어 보입니다.",
+ },
+ ],
+ };
+ case "section":
+ return {
+ title: "섹션 블록 튜토리얼",
+ description:
+ "레이아웃의 큰 덩어리를 나누는 컨테이너 블록입니다. 배경색/배경 이미지/비디오, 위아래 패딩, 너비를 설정해 Hero, Features, Footer 같은 영역을 구성할 수 있습니다.",
+ properties: [
+ {
+ label: "배경 색상",
+ description:
+ "섹션 전체의 기본 배경색입니다. 페이지의 큰 분위기를 결정하는 요소이므로, 섹션 간 배경 대비를 적절히 주는 것이 좋습니다.",
+ },
+ {
+ label: "배경 이미지 소스 / URL / 파일 업로드",
+ description:
+ "섹션 배경으로 사용할 이미지를 외부 URL 또는 업로드 파일로 지정합니다. Hero 배경, 패턴, 질감 이미지를 설정할 때 사용합니다.",
+ },
+ {
+ label: "배경 이미지 크기 / 위치 / 반복",
+ description:
+ "cover/contain/auto로 크기를 조절하고, 프리셋 또는 X/Y 퍼센트로 위치를 조절하며, 반복 여부를 설정해 패턴 형태로 사용할 수 있습니다.",
+ },
+ {
+ label: "배경 비디오 소스 / URL / 파일 업로드",
+ description:
+ "섹션 배경에 비디오를 설정합니다. 시선을 끌어야 하는 Hero 영역 등에 사용하되, 가독성 저하를 막기 위해 텍스트 대비를 꼭 확인하세요.",
+ },
+ {
+ label: "세로 패딩",
+ description:
+ "섹션 위·아래 여백입니다. 값이 클수록 섹션이 여유 있고 강조되어 보입니다. Hero 섹션은 넉넉한 패딩을, 보조 섹션은 중간 정도를 추천합니다.",
+ },
+ ],
+ };
+ case "video":
+ return {
+ title: "비디오 블록 튜토리얼",
+ description:
+ "YouTube/영상 URL 또는 직접 호스팅한 비디오를 삽입할 때 사용하는 블록입니다. 동영상 주소를 입력하고, 비율/정렬/재생 옵션을 조정해 페이지에 맞게 배치해 보세요.",
+ properties: [
+ {
+ label: "비디오 소스 / 비디오 URL / 비디오 파일 업로드",
+ description:
+ "외부 동영상 URL(YouTube, Vimeo 등)을 직접 입력하거나, 비디오 파일을 업로드해 `/api/video/:id` 형태로 사용할 수 있습니다.",
+ },
+ {
+ label: "포스터 이미지 URL",
+ description:
+ "동영상 재생 전/로딩 중에 보여줄 썸네일 이미지입니다. 영상의 핵심 장면이나 대표 이미지를 사용하면 클릭률을 높일 수 있습니다.",
+ },
+ {
+ label: "카드 배경색",
+ description:
+ "비디오가 들어가는 카드 영역의 배경색입니다. 주변 섹션과의 대비를 위해 살짝 어둡거나 밝은 색을 설정할 수 있습니다.",
+ },
+ {
+ label: "비디오 정렬",
+ description:
+ "비디오를 컨테이너 안에서 왼쪽/가운데/오른쪽 중 어디에 위치시킬지 결정합니다.",
+ },
+ {
+ label: "비디오 너비 모드 / 고정 너비 (px)",
+ description:
+ "비디오를 내용 너비에 맞출지, 가로 전체를 채울지, 특정 px 너비로 고정할지 선택합니다.",
+ },
+ {
+ label: "카드 패딩 / 카드 모서리 둥글기",
+ description:
+ "비디오 주변 카드의 안쪽 여백과 모서리 둥글기입니다. 카드형 레이아웃에서는 적당한 패딩과 둥근 모서리를 주면 디자인이 정돈됩니다.",
+ },
+ {
+ label: "시작 시점 (초) / 종료 시점 (초)",
+ description:
+ "영상의 특정 구간만 재생하고 싶을 때 사용하는 옵션입니다. 예를 들어 10초~30초만 재생하도록 설정할 수 있습니다.",
+ },
+ {
+ label: "화면 비율",
+ description:
+ "동영상 프레임 비율입니다. 대부분의 웹 영상은 16:9를 사용하며, 정사각형/세로형 콘텐츠는 1:1, 4:3 등을 사용할 수 있습니다.",
+ },
+ {
+ label: "자동 재생 / 반복 재생 / 음소거 / 재생 컨트롤 표시",
+ description:
+ "자동 재생/반복 재생/음소거/컨트롤 표시 여부를 설정합니다. 자동 재생 영상은 보통 음소거를 함께 켜 두는 것이 좋습니다.",
+ },
+ ],
+ };
+ case "form":
+ return {
+ title: "폼 컨트롤러 블록 튜토리얼",
+ description:
+ "입력 필드(formInput/select/checkbox/radio)를 하나의 폼으로 묶는 컨트롤러입니다. 전송 대상, 전송 포맷, 너비, 여백 등을 설정해 네이티브 폼 제출을 구성하고, 필드 ID를 연결해 폼 구조를 완성할 수 있습니다.",
+ properties: [
+ {
+ label: "전송 대상 / Webhook 설정",
+ description:
+ "폼 데이터를 내부 처리로만 사용할지, 외부 Webhook/Google Sheets 등으로 전송할지 결정하고, 목적지 URL/전송 포맷/HTTP 메서드 등을 설정합니다.",
+ },
+ {
+ label: "추가 파라미터",
+ description:
+ "`key=value` 형식으로 줄바꿈해 작성하면, 모든 폼 제출에 공통으로 포함될 추가 파라미터를 지정할 수 있습니다. 예: `source=landing`.",
+ },
+ {
+ label: "폼 너비 모드 / 폼 고정 너비 (px)",
+ description:
+ "폼 전체의 가로 폭을 자동/전체 폭/고정 px 값 중에서 선택합니다. 문의 폼은 보통 480~640px 정도의 고정 폭이 읽기 좋습니다.",
+ },
+ {
+ label: "폼 위/아래 여백 (px)",
+ description:
+ "폼 블록 위·아래에 들어가는 공백입니다. 페이지 내 다른 섹션과의 간격을 조절할 때 사용합니다.",
+ },
+ {
+ label: "성공 메시지 / 에러 메시지",
+ description:
+ "폼 전송 성공 또는 실패 시 사용자에게 보여줄 텍스트입니다. 명확하고 친절한 문구로 작성하는 것이 좋습니다.",
+ },
+ {
+ label: "폼 필드 매핑",
+ description:
+ "폼 컨트롤러와 연결할 입력 필드(formInput/select/checkbox/radio)를 체크박스로 선택합니다. 체크된 필드만 실제 폼 제출 payload에 포함됩니다.",
+ },
+ {
+ label: "Submit 버튼",
+ description:
+ "폼 제출을 담당할 버튼 블록을 지정합니다. 별도 버튼 블록을 만들어 이 컨트롤러와 연결하면, 해당 버튼 클릭 시 폼이 제출됩니다.",
+ },
+ ],
+ };
+ case "formInput":
+ return {
+ title: "폼 입력 블록 튜토리얼",
+ description:
+ "이름, 이메일 등 한 줄 텍스트 또는 긴 텍스트 입력 필드를 만들 때 사용하는 블록입니다. 레이블, 플레이스홀더, 필수 여부, 너비 등을 설정해 폼 컨트롤러와 함께 사용합니다.",
+ properties: [
+ {
+ label: "라벨 타입 / 필드 라벨",
+ description:
+ "입력 필드 위나 옆에 표시될 설명입니다. 텍스트 또는 이미지로 라벨을 구성할 수 있으며, 사용자가 어떤 값을 입력해야 하는지 명확하게 알려줍니다.",
+ },
+ {
+ label: "라벨 이미지 URL / 대체 텍스트",
+ description:
+ "라벨을 이미지로 사용할 때 경로와 alt 텍스트를 지정합니다. 로고형 라벨이나 아이콘 기반 UI를 만들 때 활용할 수 있습니다.",
+ },
+ {
+ label: "전송 키",
+ description:
+ "이 입력값이 서버/웹훅에 전달될 때 사용되는 필드 이름입니다. 백엔드나 스프레드시트 컬럼명과 일치시키면 이후 처리가 편해집니다.",
+ },
+ {
+ label: "필드 타입",
+ description:
+ "텍스트/이메일/긴 텍스트 중 어떤 형태의 입력을 받을지 결정합니다. 이메일 타입은 브라우저 기본 이메일 검증을 활용할 수 있습니다.",
+ },
+ {
+ label: "Placeholder",
+ description:
+ "입력 전 필드 안에 흐릿하게 보여줄 안내 문구입니다. 예: '이메일을 입력해 주세요'.",
+ },
+ {
+ label: "필수 필드",
+ description:
+ "체크 시 이 필드는 반드시 채워야 합니다. 이름/이메일 같은 필수 값에는 활성화하고, 선택 항목에는 비활성화하는 것을 추천합니다.",
+ },
+ {
+ label: "텍스트 크기 / 줄간격 / 자간",
+ description:
+ "입력 값의 폰트 크기(px), 줄간격(px), 자간(px)을 조절해 폼 필드의 가독성과 분위기를 세밀하게 튜닝합니다.",
+ },
+ {
+ label: "텍스트 정렬",
+ description:
+ "필드 안 텍스트를 왼쪽/가운데/오른쪽 중 어디에 정렬할지 결정합니다. 일반 입력은 왼쪽 정렬을 권장합니다.",
+ },
+ {
+ label: "레이아웃 / 라벨/필드 간격",
+ description:
+ "라벨과 필드를 세로(stack) 또는 가로(inline)로 배치하고, inline 모드에서 라벨과 입력 사이 간격(px)을 조절합니다.",
+ },
+ {
+ label: "너비 / 필드 고정 너비",
+ description:
+ "필드를 자동/전체 폭/고정 px 중 어떤 너비로 렌더링할지 결정합니다. 짧은 필드는 고정 값, 긴 입력은 전체 폭을 사용할 수 있습니다.",
+ },
+ {
+ label: "필드 가로/세로 패딩",
+ description:
+ "입력 상자 안쪽 여백을 조절합니다. 값이 클수록 필드가 커지고 누르기/입력하기 편해집니다.",
+ },
+ {
+ label: "필드 텍스트/채움/테두리 색상",
+ description:
+ "입력 텍스트, 배경, 테두리 색상을 각각 조절합니다. 에러 상태/강조 상태 등을 표현할 때 조합해서 사용할 수 있습니다.",
+ },
+ {
+ label: "필드 모서리 둥글기",
+ description:
+ "입력 상자의 모서리를 얼마나 둥글게 할지 결정합니다. 페이지의 전체 디자인 톤과 맞춰 사용하세요.",
+ },
+ ],
+ };
+ case "formSelect":
+ return {
+ title: "폼 셀렉트 블록 튜토리얼",
+ description:
+ "드롭다운 선택 필드를 만들 때 사용하는 블록입니다. 옵션 목록과 기본 선택값, 너비를 설정해 폼 컨트롤러와 함께 사용합니다.",
+ properties: [
+ {
+ label: "라벨 타입 / 필드 라벨",
+ description:
+ "셀렉트 필드의 제목 역할을 하는 라벨입니다. 텍스트 또는 이미지로 구성할 수 있으며, 선택해야 할 값의 의미를 설명합니다.",
+ },
+ {
+ label: "전송 키",
+ description:
+ "선택된 옵션 값이 서버/웹훅에 전달될 때 사용되는 필드 이름입니다. 백엔드나 스프레드시트 컬럼명과 일치시키면 이후 처리가 편해집니다.",
+ },
+ {
+ label: "옵션",
+ description:
+ "사용자가 선택할 수 있는 옵션 목록입니다. 라벨과 value를 함께 설정하며, '옵션 추가' 버튼으로 새 옵션을 만들 수 있습니다.",
+ },
+ {
+ label: "필수 필드",
+ description:
+ "체크 시 반드시 하나의 옵션을 선택해야 합니다. 중요 선택 항목에는 필수로 설정하는 것을 권장합니다.",
+ },
+ {
+ label: "셀렉트 텍스트 크기 / 줄간격 / 자간",
+ description:
+ "드롭다운 필드의 텍스트 타이포그래피를 px 단위로 조절해 가독성과 분위기를 맞춥니다.",
+ },
+ {
+ label: "필드 너비 / 필드 고정 너비",
+ description:
+ "셀렉트 필드를 자동/전체 폭/고정 px 중 어떤 너비로 렌더링할지 결정합니다.",
+ },
+ {
+ label: "셀렉트 가로/세로 패딩",
+ description:
+ "드롭다운 안쪽 여백을 조절해 클릭 영역과 시각적 무게감을 조정합니다.",
+ },
+ {
+ label: "필드 텍스트/채움/테두리 색상",
+ description:
+ "선택 영역의 텍스트, 배경, 테두리 색상을 설정합니다. 폼 전체 톤과 잘 어울리는 색상을 사용하는 것이 좋습니다.",
+ },
+ {
+ label: "필드 모서리 둥글기",
+ description:
+ "셀렉트 박스의 모서리를 얼마나 둥글게 표시할지 결정합니다.",
+ },
+ ],
+ };
+ case "formCheckbox":
+ return {
+ title: "폼 체크박스 블록 튜토리얼",
+ description:
+ "여러 항목 중 복수 선택이 필요한 경우 사용하는 체크박스 그룹 블록입니다. 그룹 타이틀과 옵션 라벨/이미지를 설정해 동의 항목이나 관심사 선택 등을 구성할 수 있습니다.",
+ properties: [
+ {
+ label: "그룹 타이틀 타입 / 그룹 타이틀",
+ description:
+ "체크박스 그룹 전체의 제목입니다. 텍스트 또는 이미지로 표현할 수 있으며, 사용자가 어떤 범주를 선택하는지 알려줍니다.",
+ },
+ {
+ label: "그룹 타이틀 이미지 소스 / URL / 파일 업로드",
+ description:
+ "그룹 라벨을 이미지로 사용할 때, URL 또는 업로드된 이미지를 선택합니다.",
+ },
+ {
+ label: "전송 키",
+ description:
+ "체크된 옵션들의 값이 서버/웹훅에 전달될 때 사용되는 필드 이름입니다.",
+ },
+ {
+ label: "옵션 / 옵션 이미지 소스",
+ description:
+ "각 체크박스 옵션의 라벨/값/이미지를 설정합니다. URL 또는 업로드 이미지로 옵션별 아이콘을 붙일 수 있습니다.",
+ },
+ {
+ label: "필수 필드",
+ description:
+ "체크 시 하나 이상 옵션을 선택해야 합니다. 약관 동의 등 필수 동의 항목에 사용합니다.",
+ },
+ {
+ label: "체크박스 텍스트 크기 / 줄간격 / 자간",
+ description:
+ "체크박스 라벨의 폰트 크기, 줄간격, 자간을 조절합니다. 항목이 길어질수록 줄간격을 넉넉히 두는 것이 좋습니다.",
+ },
+ ],
+ };
+ case "formRadio":
+ return {
+ title: "폼 라디오 블록 튜토리얼",
+ description:
+ "여러 옵션 중 하나만 선택해야 할 때 사용하는 라디오 버튼 그룹 블록입니다. 옵션 라벨/이미지와 기본 선택값을 설정해 요금제 선택 등 단일 선택 시나리오를 구성할 수 있습니다.",
+ properties: [
+ {
+ label: "그룹 타이틀 타입 / 그룹 타이틀",
+ description:
+ "라디오 그룹의 제목입니다. 요금제 이름, 질문 문구 등 단일 선택의 맥락을 설명합니다.",
+ },
+ {
+ label: "그룹 타이틀 이미지 소스 / URL / 파일 업로드",
+ description:
+ "그룹 라벨을 이미지로 사용할 때, URL 또는 업로드 이미지를 선택합니다.",
+ },
+ {
+ label: "전송 키",
+ description:
+ "선택된 하나의 옵션 값이 서버/웹훅에 전달될 때 사용되는 필드 이름입니다.",
+ },
+ {
+ label: "옵션 / 옵션 이미지 소스",
+ description:
+ "각 라디오 옵션의 라벨/값/이미지를 설정합니다. 옵션별 아이콘이나 썸네일을 붙여 더 풍부한 선택 UI를 만들 수 있습니다.",
+ },
+ {
+ label: "필수 필드",
+ description:
+ "체크 시 반드시 하나의 옵션을 선택해야 합니다. 요금제/유형 선택처럼 반드시 선택이 필요한 경우에 사용합니다.",
+ },
+ {
+ label: "라디오 텍스트 크기 / 줄간격 / 자간",
+ description:
+ "라디오 라벨의 폰트 크기, 줄간격, 자간을 조절합니다. 옵션 설명이 긴 경우 줄간격을 넉넉히 두세요.",
+ },
+ ],
+ };
+ default:
+ return {
+ title: "블록 튜토리얼",
+ description: "이 블록에 대한 자세한 도움말은 추후 추가될 예정입니다.",
+ };
+ }
+ };
+
return (