mcpField
B
building-react-quill-canvases

building-react-quill-canvases

github.com/posthog设计与 UI95108 次安装今天更新
代码仓库

关于 building-react-quill-canvases

用于构建 PostHog 数据画布的技能,采用单文件 React 和 Quill 组件。内容涵盖界面约束、数据加载与错误处理,以及仪表板模式。

主要功能

  1. 01单文件 React/TSX 画布结构
  2. 02Quill 组件与样式规则
  3. 03独立加载和错误状态
  4. 04仪表板与数据探索模式
  5. 05日期控件和 PostHog 数据访问

适用场景

  1. 01构建 PostHog 分析仪表板
  2. 02创建交互式数据探索器
  3. 03设计清单或运行手册画布

MCP 相关

介绍了通过 PostHog MCP 工具执行操作,并引用 querying-canvas-data 说明数据访问、能力声明和工具调用。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/posthog/ai-plugin --skill building-react-quill-canvases

安装后在 Claude Code 中输入/building-react-quill-canvases确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
checklist-example.md
platform-libraries.md
starter-scaffold.md

详细介绍

构建 React + Quill 画布

整个应用是一个 React/TSX 文件(源项目中的 src/canvas.tsx)。它必须 export default 一个不接收任何属性的 React 组件,由宿主挂载。不要导入 react-dom,也不要调用 createRoot。

首次构建时,请从可正常运行的脚手架开始:references/starter-scaffold.md。 它已经接好了日期选择器、主题令牌、按查询分别管理的加载状态(每张卡片会在各自的数据到达后独立填充),以及正确的类型化节点结果读取。保留这些接线,并替换示例指标和布局。 沿用每张卡片使用一个组件并通过 editable() 设置参数的模式;新增卡片时,请遵循 building-canvases 技能中的“Params”章节。

导入

标准应用外壳使用 React、Quill、Recharts、Lucide 和 Day.js。平台还支持十个可选库,用于特定场景。选择之前,请阅读 references/platform-libraries.md。

PostHog 数据通过 import { ph } from "@posthog/canvas-sdk" 获取——这是平台提供的模块,无需在 dependencies 中添加条目。同一个对象也存在于 window.ph 全局变量中(现有画布通过它访问);新代码优先使用导入方式。

其他裸导入、动态 import()、require()、<script> 标签和远程代码都会导致验证失败。直接网络请求以及外部图片、字体、媒体或框架都需要在 capabilities.network.origins 中声明精确的 HTTPS 来源。它们仅在已发布的画布中可用——编辑模式预览会阻止直接网络访问,无论是否已声明。允许使用来自已声明来源的样式表;远程脚本仍会被阻止,因此应将代码与画布打包。

Quill 组件规则

PostHog 数据看板必须完全由 @posthog/quill 组件构建——不得用原生控件或经过样式处理的 <div> 代替:

  • 下拉菜单/选择器 → Select(绝不使用原生 <select>);按钮 → Button(绝不使用 <button>); 文本字段 → Input/Textarea;复选框 → Checkbox;标签 → Label。
  • 表格 → Table(TableHeader > TableRow > TableHead,然后是 TableBody > TableRow > TableCell); 面板 → Card(CardHeader + CardTitle + CardContent);徽标 → Badge;标题 → Heading;正文 → Text。
  • Card 中的 Table 必须用 <Card size="sm" flush> 包裹 <Table size="sm" fullWidth>。 如果没有 flush,卡片内边距会使表格内缩,导致表头和行无法与卡片边缘对齐。 flush 会移除卡片的区块间距、底部内边距和 CardContent 的行内内边距,但表头仍保留自身的内边距和分隔线。 两处都使用 size="sm",可使表格边缘列与卡片标题对齐。
  • 只允许使用纯布局 <div> 和 recharts 元素作为非 Quill 标签。
  • Quill 基于 Base UI 构建:组合复合部件(Select + SelectTrigger/SelectContent/SelectItem), 使用受控的 value + onValueChange;要替换部件的元素,请使用 render 属性 (例如 <PopoverTrigger render={<Button …/>} />),而不是将其包裹起来。
  • Quill 组件已经应用主题样式——绝不要用 Tailwind 类或内联 style 重新设置其样式; 应使用它们的 variant/size 属性。将布局工具类(flex、grid、gap-4、p-4)放在你自己的 包装 <div> 上。
  • 按钮:默认使用 variant="outline";仅主要操作使用 variant="primary"。

