添加下拉菜单以选择列表类型

Available for free

一个用于从多种列表类型中选择的下拉菜单。

安装

通过 Tiptap CLI 添加该组件:

npx @tiptap/cli@latest add list-dropdown-menu

组件

<ListDropdownMenu />

一个预构建的 React 组件,提供一个下拉菜单,用于选择不同的列表类型。

使用示例

import { EditorContent, EditorContext, useEditor } from '@tiptap/react'
import { StarterKit } from '@tiptap/starter-kit'
import { TaskList } from '@tiptap/extension-task-list'
import { TaskItem } from '@tiptap/extension-task-item'
import { ListDropdownMenu } from '@/components/tiptap-ui/list-dropdown-menu'

import '@/components/tiptap-node/code-block-node/code-block-node.scss'
import '@/components/tiptap-node/list-node/list-node.scss'
import '@/components/tiptap-node/paragraph-node/paragraph-node.scss'

export default function MyEditor() {
  const editor = useEditor({
    immediatelyRender: false,
    extensions: [StarterKit, TaskList, TaskItem.configure({ nested: true })],
    content: `
        <ul>
            <li>
                <strong>粗体</strong> 用于强调,可以使用 <code>**</code> 或 <code>⌘+B</code> 或 <code>B</code> 按钮。
            </li>
            <li>
                <em>斜体</em> 用于细微的差别,可以使用 <code>*</code> 或 <code>⌘+I</code> 或 <code>I</code> 按钮。
            </li>
            <li>
                <s>删除线</s> 用于显示修改,可以使用 <code>~~</code> 或 <code>~~S~~</code> 按钮。
            </li>
        </ul>
        <ul data-type="taskList">
            <li data-type="taskItem" data-checked="true">
                <div>
                    测试模板
                </div>
            </li>
            <li data-type="taskItem" data-checked="false">
                <div>
                    <a target="_blank" rel="noopener noreferrer nofollow" href="https://tiptap.dev/pricing">创建帐户</a>
                </div>
            </li>
            <li data-type="taskItem" data-checked="false">
                <div>
                   下载免费模板
                </div>
            </li>
        </ul>
        `,
  })

  return (
    <EditorContext.Provider value={{ editor }}>
      <ListDropdownMenu
        editor={editor}
        types={['bulletList', 'orderedList', 'taskList']}
        hideWhenUnavailable={true}
        portal={false}
        onOpenChange={(isOpen) => console.log('Dropdown opened:', isOpen)}
      />

      <EditorContent editor={editor} role="presentation" />
    </EditorContext.Provider>
  )
}

属性

名称类型默认值描述
editorEditor | nullnullTiptap 编辑器实例
typesArray<'bulletList' | 'orderedList' | 'taskList'>['bulletList', 'orderedList', 'taskList']下拉菜单中包含的列表类型
hideWhenUnavailablebooleanfalse当没有可用列表类型时是否隐藏菜单
onOpenChange(isOpen: boolean) => void-下拉菜单打开状态变化时的回调函数
portalbooleanfalse是否在 Portal 中渲染下拉菜单

Hooks

useListDropdownMenu()

一个自定义 Hook,用于管理列表下拉菜单的状态并确定可用的选项。

使用示例

import { useListDropdownMenu } from '@/components/tiptap-ui/list-dropdown-menu'
import { ListButton } from '@/components/tiptap-ui/list-button'
import {
  DropdownMenu,
  DropdownMenuTrigger,
  DropdownMenuContent,
  DropdownMenuItem,
} from '@/components/tiptap-ui-primitive/dropdown-menu'
import { ButtonGroup } from '@/components/tiptap-ui-primitive/button'

function MyListDropdown() {
  const { filteredLists, canToggle, isActive, isVisible, Icon, activeType } = useListDropdownMenu({
    editor,
    types: ['bulletList', 'orderedList', 'taskList'],
    hideWhenUnavailable: true,
  })

  if (!isVisible) return null

  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <button disabled={!canToggle}>
          <Icon />
          列表 {isActive ? '(激活)' : ''}
        </button>
      </DropdownMenuTrigger>
      <DropdownMenuContent>
        <ButtonGroup>
          {filteredLists.map((option) => (
            <DropdownMenuItem key={option.type} asChild>
              <ListButton editor={editor} type={option.type} text={option.label} />
            </DropdownMenuItem>
          ))}
        </ButtonGroup>
      </DropdownMenuContent>
    </DropdownMenu>
  )
}

