GithubXDiscord

customization-guide > 自定义组件使用指南

自定义组件使用指南

Notionpresso 为各种 Notion 块类型提供了基本组件。本节将说明如何使用和自定义这些基本组件,以及如何创建新的自定义组件。

基本组件使用示例

Heading 组件

Heading 组件用于渲染 Notion 的标题块。以下是自定义 Heading 组件的示例:

import React from "react";
import { Heading, type HeadingArgs } from "@notionpresso/react";

const CustomHeading: React.FC<HeadingArgs> = (props) => {
  // level 3 헤딩에 밑줄 추가
  if (props.type === "heading_3") {
    return <Heading {...props} style={{ textDecoration: "underline" }} />;
  }
  return <Heading {...props} />;
};

export default CustomHeading;

이 예시에서는 level 속성을 확인하여 특정 레벨의 헤딩에 대해 스타일을 변경합니다.

Paragraph 组件

Paragraph 组件用于渲染普通文本块。以下是自定义 Paragraph 组件的示例:

import React from "react";
import { Paragraph, type ParagraphArgs } from "@notionpresso/react";

const CustomParagraph: React.FC<ParagraphArgs> = (props) => {
  return (
    <Paragraph
      {...props}
      className="custom-paragraph"
      style={{ lineHeight: "1.8", marginBottom: "1em" }}
    />
  );
};

export default CustomParagraph;

이 예시에서는 所有段落都调整了行高和底部边距,并添加了用户定义的类。

Toggle 组件的自定义示例

Toggle 组件用于实现 Notion 的切换块。以下是自定义 Toggle 组件的高级示例:

import React, { useState } from "react";
import { Toggle, type ToggleArgs } from "@notionpresso/react";
import { ChevronDown, ChevronRight } from "your-icon-library";

const CustomToggle: React.FC<ToggleArgs> = (props) => {
  const [isOpen, setIsOpen] = useState(false);

  const handleChangeOpen = (open: boolean) => {
    setIsOpen(open);
    // 여기에 추가적인 로직을 넣을 수 있습니다.
    console.log(`Toggle state changed to: ${open}`);
  };

  return (
    <Toggle {...props} isOpen={isOpen} onChangeOpen={handleChangeOpen}>
      <Toggle.Icon>
        {isOpen ? <ChevronDown size={20} /> : <ChevronRight size={20} />}
      </Toggle.Icon>
      <Toggle.Content>{props.children}</Toggle.Content>
    </Toggle>
  );
};

export default CustomToggle;

이 예시에서는:

  1. useState를 사용하여 切换的打开/关闭状态进行管理。
  2. handleChangeOpen 函数用于处理状态变化,并根据需要添加额外的逻辑。
  3. Toggle 组件通过 isOpenonChangeOpen prop将状态直接传递给组件。
  4. 根据 isOpen 状态显示不同的图标。

如果 <Toggle.Icon> 中没有提供内容,则使用默认图标。

应用自定义组件

在 Notionpresso 中使用自定义组件的方法如下:

import { Notion } from "@notionpresso/react";
import CustomHeading from "./CustomHeading";
import CustomParagraph from "./CustomParagraph";
import CustomToggle from "./CustomToggle";

const MyNotionPage = ({ pageData }) => {
  const customComponents = {
    heading_1: CustomHeading,
    heading_2: CustomHeading,
    heading_3: CustomHeading,
    paragraph: CustomParagraph,
    toggle: CustomToggle,
  };

  return (
    <Notion custom={customComponents}>
      <Notion.Body>
        <Notion.Blocks blocks={pageData.blocks} />
      </Notion.Body>
    </Notion>
  );
};

在此示例中,通过 custom prop将自定义组件传递给 Notion 组件。可以为每个块类型指定自定义组件。

创建完整的自定义组件

可以完全从头开始创建新的组件,而不是使用 Notionpresso 的基本组件。以下是创建 Todo 组件的示例:

import React from "react";
import { RichText, type TodoProps } from "@notionpresso/react";

const Todo: React.FC<TodoProps> = ({ children, ...props }) => {
  const {
    to_do: { color, rich_text: texts, checked },
  } = props;

  const colorClass = color !== "default" ? `notion-${color}` : "";

  return (
    <div className={`notion-block notion-to-do ${colorClass}`}>
      <div className="notion-to-do-item">
        <div className="notion-to-do-item-content">
          <input
            type="checkbox"
            checked={checked}
            readOnly
            className="notion-to-do-checkbox"
          />
          <div
            className={`notion-to-do-text ${checked ? "notion-to-do-checked" : ""}`}
          >
            <RichText props={texts} />
          </div>
        </div>
        {children}
      </div>
    </div>
  );
};

export default Todo;

在此示例中需要注意以下几点:

  • 仅使用 RichText 组件,因为这是处理复杂文本渲染的唯一方法。
  • CSS 类名必须以 notion- 开头,因为这是 Notionpresso 样式规则的要求。
  • 添加 gnotion-${color} 形式的类,因为默认颜色("default")不需要额外类。
  • 组件可以通过 children prop接收子内容,以支持嵌套结构。

组件编写时的注意事项

  1. 类型安全性: 使用 TypeScript 明确定义 prop 类型,并利用 Notionpresso 提供的类型(例如 HeadingArgs, ParagraphArgs)。
  2. prop 传递: 如果要在自定义组件中使用基本组件的所有 prop,请使用 {...props}。这有助于保持类型安全性,并避免不必要的 prop 列出。
  3. 样式覆盖: 注意不要完全覆盖现有样式,而是通过添加 className 或扩展 style prop 来使用。
  4. 性能考虑: 为了防止不必要的重新渲染,请适当使用 React.memo, useMemo, useCallback
  5. 可访问性: 在创建自定义组件时,请考虑可访问性(a11y)。例如,为切换按钮添加适当的 aria- 属性。
  6. 主题支持: 请设计自定义组件,以便与 Notionpresso 的主题系统兼容。使用 CSS 变量可以轻松支持暗模式等主题切换。

应用自定义组件

在 Notionpresso 中使用自定义组件的方法如下:

import { Notion, type NotionPage, type CustomComponents } from 'Notionpresso';
import CustomParagraph from './CustomParagraph';
import CustomToggle from './CustomToggle';

const MyNotionPage = ({ pageData }: { pageData: NotionPage }) => {
  const customComponents = useMemo<CustomComponents>(() => ({
    paragraph: CustomParagraph,
    toggle: CustomToggle,
  }), []);

  return (
    <Notion custom={customComponents}>
    <Notion.Cover cover={pageData.cover} />
      <Notion.Body>
        <Notion.Title title={pageData.title} />
        <Notion.Blocks blocks={pageData.blocks} />
      </Notion.Body>
    </Notion>
  );
};

在此示例中,通过 custom prop将自定义组件传递给 Notion 组件。

遵循这些指南,可以在扩展 Notionpresso 功能的同时保持一致性和可维护性。