GithubXDiscord

block-types > Toggle 블록

Toggle 블록

Toggle 블록은 접을 수 있는 콘텐츠를 생성하는 데 사용됩니다. 사용자가 토글을 클릭하면 숨겨진 내용이 펼쳐지거나 접히는 인터랙티브한 요소입니다.

데이터 구조

Toggle 블록의 Notion API 데이터 구조는 다음과 같습니다:

{
  "type": "toggle",
  "toggle": {
    "rich_text": [
      {
        "type": "text",
        "text": {
          "content": "Click to toggle",
          "link": null
        },
        "annotations": {
          "bold": false,
          "italic": false,
          "strikethrough": false,
          "underline": false,
          "code": false,
          "color": "default"
        },
        "plain_text": "Click to toggle",
        "href": null
      }
    ],
    "color": "default",
    "children": [
      // 중첩된 블록들...
    ]
  }
}
  • rich_text: 토글의 표시 텍스트와 스타일 정보를 담고 있는 배열입니다.
  • color: 토글 텍스트의 색상을 지정합니다.
  • children: 토글을 펼쳤을 때 표시될 중첩된 블록들의 배열입니다.

React 컴포넌트

Notionpresso에서 Toggle 블록을 렌더링하는 컴포넌트는 다음과 같습니다:

import React, { useState, useCallback } from "react";
import type { ToggleArgs } from "../types";
import { getColorCss } from "../utils";
import RichText from "./internal/rich-text";

type ToggleProps = {
  children?: React.ReactNode;
} & ToggleArgs;

const Toggle: React.FC<ToggleProps> = ({ children, ...props }) => {
  const {
    toggle: { color, rich_text: texts },
  } = props;

  const [open, setOpen] = useState(false);

  const toggleOpen = useCallback(() => setOpen((prevOpen) => !prevOpen), []);

  return (
    <div
      className={`notion-block notion-toggle ${getColorCss(color)} ${
        open ? "notion-toggle-open" : ""
      }`}
      aria-expanded={open}
    >
      <div className="notion-toggle-content">
        <button onClick={toggleOpen} className="notion-toggle-button">
          <div
            className={`notion-toggle-button-arrow ${
              open ? "notion-toggle-button-arrow-opened" : ""
            }`}
          />
        </button>
        <p>
          <RichText props={texts} />
        </p>
      </div>

      {open && children}
    </div>
  );
};

export default Toggle;

사용 예시

Toggle 블록을 사용하는 예시는 다음과 같습니다:

import { Notion } from "@notionpresso/react";

function MyNotionPage({ blocks }) {
  return (
    <Notion>
      <Notion.Blocks blocks={blocks} />
    </Notion>
  );
}

여기서 blocks는 Notion API로부터 받아온 블록 데이터 배열입니다.

상태 관리

Toggle 블록은 내부적으로 useState 훅을 사용하여 열림/닫힘 상태를 관리합니다. open 상태 변수는 토글의 현재 상태를 나타내며, toggleOpen 함수는 이 상태를 전환합니다.

스타일링

Toggle 블록의 스타일은 다음 CSS 클래스를 통해 커스터마이즈할 수 있습니다:

  • .notion-block: 모든 Notion 블록에 적용되는 기본 스타일
  • .notion-toggle: Toggle 블록 특정 스타일
  • .notion-toggle-open: 토글이 열린 상태일 때의 스타일
  • .notion-toggle-content: 토글 내용의 스타일
  • .notion-toggle-button: 토글 버튼의 스타일
  • .notion-toggle-button-arrow: 토글 화살표의 스타일

추가적인 스타일링이 필요한 경우, 이 클래스들을 대상으로 CSS를 작성하면 됩니다. 예를 들어:

.notion-toggle {
  margin-bottom: 8px;
}

.notion-toggle-button {
  cursor: pointer;
  background: none;
  border: none;
  padding: 0;
  margin-right: 4px;
}

.notion-toggle-button-arrow {
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 5px solid #333;
  transition: transform 0.3s ease;
}

.notion-toggle-button-arrow-opened {
  transform: rotate(180deg);
}

중첩 지원

Toggle 블록은 다른 블록을 포함할 수 있습니다. 이는 children prop을 통해 처리됩니다. 토글이 열린 상태일 때만 children이 렌더링됩니다.

접근성 고려사항

  • aria-expanded 속성을 사용하여 토글의 현재 상태를 스크린 리더에 알립니다.
  • 키보드 네비게이션을 지원하기 위해 토글 버튼에 tabIndex={0}를 추가하는 것이 좋습니다.
  • 토글 버튼에 적절한 aria-label을 제공하여 그 기능을 명확히 설명하는 것이 좋습니다.

주의사항

  • 토글 내부에 너무 많은 콘텐츠를 넣으면 사용자 경험이 저하될 수 있으므로 적절한 양의 콘텐츠만 포함하는 것이 좋습니다.
  • 토글의 열림/닫힘 상태는 서버에 저장되지 않으므로, 페이지를 새로고침하면 모든 토글이 기본 상태(닫힘)로 돌아갑니다.
  • 깊은 수준의 중첩된 토글은 사용자를 혼란스럽게 할 수 있으므로 가능한 한 중첩 수준을 제한하는 것이 좋습니다.