GithubXDiscord

block-types > 折叠块

折叠块

折叠块用于创建可折叠的内容。当用户点击折叠块时,隐藏的内容会展开或收起,是一个交互式元素。

数据结构

折叠块的 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 中用于渲染折叠块的组件如下:

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;

使用示例

使用折叠块的示例如下:

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

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

这里 blocks 是从 Notion API 接收到的块数据数组。

状态管理

折叠块内部使用 useState 钩子来管理展开/折叠状态。open 变量表示折叠块的当前状态,toggleOpen 函数用于切换该状态。

样式

折叠块的样式可以通过以下 CSS 类来定制:

  • .notion-block: 所有 Notion 块的默认样式
  • .notion-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);
}

嵌套支持

折叠块可以包含其他块。这通过 children prop 来处理。只有在折叠块展开时才会渲染 children

可访问性考虑

  • 使用 aria-expanded 属性来通知屏幕阅读器折叠块的当前状态。
  • 为了支持键盘导航,建议为折叠块按钮添加 tabIndex={0}
  • 为了清楚地描述折叠块的功能,建议为折叠块按钮提供适当的 aria-label

注意事项

  • 如果折叠块内部包含太多内容,可能会影响用户体验,因此建议只包含适当数量的内容。
  • 折叠块的展开/折叠状态不会保存到服务器上,因此刷新页面后所有折叠块都会恢复到默认状态(折叠)。
  • 深层次的嵌套折叠块可能会让用户感到困惑,因此建议限制嵌套层次。