Emoji 菜单

Available in Start plan

一个完全面向无障碍的 Emoji 选择菜单,适用于 Tiptap 编辑器。支持通过键盘导航浏览和搜索 Emoji,内置备用图片以及可自定义的筛选选项。

安装

通过 Tiptap CLI 添加组件:

npx @tiptap/cli@latest add emoji-menu

组件

<EmojiMenu />

一个具有搜索和导航功能的完整 Emoji 选择菜单。

用法

import { EmojiMenu } from '@/components/tiptap-ui/emoji-menu'
import { gitHubEmojis } from '@tiptap/extension-emoji'
import type { EmojiItem } from '@tiptap/extension-emoji'

export default function MyEmojiPicker() {
  const [selectedEmoji, setSelectedEmoji] = useState<EmojiItem | null>(null)

  const handleEmojiSelect = (emoji: EmojiItem) => {
    setSelectedEmoji(emoji)
    console.log('选中的 emoji:', emoji.name, emoji.emoji)
  }

  const handleClose = () => {
    console.log('Emoji 菜单已关闭')
  }

  return (
    <EmojiMenu
      emojis={gitHubEmojis}
      onSelect={handleEmojiSelect}
      onClose={handleClose}
      showSearch={true}
      selector=".my-emoji-menu"
    />
  )
}

属性

名称类型默认值描述
emojisT[] extends EmojiItemundefined要显示的 Emoji 项目数组
onSelect(emoji: T) => voidundefined选择 Emoji 时触发的回调
onClose() => voidundefined菜单关闭时触发的回调
showSearchbooleanfalse是否显示搜索输入框
selectorstring".emoji-menu-list"可滚动菜单容器的 CSS 选择器

<EmojiMenuItem />

Emoji 菜单内使用的单个 Emoji 条目组件。

用法

import { EmojiMenuItem } from '@/components/tiptap-ui/emoji-menu'
import type { EmojiItem } from '@tiptap/extension-emoji'

function CustomEmojiList({ emojis, onSelect, selectedIndex }) {
  return (
    <div>
      {emojis.map((emoji, index) => (
        <EmojiMenuItem
          key={emoji.name}
          emoji={emoji}
          index={index}
          isSelected={index === selectedIndex}
          onSelect={onSelect}
          selector=".custom-emoji-list"
        />
      ))}
    </div>
  )
}

属性

名称类型默认值描述
emojiT extends EmojiItemundefined要渲染的 Emoji 项目
indexnumberundefinedEmoji 在列表中的索引
isSelectedbooleanundefined此 Emoji 条目当前是否被选中
onSelect(emoji: T) => voidundefined选择此 Emoji 时触发的回调
selectorstringundefined可滚动容器的 CSS 选择器

工具函数

getFilteredEmojis(props)

根据搜索查询筛选并排序 Emoji 数据。

import { getFilteredEmojis } from '@/components/tiptap-ui/emoji-menu'
import { gitHubEmojis } from '@tiptap/extension-emoji'

const filteredEmojis = getFilteredEmojis({
  query: 'smile',
  emojis: gitHubEmojis,
})

console.log('筛选后的 Emoji 数量:', filteredEmojis.length)

参数

名称类型描述
props.querystring用于筛选 Emoji 的搜索查询字符串
props.emojisT[] extends EmojiItem要筛选的 Emoji 项目数组

返回值

T[] - 筛选并排序后的 Emoji 项目数组(最多 100 条结果)。

searchEmojiData(query, emojiData)

判断一个 Emoji 是否匹配搜索查询。

import { searchEmojiData } from '@/components/tiptap-ui/emoji-menu'

const emoji = {
  name: 'grinning',
  shortcodes: ['grinning', 'grinning_face'],
  tags: ['face', 'smile'],
  emoji: '😀',
}

const matches = searchEmojiData('smile', emoji) // true

参数

名称类型描述
querystring搜索查询字符串
emojiDataT extends EmojiItem用于匹配的 Emoji 项目

返回值

boolean - 该 Emoji 是否匹配搜索查询。

搜索功能

Emoji 菜单支持跨多个 Emoji 属性的智能搜索:

搜索字段

  • 名称:主要 Emoji 名称(例如 "grinning")
  • 短码:别名(例如 "grinning_face")
  • 标签:描述性标签(例如 "face", "smile")

搜索特点

  • 不区分大小写:搜索时忽略大小写
  • 部分匹配:找到包含搜索词的 Emoji
  • 多字段搜索:跨名称、短码和标签进行搜索
  • 结果限制:为了性能,最多返回 100 条结果
  • 字母排序:结果按照 Emoji 名称排序

示例搜索查询

// 按名称搜索
getFilteredEmojis({ query: 'heart', emojis }) // ❤️, 💖, 💕 等

// 按标签搜索
getFilteredEmojis({ query: 'face', emojis }) // 😀, 😃, 😄 等

// 按短码搜索
getFilteredEmojis({ query: 'grinning', emojis }) // 😀, 😃 等

// 空查询返回前 100 个 Emoji
getFilteredEmojis({ query: '', emojis }) // 前 100 个 Emoji

键盘导航

Emoji 菜单支持完整的键盘导航:

  • 方向键:上下导航 Emoji 列表
  • 回车键:选择当前高亮的 Emoji
  • Esc 键:关闭菜单
  • 输入搜索:自动聚焦搜索输入并过滤结果

导航功能由 useMenuNavigation 钩子提供,包括:

  • 智能滚动:自动滚动高亮项进入视野
  • 溢出处理:防止超出菜单边界的滚动
  • 焦点管理:导航过程中保持焦点状态

自定义 Emoji 数据

const customEmojis = [
  {
    emoji: '🎉',
    name: 'party',
    shortcodes: ['party', 'celebration'],
    tags: ['celebrate', 'fun'],
    group: 'activities',
    emoticons: [],
    version: 1,
    fallbackImage: 'https://example.com/party-emoji.png',
  },
  // ... 更多自定义 Emoji
]

function CustomEmojiPicker() {
  return (
    <EmojiMenu
      emojis={customEmojis}
      onSelect={(emoji) => console.log('自定义 Emoji:', emoji)}
      showSearch={true}
    />
  )
}

Emoji 项接口

@tiptap/extension-emoji 中的 EmojiItem 接口定义:

interface EmojiItem {
  emoji: string // 实际的 Emoji 字符: "😀"
  name: string // 主要名称: "grinning"
  shortcodes: string[] // 别名数组: ["grinning", "grinning_face"]
  tags: string[] // 描述标签: ["face", "smile"]
  group: string // 分类组别: "smileys-emotion"
  emoticons: string[] // 文本表现形式: [":D"]
  version: number // Unicode 版本号: 1.0
  fallbackImage?: string // 可选备用图片 URL
}

依赖项

必需依赖

  • @tiptap/react - Tiptap React 核心集成
  • @tiptap/extension-emoji - Emoji 扩展及类型定义

可选依赖

  • sass - 用于支持 SCSS 样式
  • sass-embedded - 增强的 Sass 处理器

相关组件

  • use-menu-navigation(钩子)
  • button, button-group(基础组件)
  • input(基础组件)
  • card, card-body, card-header(基础组件)
  • tiptap-collab-utils(库)