Metabase 嵌入 SDK 自定义仪表盘卡片菜单:DashboardCardMenuCustomElement 类型完全指南
【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase
仪表盘卡片右上角的“…”菜单(下载、编辑链接、查看原始问题等)是嵌入场景中经常需要定制的能力。Metabase Embedding SDK 通过DashboardCardMenuCustomElement类型让你用自己的 React 组件整体替换该菜单。本文从类型定义、参数语义、返回值约束到插件挂载方式逐层拆解,并结合当前仓库源码给出可直接落地的实现示例。
类型定义与签名
DashboardCardMenuCustomElement在仓库中的权威定义位于 dashcard-menu.ts,SDK 对外文档中的签名为:
type DashboardCardMenuCustomElement = ({ question, }: { question: MetabaseQuestion; }) => ReactNode;其本质是一个接收参数对象、返回ReactNode的函数组件类型。即:你传入的组件会收到一个包含question的对象,并用返回值(通常是 JSX)渲染整个卡片菜单。返回null或false时菜单不渲染。
参数详解
{ question }:当前卡片对应的问题
| 参数 | 类型 | 说明 |
|---|---|---|
{ question, } | { question: MetabaseQuestion; } | 参数对象,唯一公开字段为question |
{ question, }.question | MetabaseQuestion | 当前仪表盘卡片所基于的问题对象 |
MetabaseQuestion是 SDK 暴露给嵌入应用的问题描述类型,在 question.ts 中由metabase/embedding-sdk/types/questionre-export,其公开属性(见 MetabaseQuestion 片段文档)包括:
id: number— 问题的数字 IDentityId: string— 问题的实体 ID(entity_id)name: string— 问题名称description: string \| null— 问题描述isSavedQuestion: boolean— 是否为已保存问题
你可以依据这些字段定制菜单行为,例如未保存的临时问题不显示“编辑”入口。
内部参数(@internal,仅供组件读取)
从源码看,实际传入组件上下文还包含三个被标记为@internal的字段:
/** @internal */ dashcard: DashboardCard; /** @internal */ result: Dataset; /** @internal */ downloadsEnabled: DashboardContextProps["downloadsEnabled"];dashcard— 卡片原始数据对象(来自metabase-types/api);result— 当前卡片的查询结果数据集(Dataset);downloadsEnabled— 仪表盘上下文中的下载开关状态,可据此决定是否渲染下载项。
虽然它们不构成公共 API 承诺,但说明了自定义菜单组件能够在渲染时拿到卡片数据与查询结果,从而基于数据状态动态控制菜单内容。
返回值:ReactNode
该类型返回ReactNode。实践中通常是:
- 一个下拉菜单组件(如 Mantine 的
Menu); - 一个普通按钮或链接;
null(隐藏菜单)。
返回值没有固定 UI 约束,完全由嵌入方控制。
如何挂载到 SDK:plugins 配置链路
该类型并非独立使用,而是作为 SDK 插件配置的一部分注入。仓库 plugins.ts 中定义了完整的配置结构:
export type MetabaseDashboardPluginsConfig = { dashboardCardMenu?: DashboardCardMenu; }; export type MetabasePluginsConfig = { mapQuestionClickActions?: MetabaseClickActionPluginsConfig; dashboard?: MetabaseDashboardPluginsConfig; };即挂载路径为:plugins.dashboard.dashboardCardMenu。而DashboardCardMenu本身是一个联合类型(见 dashcard-menu.ts):
export type DashboardCardMenu = | DashboardCardMenuCustomElement // 完全自定义:整个菜单替换为你的组件 | DashboardCardCustomMenuItem; // 部分定制:保留默认菜单项并追加自定义项因此有两种定制粒度:
- 完全替换:传入
DashboardCardMenuCustomElement,整个“…”菜单都由你的组件渲染,默认的下载/编辑项随之消失(除非你在组件里自行实现); - 部分定制:传入
DashboardCardCustomMenuItem,通过withDownloads、withEditLink控制内置项,用customItems追加自定义菜单项。
CustomDashboardCardMenuItem与DashboardCardCustomMenuItem的类型同样定义在同文件中,前者接收question(可选)并返回DashCardMenuItem。
完整实现示例
以下示例展示了如何用自定义组件替换卡片菜单,并通过MetabaseQuestion的属性动态改变菜单内容:
import { Menu } from "@mantine/core"; import { MetabaseProvider } from "@metabase/embedding-sdk-react"; import type { DashboardCardMenuCustomElement, MetabasePluginsConfig, } from "@metabase/embedding-sdk-react"; // 自定义菜单组件:仅当问题是已保存问题时显示菜单 const MyCardMenu: DashboardCardMenuCustomElement = ({ question }) => { if (!question.isSavedQuestion) { return null; } return ( <Menu> <Menu.Target> <button aria-label="卡片菜单">⋯</button> </Menu.Target> <Menu.Dropdown> <Menu.Item onClick={() => window.open(`/question/${question.id}`)}> 打开问题 #{question.id} </Menu.Item> <Menu.Item disabled>问题名:{question.name}</Menu.Item> </Menu.Dropdown> </Menu> ); }; const plugins: MetabasePluginsConfig = { dashboard: { dashboardCardMenu: MyCardMenu, }, }; export function App() { return ( <MetabaseProvider authType="token" config={{ getEmbeddingConfig: () => ({}) }} plugins={plugins} > {/* 仪表盘通过 InteractiveDashboard 渲染 */} </MetabaseProvider> ); }要点:
- 组件签名必须与
({ question }) => ReactNode兼容; question.id可直接用于拼接问题详情链接,question.isSavedQuestion用于过滤未保存的临时卡片;- 若需要保留默认的下载能力,请在自定义组件中基于
downloadsEnabled自行实现,或改用DashboardCardCustomMenuItem的部分定制模式。
源码验证与延伸阅读
- 类型权威定义:dashcard-menu.ts,其中同时包含
DashboardCardMenuCustomElement、CustomDashboardCardMenuItem、DashboardCardCustomMenuItem与联合类型DashboardCardMenu; - 插件配置入口:plugins.ts,
MetabasePluginsConfig.dashboard.dashboardCardMenu是唯一挂载点; MetabaseQuestion属性表:MetabaseQuestion.md,以及其在 question.ts 中的 re-export;- 相关 API 参考:MetabaseQuestion(HTML 版完整文档)。
小结
DashboardCardMenuCustomElement是 SDK 插件体系中“全量替换”卡片菜单的入口:参数侧只承诺question(含id、entityId、name、description、isSavedQuestion),实现侧返回任意ReactNode,并通过plugins.dashboard.dashboardCardMenu注入。配合同文件中的DashboardCardCustomMenuItem,你可以自由选择“整菜单替换”与“默认菜单追加自定义项”两种嵌入定制策略。
【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考