样式与主题

  • 为画布最外层元素添加 min-h-screen(min-height: 100vh),使其填满 iframe 视口,并在内容需要时继续增高。 不要在此处使用 h-screen:固定的视口高度会限制 flex 列,因此高子元素会被压缩并裁切,而不是滚动。 也不要在此处使用 h-full:已发布画布的 artifact 外壳不会为其 html、body 和 #root 元素设置明确高度,因此根元素的百分比高度会收缩为内容高度。
  • 根元素不需要 overflow-y-auto:一旦它的高度超过视口,iframe 自身的文档就会滚动。
  • min-height 根元素并不是确定高度,因此直接子元素上的 h-full 仍会收缩为内容高度。 当子元素必须填满一个盒子时,为中间包装元素设置明确高度(h-[280px])。
  • 使用 Tailwind 工具类和 Quill 组件设置样式;仅对真正动态的运行时值使用内联 style (固定尺寸使用 h-[280px] 这类任意值工具类)。
  • 编写具体的界面文案。完成的画布中绝不要使用 lorem ipsum 或占位标签。
  • 画布遵循用户的 PostHog 主题;文档根元素上的 .dark 类会在运行时切换主题。 颜色只能使用设计令牌工具类:表面使用 bg-background bg-card bg-muted bg-primary bg-success bg-warning bg-info bg-destructive;文本使用 text-foreground text-muted-foreground text-card-foreground;边框使用 border-border。绝不要使用硬编码的十六进制颜色或仅适用于浅色主题的颜色。
  • 状态令牌与常见约定相反:裸令牌(bg-success)是浅色背景填充,-foreground(text-success-foreground)是清晰易读的强调色。彩色文本或图标始终使用 -foreground 工具类;填充式徽标应搭配 bg-success text-success-foreground。 对于增减变化,优先使用 Quill 的 Badge(variant="success"/"destructive"),避免手动挑选颜色。
  • 画布中未定义 bg-secondary、text-secondary、bg-accent 和 bg-popover;请避免使用。
  • 绝不要在样式表或 <style> 块中声明与平台令牌同名的 CSS 变量(--background、--border、--card、--chrome、--input、--muted、--primary、--fill-*)。 Quill 会在每个元素上设置这些变量,因此你的值永远不会生效,文本还可能变得难以辨认。 请为自定义变量添加前缀(--doc-muted);验证会通过 platform_token_redeclared 拒绝变量名冲突。
  • recharts 的描边和填充使用令牌 CSS 变量(stroke="var(--primary)",网格线和坐标轴使用 var(--border)/var(--muted-foreground))。
  • 部分 recharts 默认样式是为浅色主题硬编码的,在深色画布中会显示异常。平台样式表会修正这些问题,因此不要在画布代码中自行处理。饼图扇区描边就是一例:recharts 会为每个扇区添加白色描边,而样式表会移除描边。堆叠条形图各分段之间的抗锯齿接缝也是一例,默认工具提示也同样如此;样式表会反转工具提示的颜色,使其与页面形成对比,确保文本始终满足对比度要求。直接写 <Tooltip /> 即可。
  • 在 JSX 中将 Unicode 字符(弯引号、省略号、箭头、表情符号)写成字面字符 — JSX 文本中的 \uXXXX 转义会原样显示。

加载、错误和空状态

加载或刷新时,每个数据点都在自己的 Card 中显示骨架屏:文本或数字值使用 SkeletonText (匹配 lines 和文本大小 className),区块或图表使用 Skeleton。

渐进式渲染——每个查询都管理自己的加载状态。外框(标题、日期选择器、内部带有骨架屏的卡片框架)立即渲染,挂载时并发触发每个独立查询,每张卡片在自己的查询完成时立即将骨架屏替换为数据,因此缓慢的查询只会延迟它自己的卡片。切勿用一个共享的 loading 标志或跨独立查询的 Promise.all 来控制整个画布——这会让最快的指标也要等最慢的查询。刷新时,将每个区块的加载状态重新设为 true;切勿显示空白或跳动的布局。首屏不可见的内容(未激活的标签页、折叠的区块、下钻视图)应等到用户将其显示后再发起查询。