属性

名称类型默认值描述
editorEditor | nullundefinedTiptap 编辑器实例
typesListType[]["bulletList", "orderedList", "taskList"]要显示在下拉菜单中的列表类型数组
hideWhenUnavailablebooleanfalse是否在没有可用列表类型时隐藏下拉菜单

返回值

名称类型描述
isVisibleboolean下拉菜单是否应该显示
activeTypeListType | undefined当前激活的列表类型
isActiveboolean是否有列表类型当前处于激活状态
canToggleboolean是否可以切换任何列表类型
typesListType[]配置中的列表类型数组
filteredListsListOption[]根据可用类型过滤后的列表选项数组
labelstring下拉菜单的辅助功能文本标签
IconReact.FC用于当前激活列表类型或默认图标的组件

工具函数

canToggleAnyList(editor, listTypes)

检查指定的列表类型中是否有任何可以在当前编辑器状态下切换的。

import { canToggleAnyList } from '@/components/tiptap-ui/list-dropdown-menu'

const canToggle = canToggleAnyList(editor, ['bulletList', 'orderedList'])
if (canToggle) {
  console.log('至少有一种列表类型可以切换')
}

参数

名称类型描述
editorEditor | nullTiptap 编辑器实例
listTypesListType[]要检查的列表类型数组

返回值

boolean - 是否至少有一种列表类型可以切换。

isAnyListActive(editor, listTypes)

检查指定的列表类型中是否有任何当前处于激活状态的。

import { isAnyListActive } from '@/components/tiptap-ui/list-dropdown-menu'

const isActive = isAnyListActive(editor, ['bulletList', 'orderedList', 'taskList'])
if (isActive) {
  console.log('至少有一种列表类型当前处于激活状态')
}

参数

名称类型描述
editorEditor | nullTiptap 编辑器实例
listTypesListType[]要检查的列表类型数组

返回值

boolean - 是否至少有一种列表类型当前处于激活状态。

getFilteredListOptions(availableTypes)

根据可用类型过滤预定义的列表选项。

import { getFilteredListOptions } from '@/components/tiptap-ui/list-dropdown-menu'

const availableOptions = getFilteredListOptions(['bulletList', 'taskList'])
// 只返回项目符号列表和任务列表的选项

参数

名称类型描述
availableTypesListType[]要包含的列表类型数组

返回值

ListOption[] - 过滤后的列表选项数组。

getActiveListType(editor, availableTypes)

获取可用类型中当前激活的列表类型。

import { getActiveListType } from '@/components/tiptap-ui/list-dropdown-menu'

const activeType = getActiveListType(editor, ['bulletList', 'orderedList', 'taskList'])
console.log('当前列表类型:', activeType)

参数

名称类型描述
editorEditor | nullTiptap 编辑器实例
availableTypesListType[]要检查的列表类型数组

返回值

ListType | undefined - 当前激活的列表类型,如果没有激活则为 undefined

快捷键

每个列表类型支持以下快捷键(继承自底层的 ListButton 组件):

  • Cmd/Ctrl + Shift + 8:切换项目符号列表
  • Cmd/Ctrl + Shift + 7:切换有序列表
  • Cmd/Ctrl + Shift + 9:切换任务列表

当编辑器的 schema 中包含对应的列表类型时,这些快捷键会自动注册。

依赖

  • @tiptap/react — 核心 Tiptap React 集成
  • @tiptap/starter-kit — 包含列表支持的基础扩展包
  • @tiptap/extension-task-list — 任务列表扩展
  • @tiptap/extension-task-item — 任务项扩展

参考组件

  • use-tiptap-editor (hook)
  • list-button (组件)
  • button (基础组件)
  • dropdown-menu (基础组件)
  • card (基础组件)
  • tiptap-utils (工具库)
  • chevron-down-icon (图标)
  • list-icon (图标)
  • list-ordered-icon (图标)
  • list-todo-icon (图标)