查询失败和结果为空是两种不同状态——切勿让一种状态渲染成另一种。每个 ph.query/ph.loadInsight 上的 .catch 都必须设置错误状态,并以可见形式呈现(错误消息和一个连接到刷新 nonce 的 Retry 按钮,参照起始脚手架),不能悄悄退化为零值、空图表或“暂无数据”消息。悄悄吞掉错误的查询,会让真实故障(缺少表、身份验证失败、查询错误)看起来像是缺少数据。只有查询成功但没有行时,才显示空状态。

数据产品模式

将这些模式视为起始样式,并根据请求和可用数据进行调整。

产品仪表板
  • 使用经过验证的 PostHog 数据构建实时看板,切勿使用静态样例。
  • 先显示 Heading,然后使用响应式网格展示精简的 Card KPI、趋势图和实用的明细表。
  • 存在有意义的比较时段时,为 KPI 显示 Badge 差值。
  • 时间序列使用 LineChart,离散类别使用 BarChart。不要将每个结果都转换为表格。
  • 为每个 KPI、图表和表格分别设置加载、空和错误状态。
  • 确保每个数值都可验证:由 insight 支撑的卡片应提供“在 PostHog 中查看”入口,打开其已保存的 insight(使用 ph.openExternal 和由 generate-app-url 生成的网址);临时 ph.query 卡片应提供“查看查询” Dialog 或 Collapsible,展示实际运行的查询——参见 querying-canvas-data 中的“可验证性”。
网站分析看板

当请求或旧版请求模式指定 web-analytics 时,使用以下布局:

  1. 将访客数、页面浏览量、会话数、会话时长和跳出率作为 KPI 卡片展示,并与前一个等长时段进行比较,显示差值。
  2. 绘制随时间变化的独立访客数;有比较数据时,用第二条线显示前一个时段。
  3. 下方显示精简表格,列出热门路径、流量来源或渠道、设备和地理位置。
  4. 为国家加上国旗 emoji。只有在可用数据表明有用时,才添加留存或活跃时段视图。

使用 querying-canvas-data 中所述的网站分析查询类型;不要在 HogQL 中重新实现跳出率、会话划分、归因或独立访客数。为展示而格式化较大的数值,例如 236K,同时保留原始值用于计算和无障碍标签。

交互式探索器

为每个维度、事件或日期选项使用受控的 Quill 输入控件。保持结果集较小,并在控件发生变化时刷新所有依赖的查询。

检查清单或运行手册

对于检查清单、QA 运行手册、发布计划、入门流程,或任何供人逐步完成并勾选的步骤列表,请从references/checklist-example.md中的完整且经过验证的项目开始。其关键部分——与组件分离的类型化内容模块、每个步骤各自共享的 ph.state 键、带防抖且与状态并行的 ref 更新路径、每个步骤的预期结果,以及可见的加载/保存失败状态——都是即兴处理时容易出问题的地方。保留这些部分,只替换内容。

日期范围

数据面板应自行管理日期控件——在 Popover 内渲染 Quill 的 DateTimePicker(绝不可使用自定义 Select 或原生日期输入框),并以 Quill 的 Button 作为触发器。PopoverContent 的 className 必须严格设为 "w-auto p-0",且不得在 DateTimePicker 上添加 value/onApply/onCancel 以外的属性(它会自行调整尺寸;不要传入 compact 或宽度)。窗口变化时重新运行每个查询——请参阅 querying-canvas-data 技能,了解如何将其传入 dateRange。

状态与操作

跨重新加载持久化值(ph.state,包括用户/共享作用域),以及通过按钮向 PostHog 写入内容(ph.actions.invoke,例如提交任务或注释;或 ph.tools.call,例如更改功能标志的推出比例),各自都有 API 合约、能力声明和手势规则——使用前请阅读 querying-canvas-data 技能中的“运行时内存”“PostHog 写入”和“PostHog MCP 工具”部分。将操作绑定到 Button 的 onClick,调用进行期间禁用按钮,并渲染返回的错误(这些操作会实际写入 PostHog,且由服务器端进行限流)。

评论

支持 Markdown